From ce50ca62010fa6bb4af9c57daa088dd5e339455b Mon Sep 17 00:00:00 2001 From: Stephen Lee Date: Mon, 2 Jan 2017 22:45:37 +0800 Subject: [PATCH 1/7] Added the HTTP request method: PUT,DELETE,HEAD,OPTIONS to Http.php --- Protocols/Http.php | 53 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/Protocols/Http.php b/Protocols/Http.php index ebe726c3c..30c3ba918 100644 --- a/Protocols/Http.php +++ b/Protocols/Http.php @@ -21,6 +21,12 @@ */ class Http { + /** + * The supported HTTP methods + * @var array + */ + public static $methods = array('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'); + /** * Check the integrity of the package. * @@ -40,23 +46,36 @@ public static function input($recv_buffer, TcpConnection $connection) } list($header,) = explode("\r\n\r\n", $recv_buffer, 2); - if (0 === strpos($recv_buffer, "POST")) { - // find Content-Length - $match = array(); - if (preg_match("/\r\nContent-Length: ?(\d+)/i", $header, $match)) { - $content_length = $match[1]; - return $content_length + strlen($header) + 4; - } else { - return 0; - } - } elseif (0 === strpos($recv_buffer, "GET")) { - return strlen($header) + 4; - } else { + $method = substr($header, 0, strpos($header, ' ')); + + if(in_array($method, static::$methods)) { + return static::getRequestSize($header, $method); + }else{ $connection->send("HTTP/1.1 400 Bad Request\r\n\r\n", true); return 0; } } + /** + * Get whole size of the request + * includes the request headers and request body. + * @param string $header The request headers + * @param string $method The request method + * @return integer + */ + protected static function getRequestSize($header, $method) + { + if($method=='GET') { + return strlen($header) + 4; + } + $match = array(); + if (preg_match("/\r\nContent-Length: ?(\d+)/i", $header, $match)) { + $content_length = isset($match[1]) ? $match[1] : 0; + return $content_length + strlen($header) + 4; + } + return 0; + } + /** * Parse $_POST、$_GET、$_COOKIE. * @@ -144,10 +163,18 @@ public static function decode($recv_buffer, TcpConnection $connection) } else { parse_str($http_body, $_POST); // $GLOBALS['HTTP_RAW_POST_DATA'] - $GLOBALS['HTTP_RAW_POST_DATA'] = $http_body; + $GLOBALS['HTTP_RAW_REQUEST_DATA'] = $GLOBALS['HTTP_RAW_POST_DATA'] = $http_body; } } + if ($_SERVER['REQUEST_METHOD'] === 'PUT') { + $GLOBALS['HTTP_RAW_REQUEST_DATA'] = $http_body; + } + + if ($_SERVER['REQUEST_METHOD'] === 'DELETE') { + $GLOBALS['HTTP_RAW_REQUEST_DATA'] = $http_body; + } + // QUERY_STRING $_SERVER['QUERY_STRING'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY); if ($_SERVER['QUERY_STRING']) { From 1d27cfa43364db53202415e93e7d3178faa1ed8d Mon Sep 17 00:00:00 2001 From: Joanne Date: Fri, 13 Jan 2017 15:45:32 +0100 Subject: [PATCH 2/7] Check if $fd is null before call cancelTimer Fix error: "Argument 1 passed to React\EventLoop\StreamSelectLoop::cancelTimer() must implement interface React\EventLoop\Timer\TimerInterface, null given, called in workerman/Events/React.php on line 90" --- Events/React.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Events/React.php b/Events/React.php index 3b66bde80..be8c87fb7 100644 --- a/Events/React.php +++ b/Events/React.php @@ -87,7 +87,9 @@ public function del($fd, $flag) return $this->_loop->removeSignal($fd); case EventInterface::EV_TIMER: case EventInterface::EV_TIMER_ONCE; - return $this->_loop->cancelTimer($fd); + if ($fd !== null){ + return $this->_loop->cancelTimer($fd); + } } return false; } From f31dfd214f09fd4b3b757c2b861f6f31e8ec86a1 Mon Sep 17 00:00:00 2001 From: walkor Date: Wed, 25 Jan 2017 19:08:22 +0800 Subject: [PATCH 3/7] support ssl --- Worker.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Worker.php b/Worker.php index 240a60776..524e42cec 100644 --- a/Worker.php +++ b/Worker.php @@ -411,10 +411,7 @@ class Worker 'tcp' => 'tcp', 'udp' => 'udp', 'unix' => 'unix', - 'ssl' => 'tcp', - 'sslv2' => 'tcp', - 'sslv3' => 'tcp', - 'tls' => 'tcp' + 'ssl' => 'tcp' ); /** @@ -1408,7 +1405,6 @@ public function listen() // Autoload. Autoloader::setRootPath($this->_autoloadRootPath); - $local_socket = $this->_socketName; // Get the application layer communication protocol and listening address. list($scheme, $address) = explode(':', $this->_socketName, 2); // Check application layer protocol class. @@ -1425,11 +1421,15 @@ public function listen() } } } - $local_socket = $this->transport . ":" . $address; + if (!isset(self::$_builtinTransports[$this->transport])) { + throw new \Exception('Bad worker->transport ' . var_export($this->transport, true)); + } } else { - $this->transport = self::$_builtinTransports[$scheme]; + $this->transport = $scheme; } + $local_socket = self::$_builtinTransports[$this->transport] . ":" . $address; + // Flag. $flags = $this->transport === 'udp' ? STREAM_SERVER_BIND : STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; $errno = 0; @@ -1445,8 +1445,12 @@ public function listen() throw new Exception($errmsg); } + if ($this->transport === 'ssl') { + stream_socket_enable_crypto($this->_mainSocket, false); + } + // Try to open keepalive for tcp and disable Nagle algorithm. - if (function_exists('socket_import_stream') && $this->transport === 'tcp') { + if (function_exists('socket_import_stream') && self::$_builtinTransports[$this->transport] === 'tcp') { $socket = socket_import_stream($this->_mainSocket); @socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1); @socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1); @@ -1575,6 +1579,7 @@ public function acceptConnection($socket) $this->connections[$connection->id] = $connection; $connection->worker = $this; $connection->protocol = $this->protocol; + $connection->transport = $this->transport; $connection->onMessage = $this->onMessage; $connection->onClose = $this->onClose; $connection->onError = $this->onError; From 6ba6d72fa05a97c32b1c8995db50aca28c3ca2fd Mon Sep 17 00:00:00 2001 From: walkor Date: Wed, 25 Jan 2017 19:10:05 +0800 Subject: [PATCH 4/7] support ssl --- Connection/TcpConnection.php | 52 +++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/Connection/TcpConnection.php b/Connection/TcpConnection.php index f63afa1ef..0083e4690 100644 --- a/Connection/TcpConnection.php +++ b/Connection/TcpConnection.php @@ -107,6 +107,13 @@ class TcpConnection extends ConnectionInterface */ public $protocol = null; + /** + * Transport (tcp/udp/unix/ssl). + * + * @var string + */ + public $transport = 'tcp'; + /** * Which worker belong to. * @@ -206,6 +213,13 @@ class TcpConnection extends ConnectionInterface */ protected $_isPaused = false; + /** + * SSL handshake completed or not + * + * @var bool + */ + protected $_sslHandshakeCompleted = false; + /** * Construct. * @@ -236,6 +250,10 @@ public function __construct($socket, $remote_address = '') */ public function send($send_buffer, $raw = false) { + if ($this->_status === self::STATUS_CLOSING || $this->_status === self::STATUS_CLOSED) { + return false; + } + // Try to call protocol::encode($send_buffer) before sending. if (false === $raw && $this->protocol) { $parser = $this->protocol; @@ -245,7 +263,9 @@ public function send($send_buffer, $raw = false) } } - if ($this->_status === self::STATUS_INITIAL || $this->_status === self::STATUS_CONNECTING) { + if ($this->_status !== self::STATUS_ESTABLISH || + ($this->transport === 'ssl' && $this->_sslHandshakeCompleted !== true) + ) { if ($this->_sendBuffer) { if ($this->bufferIsFull()) { self::$statistics['send_fail']++; @@ -255,10 +275,9 @@ public function send($send_buffer, $raw = false) $this->_sendBuffer .= $send_buffer; $this->checkBufferWillFull(); return null; - } elseif ($this->_status === self::STATUS_CLOSING || $this->_status === self::STATUS_CLOSED) { - return false; } + // Attempt to send data directly. if ($this->_sendBuffer === '') { $len = @fwrite($this->_socket, $send_buffer); @@ -366,6 +385,33 @@ public function resumeRecv() */ public function baseRead($socket, $check_eof = true) { + // SSL handshake. + if ($this->transport === 'ssl' && $this->_sslHandshakeCompleted !== true) { + stream_set_blocking($socket, true); + stream_set_timeout($socket, 1); + $ret = stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_SSLv23_SERVER); + if(!$ret) { + echo new \Exception('ssl handshake fail, stream_socket_enable_crypto return ' . var_export($ret, true)); + return $this->destroy(); + } + if (isset($this->onSslHandshake)) { + try { + call_user_func($this->onSslHandshake, $this); + } catch (\Exception $e) { + self::log($e); + exit(250); + } catch (\Error $e) { + self::log($e); + exit(250); + } + } + $this->_sslHandshakeCompleted = true; + if ($this->_sendBuffer) { + Worker::$globalEvent->add($socket, EventInterface::EV_WRITE, array($this, 'baseWrite')); + } + return; + } + $buffer = fread($socket, self::READ_BUFFER_SIZE); // Check connection closed. From d466c0f4b37c6cfb4f27c69b158175c7e7ccc24c Mon Sep 17 00:00:00 2001 From: walkor Date: Thu, 2 Feb 2017 10:52:58 +0800 Subject: [PATCH 5/7] Update Worker.php --- Worker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Worker.php b/Worker.php index 524e42cec..08e7dd6a8 100644 --- a/Worker.php +++ b/Worker.php @@ -33,7 +33,7 @@ class Worker * * @var string */ - const VERSION = '3.3.6'; + const VERSION = '3.3.7'; /** * Status starting. From 40dd0d10ff379f2bf2eeb472a7cafd6263796b5c Mon Sep 17 00:00:00 2001 From: walkor Date: Tue, 7 Feb 2017 15:03:07 +0800 Subject: [PATCH 6/7] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 17b687dec..ced289d6d 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,9 @@ $ws_worker = new Worker("websocket://0.0.0.0:2346"); // 4 processes $ws_worker->count = 4; +// WebSockets over SSL (wss) +//$ws_worker->transport = 'ssl'; + // Emitted when new connection come $ws_worker->onConnect = function($connection) { @@ -64,6 +67,9 @@ $http_worker = new Worker("http://0.0.0.0:2345"); // 4 processes $http_worker->count = 4; +// HTTP over SSL (https) +//$ws_worker->transport = 'ssl'; + // Emitted when data received $http_worker->onMessage = function($connection, $data) { From d131cc357a853a1b95979e137e4352cefd48a283 Mon Sep 17 00:00:00 2001 From: walkor Date: Tue, 7 Feb 2017 15:03:48 +0800 Subject: [PATCH 7/7] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index ced289d6d..17b687dec 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,6 @@ $ws_worker = new Worker("websocket://0.0.0.0:2346"); // 4 processes $ws_worker->count = 4; -// WebSockets over SSL (wss) -//$ws_worker->transport = 'ssl'; - // Emitted when new connection come $ws_worker->onConnect = function($connection) { @@ -67,9 +64,6 @@ $http_worker = new Worker("http://0.0.0.0:2345"); // 4 processes $http_worker->count = 4; -// HTTP over SSL (https) -//$ws_worker->transport = 'ssl'; - // Emitted when data received $http_worker->onMessage = function($connection, $data) {