php websocket无法使用ssl

时间:2017-05-31 19:25:35

标签: php ssl websocket

我有一个PHP脚本,可以创建和运行websocket。

$wmdir=dirname(__FILE__);   
$privdir=dirname(__DIR__);
    /////////// ======== FUNCTIONS ========== /////////////////
function customError2($errno, $errstr, $errfile, $errline)  { 
    $theerror= "Error [$errno] in $errfile on line $errline : $errstr ";         
} 
function fatalHandler() {
    $error = error_get_last();
    if($error)  {
       wm_onerror('FATAL: '.$error["type"].$error["message"].$error["file"].$error["line"] )  ;}
}
set_error_handler("customError2");               
register_shutdown_function("fatalHandler");

function wmlog($log){
   global $privdir; 
   $f=fopen($privdir.'/logs/SocketLog'.date("d_m_y").'.log','a'); 
   fwrite($f, PHP_EOL.date("h:i:s").'LOG: '.$log); 
   fclose($f);  
}
include_once($wmdir.'/settings.php');    
include_once($wmdir.'/class/Core.php'); 
include_once($wmdir.'/ajax/intocf.php');

    //////////////    V A R S /////////////////

$host = 'myhost.net';   $port = $argv[1];     $wscode=$argv[2]; 
$uid=$argv[3] ;         $cid=$argv[4];        $ctype=$argv[5];
$mid=$argv[6];          $null = NULL;         $puid='u'.$uid;
$pwid=0;                 $uhere=1;            $uherewas=time(); 
$a_ignored=array();    $a_pids=array();       $a_viab=array();
$a_viaa=array();       $a_bora=array();       $a_ka=array(); 
$a_si=array(); 

$q_cd="SELECT * FROM chats".$mid." WHERE c_id= $cid LIMIT 1"; 
$c_cd=new Core('wmc');    $c_cd->query($q_cd);    $a_cd=$c_cd->row(); 

                  // S S L    C E R T I F I C A T E   ///
$ssl_cert = $wmdir.'/ssl/cert.pem';   $ssl_pass='wnet';   
if(!$context = stream_context_create()){
    wmlog("ERROR creating context") ;
}else{
     wmlog("context created") ;
}
stream_context_set_option($context, 'ssl', 'local_cert', $ssl_cert);
stream_context_set_option($context, 'ssl', 'passphrase', $ssl_pass);
stream_context_set_option($context, 'ssl', 'allow_self_signed', false);
stream_context_set_option($context, 'ssl', 'verify_peer', true); 

         // create SOCKET //
if(!$socket = stream_socket_server('ssl://'.$host.':'.$port, $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context)){
   wmlog("ERROR creating socket") ;
}else{    
   wmlog("socket created") ;
}
$clients = array($socket);//create & add listning socket to the list
$sk='';         
foreach($clients as $k=>$v){
    $sk.=$k.',';
}
$a_ictmp=array( 'chat_id'=>$cid,  'mid'=>$mid);
    //   LET DB KNOW that User is back ///
$a_ub=array('action'=>'ub', 'chat_id'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
$a_msdb=intochat($a_ub);   // LET DB KNOW THAT USER IS BACK

  ////  STARTING LOOP //////
while (true) {//manage multiple connections
    $changed = $clients;
    stream_select($changed, $null, $null, 0, 10);

        ///////// AD NEW SOCKET ///////
    if (in_array($socket, $changed)) {//check for new socket
        $sk='';         
        foreach($clients as $k=>$v){
            $sk.=$k.',';
        }           
        $socket_new = stream_socket_accept($socket);   
        $header = fread($socket_new, 1024);    
        $a_h=explode(PHP_EOL, $header);   
        $s_get=$a_h[0];                 $a_header=array();    
        $a_pv=explode('_', $s_get);     $pid=$a_pv[1].$a_pv[2];
        $wscode=$a_pv[3];               $a_bora[$pid]=$a_pv[4];
        if($a_pv[4]=='b'){
           $a_viab[]=$pid;
        }elseif($a_pv[4]=='a'){
            $a_viaa[]=$pid;
        }
        $clients[$pid] = $socket_new; 
        perform_handshaking($header, $socket_new, $host, $port);//-
        $peer = stream_socket_get_name($socket_new, true); //-
        $found_socket = array_search($socket, $changed);//make room for new socket
        unset($changed[$found_socket]);

            ///// authenticate person trying to make connection  ///////
            if(in_array($pid, $a_pids)){ // person already in a socket
                wmlog('CODES: '.$a_pids[$pid].' | '.$wscode); //wmlog('Socket ACCEPTED'); 
                if($a_pids[$pid]!=$wscode){unset($clients[$pid]) ;} 
            }else{  // person not in a sockets yet so check the code
                $con=0; 
                if($a_pv[1]=='u'){// WIZARD connecting to socket
                    if($a_pv[2]==$uid && $a_pv[3]==$a_cd['c_wscode']){
                        wmlog('USER '.$uid.' CONNECTED ');   $con=1;
                    }else{  unset($clients[$pid]) ;   wmlog('USER NOT CONNECTED ');  } // NOT allowing connection

                }elseif($a_pv[1]=='w'){// WIZARD CONNECTING 
                    $q_cp="SELECT ucode FROM users_d WHERE u_id = ".$a_pv[2].' LIMIT 1 ';
                    $c_cp=new Core('wmu');   $c_cp->query($q_cp);   $a_wscode=$c_cp->row();    $wsc1=trim($a_wscode['ucode']);
                    if(!empty($a_wscode) && $wsc1==$a_pv[3] && !in_array($pid, $a_ignored)){ 
                          $con=1;   
                    }else{   unset($clients[$pid]) ;    

                }elseif($a_pv[1]=='s'){  // SYSTEM connecting for maintanance etc
                    if($a_pv[3]==$wscode){ // system code is correct 
                        $con=1;
                    }else{  unset($clients[$pid]) ;  wmlog('SYSTEM NOT CONNECTED '); } // 
                }

                if($con==1){$a_ka[$pid]=time();         $a_bora[$pid]=$a_pv[4];   $a_si[$pid]=array('bora'=>$a_pv[4], 'woru'=>$a_pv[1]   ); }

            }// EOF if person not in sockets yet 
            $sk='';         foreach($clients as $k=>$v){$sk.=$k.',';} ;         wmlog('SOCKETS: '.$sk); 
        }// EOF checking new connection 

        //loop through all connected sockets
        foreach ($changed as $key => $changed_socket) { 

            while(fread($changed_socket, $buf, 1024, 0) >= 1){  //-
                wmlog('key: '.$key.' || BORA: '.$a_bora[$key].' || BEFORE UNMASK: '.$buf.' AFTER UNMAS: '.unmask($buf));
                $received_text = unmask($buf);   wmlog('RECEIVED TEXT: '.$received_text); 
                $afterunmasking=($a_bora[$key]=='b')? $buf :  unmask($buf) ; 

                $o_msg = json_decode($afterunmasking);//unmask data  AND json decode 
                            // PUT MESSAGE TO DB ////
              // a_intochat: action, chat_id, bywho, bywho_id, scope, towho, towho_id, data1, time, ctype
                if(is_object($o_msg)){

                    $a_msg = get_object_vars($o_msg);     // convert object to array
                    foreach($a_msg as $k=>$v){wmlog($k.' : '.$v);}   // LOG the message
                    $a_msg['chat_id']=$cid;   $a_msg['ctype']=$ctype;   $a_msg['mid']=$mid;    $a_msg['uid']=$uid;  
                    $action=(isset($a_msg['action']))? $a_msg['action'] : 0 ; 
                    //$operation=(isset($a_msg['operation']))? $a_msg['operation'] : 'ic'; 
                    if(isset($a_msg['method']) && $a_msg['method']=='intochat' ){
                        wmlog('O:INTOCHAT: '.$a_msg['bywho'].' | '.$a_msg['bywho_id'].' | '.$a_msg['action']);
                        if(isset($a_msg['bywho']) && isset($a_msg['bywho_id']) && isset($a_msg['action'])){
                           $t_pid=$a_msg['bywho'].$a_msg['bywho_id'];   $a_ka[$t_pid]=time();  // set keepalive time for this person
                            $a_msdb=intochat($a_msg);          // ADD MESSAGE TO DB AND GET MESSAGES TO SEND BACK
                            $j_msdb=json_encode($a_msdb);    wmlog('MSDB: '.$j_msdb); //  $j_encoded;    
                           if($a_msg['action']=='d'){$ctype='d';   $pwid='w'.$a_msg['towho_id'];   $wid=$a_msg['towho_id']; }   /// chat dedicated
                            if($a_msg['action']=='i' && $a_msg['towho']=='w'){$a_ignored[]='w'.$a_msg['towho_id'];}   /// wizard ignored
                            send_message2($a_msdb);   // send data back to chaters 
                                   /// chat closed or completed
                            if($a_msg['action']=='c'){  $cid=0;  wmlog('CLOSECOMPLETE');    closesocket($port); break 3; } 
                                // EOF if message from chater
                        }
                    }
                    switch ($action) { // ic - intochat ; ka - keepalive ; ul - user loged of
                       case 'ul': // User loged off so letting all know and closing socket 

                             $a_icul=array('action'=>'ul', 'chat_id'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
                             $a_msdb=intochat($a_icul);          // ADD MESSAGE TO DB AND GET MESSAGES TO SEND BACK
                             send_message2($a_msdb);   // send data back to chaters 
                             closesocket($port);   wmlog('user left (loged off)'); 
                             break 4;  

                       case 'al': // ALERT 

                              break ; 

                        case "ka":  /// keep alive from person 
                            $t_pid=$a_msg['bywho'].$a_msg['bywho_id'];   $a_ka[$t_pid]=time();              break;

                       case 'ts': /// TEST   
                           wmlog('testinG: '.$a_msg['t']);   $response=json_encode(array('action'=>'ts','r1'=>1));   
                             send_message($response, 0);
                           break; 

                       default:
                            wmlog('action UNKNOWN: '.$action);
                    }

                }
                break 2; //exist this loop
            }

            $buf = fread($changed_socket, 1024, PHP_NORMAL_READ);//-

            //////////////  SOMEBODY D I S C O N N E T E D ///////////////////
            if ($buf === false) { // check disconnected client
                // remove client from $clients array
                $found_socket = array_search($changed_socket, $clients);            
                unset($clients[$found_socket]);                                     wmlog('DISCONNECTED: '.$found_socket);

                if($found_socket==$puid){ // its a USER who is DISCONNETED
                    $a_icul=array('action'=>'ul', 'chat_id'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
                     $a_msdb=intochat($a_icul);        
                     send_message2($a_msdb);   // send data back to chaters 
                     closesocket($port);   wmlog('user left (disconnected)'); 
                    break 2; 
                 }elseif((strpos($found_socket, 'w') !== false)){ // WIZARD left 
                    $a_wl=array('action'=>'wl', 'chd'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
                     send_message($a_wl, 0);  

                }

            }
        }
    }

    fclose($socket); //-

    function send_message($msg_b, $a_id=0, $notall=0){ 
        $msg = mask($msg_b);

        global $clients, $uid,   $a_bora;       $a_s=$clients;    unset($a_s[0]);   
        if(!is_array($a_id) && $a_id==0){ wmlog('message sent to everybody');    // send message to everybody
           if(is_array($notall)){ // filter sockets message not to be sent to 
                foreach($notall as $v){unset($a_s[$v]);} // check which 
            }

        }elseif(!is_array($a_id) && $a_id!=0){ wmlog('Sending to single socket '.$a_id);// message to be sent to a single socket ($a_id)
            $a_s=array($a_id=>$clients[$a_id]);
        }else{ // send message to selected sockets 
            $a_s=array();   //socket_write($clients[$id],$msg,strlen($msg));  
            foreach($a_id as $id){  $a_s[$id]= $clients[$id];   }
        }
        foreach($a_s as $sid=>$soc){
            wmlog('M to be  Sent to '.$sid);
            if($a_bora[$sid]=='a'){$msg=mask($msg_b);}else{$msg=$msg_b;} /// check if to mask or not to mask 
            if(strpos($sid,'s')===false){ wmlog('M Sent to '.$sid); // exclude 0 and system socket clients  

                fwrite($clients[$sid],$msg);//-
            }

       }
        unset($a_s);      return true;
    } // EOF send_message F 

    function send_message2($a_msdb){ wmlog('F: send_message2'); 
        global $clients, $uid, $ctype, $cid, $pwid, $a_bora;   $a_not_all=array();    $a_s=$clients;   unset($a_s[0]); 
        if(isset($a_msdb['some']) && is_array($a_msdb['some']) ){ // send message to some users
           foreach($a_msdb['some'] as $k=>$v){      wmlog('SENDING TO '.$k.' : '.implode(' , ', $v)); 
                if($a_bora[$k]=='a'){$msg = mask(json_encode($v));}else{$msg = json_encode($v);}
                $a_not_all[]=$k;            
                if(isset($a_s[$k])){

                  fwrite($a_s[$k],$msg); 
                  unset($a_s[$k]);  }
            }
        }
        if(isset($a_msdb['all']) && is_array($a_msdb['all']) ){ // send message to all other if needs be  

            foreach($a_s as $sid=>$soc){  
               if($a_bora[$sid]=='a'){$msg = mask(json_encode($a_msdb['all']));}else{$msg = json_encode($a_msdb['all']);}

                fwrite($clients[$sid], $msg);//-
            } 
        }
        unset($a_s);        return true;
    }

    //Unmask incoming framed message
    function unmask($text) {
        $length = ord($text[1]) & 127;
        if($length == 126) {        $masks = substr($text, 4, 4);       $data = substr($text, 8);
        }elseif($length == 127) {       $masks = substr($text, 10, 4);      $data = substr($text, 14);
        }else{                          $masks = substr($text, 2, 4);       $data = substr($text, 6);       }
        $text = "";
        for ($i = 0; $i < strlen($data); ++$i) {        $text .= $data[$i] ^ $masks[$i%4];  }
        return $text;
    }

    //Encode message for transfer to client.
    function mask($text){
        $b1 = 0x80 | (0x1 & 0x0f);      $length = strlen($text);
        if($length <= 125){                         $header = pack('CC', $b1, $length);          }
        elseif($length > 125 && $length < 65536){      $header = pack('CCn', $b1, 126, $length);    }
        elseif($length >= 65536) {                    $header = pack('CCNN', $b1, 127, $length);   }
        return $header.$text;         }

    //handshake new client.
    function perform_handshaking($receved_header,$client_conn, $host, $port){
        $headers = array();     $lines = preg_split("/\r\n/", $receved_header);
        foreach($lines as $line)    {
            $line = chop($line);
            if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)){           $headers[$matches[1]] = $matches[2];        }
        }
        $secKey = $headers['Sec-WebSocket-Key'];
        $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
        //hand shaking header
        $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .  "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" .
        "WebSocket-Origin: $host\r\n" . "WebSocket-Location: ws://$host:$port\r\n". "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
        //-socket_write($client_conn,$upgrade,strlen($upgrade));
        fwrite($client_conn,$upgrade,strlen($upgrade));
    }

    function closesocket($port){
        $q_rw="UPDATE wss SET ws_cid= 0 , ws_mid= 0 , ws_used= 0, wreleasetime= ".time()."  WHERE wport= $port ";
        $c_rw=new Core('wmc');   $c_rw->query($q_rw);   

    }
    wmlog('SOCKET CLOSING - last line');

问题是,当客户端尝试连接到它时出现以下错误,它会失败:
 &#34;第71行/opt/bitnami/apache2/mysite/socket.php中的错误[2]:stream_socket_accept():SSL操作失败,代码为1. OpenSSL错误消息:错误:14094418:SSL例程:ssl3_read_bytes:tlsv1提醒未知的ca&#34;
我用openssl创建了证书 感谢

0 个答案:

没有答案