protected function processRequest($socket) { $raw_request = ""; $connection_time = time(); while (time() < $connection_time + $this->getTimeout()) { // Child: reading $buffer = socket_read($socket, $this->packet_size, PHP_BINARY_READ); if ($buffer === false) { // Child: Error or EOF. Exiting. return false; } else { $raw_request .= $buffer; if ($buffer === "" || strlen($buffer) < $this->packet_size) { $request = new Request($raw_request); $request->document_root = $this->document_root; socket_getpeername($socket, $request->remote_ip); if ($request->isComplete()) { $handler = new $this->handler($request, $this->handler_options); $response = $handler->handle(); socket_write($socket, $response->asString()); $this->logAccess($request, $response); return true; } else { unset($request); } } } } error_log("Request was not complete after connection timeout reached ({$this->getTimeout()} seconds)"); return false; }
public function listen() { if (($ret = socket_listen($this->socket, 5)) < 0) { throw new Zend_Http_Server_Exception("socket_listen() failed: Reason: " . socket_strerror($ret)); } // Listening... while (true) { $sockets = array($this->socket); $client = null; if (socket_select($sockets, $w = NULL, $e = NULL, 0)) { // Waiting for connections... if (($client = socket_accept($this->socket)) < 0) { throw new Zend_Http_Server_Exception("socket_accept() failed: Reason: " . socket_strerror($client)); } } else { // Without this, the server will use 100% of available CPU constantly! usleep(100); // The only sensible place to sleep. Sleep for 0.0001 seconds if no new connections have arrived. Still allows a potential 10000 requests a second :) } // New connection, forking. if ($client) { $pid = pcntl_fork(); if ($pid == -1) { die("Could not fork new process!"); } else { if ($pid) { // print "Storing socket for $pid\n"; $this->connections[$pid] = $client; } else { $raw_request = ""; $i = 1; while ($i < 10) { // print "Read attempt: $i\n"; $i++; // Child: reading $buffer = socket_read($client, 2048, PHP_BINARY_READ); // print strlen( $buffer ) . " bytes read\n"; if ($buffer === false) { // Child: Error or EOF. Exiting. exit; } else { $raw_request .= $buffer; if ($buffer === "" || strlen($buffer) < 2048) { $request = new Request($raw_request); $request->document_root = $this->document_root; socket_getpeername($client, $request->remote_ip); if ($request->isComplete()) { $handler = new $this->handler($request); $response = $handler->handle(); socket_write($client, $response->asString()); print $request->remote_ip . " - - [" . date("d/M/Y:H:i:s O") . "] \"" . $request->method . " " . $request->uri . " " . $request->protocol_version . "\" " . $response->getStatus() . " " . strlen($response->getBody()) . " \"" . trim($request->headers["Referer"]) . "\" \"" . trim($request->headers["User-Agent"]) . "\"\n"; exit; } else { unset($request); } } } } // print "Here!\n"; print "Read more than ten times for request and still incomplete - bailing out"; exit; } } } // Parent: Check for finished children while (($child = pcntl_wait($status, WNOHANG)) > 0) { // print "Closing socket for $child\n"; socket_close($this->connections[$child]); unset($this->connections[$child]); // print "Connection count: " . count( $this->connections ) . "\n"; } } }