Parcourir la source

Merge pull request #299 from ares333/patch

Fix tcp connection lost bug and EV_WRITE register twice bug.
walkor il y a 7 ans
Parent
commit
43f0c542b7
2 fichiers modifiés avec 31 ajouts et 64 suppressions
  1. 17 54
      Connection/AsyncTcpConnection.php
  2. 14 10
      Connection/TcpConnection.php

+ 17 - 54
Connection/AsyncTcpConnection.php

@@ -158,13 +158,12 @@ class AsyncTcpConnection extends TcpConnection
         self::$statistics['connection_count']++;
         $this->maxSendBufferSize        = self::$defaultMaxSendBufferSize;
         $this->_contextOption           = $context_option;
-        static::$connections[$this->id] = $this;
     }
 
     /**
      * Do connect.
      *
-     * @return void 
+     * @return void
      */
     public function connect()
     {
@@ -199,7 +198,7 @@ class AsyncTcpConnection extends TcpConnection
             }
             return;
         }
-        // Add socket to global event loop waiting connection is successfully established or faild. 
+        // Add socket to global event loop waiting connection is successfully established or faild.
         Worker::$globalEvent->add($this->_socket, EventInterface::EV_WRITE, array($this, 'checkConnection'));
         // For windows.
         if(DIRECTORY_SEPARATOR === '\\') {
@@ -228,7 +227,7 @@ class AsyncTcpConnection extends TcpConnection
     /**
      * Get remote address.
      *
-     * @return string 
+     * @return string
      */
     public function getRemoteHost()
     {
@@ -276,14 +275,8 @@ class AsyncTcpConnection extends TcpConnection
      */
     public function checkConnection($socket)
     {
-        // Remove EV_EXPECT for windows.
-        if(DIRECTORY_SEPARATOR === '\\') {
-            Worker::$globalEvent->del($socket, EventInterface::EV_EXCEPT);
-        }
         // Check socket state.
         if ($address = stream_socket_get_name($socket, true)) {
-            // Remove write listener.
-            Worker::$globalEvent->del($socket, EventInterface::EV_WRITE);
             // Nonblocking.
             stream_set_blocking($socket, 0);
             // Compatible with hhvm
@@ -298,14 +291,24 @@ class AsyncTcpConnection extends TcpConnection
             }
 
             // SSL handshake.
-            if ($this->transport === 'ssl' && $this->doSslHandshake($socket)) {
-                $this->_sslHandshakeCompleted = true;
+            if ($this->transport === 'ssl') {
+                $this->_sslHandshakeCompleted = $this->doSslHandshake($socket,true);
+                if(!$this->_sslHandshakeCompleted){
+                    return;
+                }
             }
+            
+            // Remove EV_EXPECT for windows.
+            if(DIRECTORY_SEPARATOR === '\\') {
+                Worker::$globalEvent->del($socket, EventInterface::EV_EXCEPT);
+            }
+            // Remove write listener.
+            Worker::$globalEvent->del($socket, EventInterface::EV_WRITE);
 
             // Register a listener waiting read event.
             Worker::$globalEvent->add($socket, EventInterface::EV_READ, array($this, 'baseRead'));
             // There are some data waiting to send.
-            if ($this->_sendBuffer && $this->transport !== 'ssl') {
+            if ($this->_sendBuffer) {
                 Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite'));
             }
             $this->_status                = self::STATUS_ESTABLISHED;
@@ -335,6 +338,7 @@ class AsyncTcpConnection extends TcpConnection
                     exit(250);
                 }
             }
+            static::$connections[$this->id] = $this;
         } else {
             // Connection failed.
             $this->emitError(WORKERMAN_CONNECT_FAIL, 'connect ' . $this->_remoteAddress . ' fail after ' . round(microtime(true) - $this->_connectStartTime, 4) . ' seconds');
@@ -346,45 +350,4 @@ class AsyncTcpConnection extends TcpConnection
             }
         }
     }
-
-    /**
-     * SSL handshake.
-     *
-     * @param $socket
-     * @return bool
-     */
-    public function doSslHandshake($socket){
-        if (feof($socket)) {
-            $this->destroy();
-            return false;
-        }
-        $ret = stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv2_CLIENT |
-            STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
-        // Negotiation has failed.
-        if(false === $ret) {
-            if (!feof($socket)) {
-                echo "\nSSL Handshake as client fail. \nBuffer:".bin2hex(fread($socket, 8182))."\n";
-            }
-            $this->destroy();
-            return false;
-        } elseif(0 === $ret) {
-            // There isn't enough data and should try again.
-            return false;
-        }
-        if (isset($this->onSslHandshake)) {
-            try {
-                call_user_func($this->onSslHandshake, $this);
-            } catch (\Exception $e) {
-                Worker::log($e);
-                exit(250);
-            } catch (\Error $e) {
-                Worker::log($e);
-                exit(250);
-            }
-        }
-        if ($this->_sendBuffer) {
-            Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite'));
-        }
-        return true;
-    }
 }

+ 14 - 10
Connection/TcpConnection.php

@@ -565,10 +565,14 @@ class TcpConnection extends ConnectionInterface
     {
         // SSL handshake.
         if ($this->transport === 'ssl' && $this->_sslHandshakeCompleted !== true) {
-            if ($this->doSslHandshake($socket)) {
+            if ($this->doSslHandshake($socket,false)) {
                 $this->_sslHandshakeCompleted = true;
+                if ($this->_sendBuffer) {
+                    Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite'));
+                }
+            }else{
+                return;
             }
-            return;
         }
 
         $buffer = @fread($socket, self::READ_BUFFER_SIZE);
@@ -711,17 +715,21 @@ class TcpConnection extends ConnectionInterface
      * @param $socket
      * @return bool
      */
-    public function doSslHandshake($socket){
+    public function doSslHandshake($socket,$async){
         if (feof($socket)) {
             $this->destroy();
             return false;
         }
-        $ret = stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv2_SERVER |
-            STREAM_CRYPTO_METHOD_SSLv23_SERVER);
+        if($async){
+            $type=STREAM_CRYPTO_METHOD_SSLv2_CLIENT | STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
+        }else{
+            $type=STREAM_CRYPTO_METHOD_SSLv2_SERVER | STREAM_CRYPTO_METHOD_SSLv23_SERVER;
+        }
+        $ret = stream_socket_enable_crypto($socket, true, $type);
         // Negotiation has failed.
         if(false === $ret) {
             if (!feof($socket)) {
-                echo "\nSSL Handshake fail. \nBuffer:".bin2hex(fread($socket, 8182))."\n";
+                echo "\nSSL Handshake fail as ".($async?'client':'server').". \nBuffer:".bin2hex(fread($socket, 8182))."\n";
             }
             $this->destroy();
             return false;
@@ -740,10 +748,6 @@ class TcpConnection extends ConnectionInterface
                 exit(250);
             }
         }
-
-        if ($this->_sendBuffer) {
-            Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite'));
-        }
         return true;
     }