|
5 | 5 |
|
6 | 6 | class Server
|
7 | 7 | {
|
8 |
| - public $app, $reload = true; |
9 |
| - private $host, $port, $running, $in, $out; |
10 |
| - |
11 |
| - public function __construct($host = '0.0.0.0', $port = 9393, $app = 'config.php') |
12 |
| - { |
13 |
| - declare(ticks=1); |
14 |
| - $this->host = $host; |
15 |
| - $this->port = $port; |
16 |
| - $this->app = $app; |
17 |
| - $this->in = array(); |
18 |
| - $this->out = array(); |
19 |
| - |
20 |
| - \Rackem::$handler = new \Rackem\Handler\Rackem(); |
21 |
| - } |
22 |
| - |
23 |
| - public function start() |
24 |
| - { |
25 |
| - $this->init(); |
26 |
| - $this->running = true; |
27 |
| - |
28 |
| - while($this->step()) |
29 |
| - { |
30 |
| - |
31 |
| - } |
32 |
| - } |
| 8 | + public $app, $reload = true; |
| 9 | + private $host, $port, $running, $in, $out; |
33 | 10 |
|
34 |
| - public function step() |
35 |
| - { |
36 |
| - $read = array(); |
37 |
| - $write = array(); |
38 |
| - $except = null; |
39 |
| - |
40 |
| - foreach($this->in as $id => $conn) |
| 11 | + public function __construct($host = '0.0.0.0', $port = 9393, $app = 'config.php') |
41 | 12 | {
|
42 |
| - if(!$conn->is_request_complete()) |
43 |
| - { |
44 |
| - $read[] = $conn->socket; |
45 |
| - }else |
46 |
| - { |
47 |
| - if(strlen($conn->buffer) || $conn->is_response_complete()) $write[] = $conn->socket; |
48 |
| - else $read[] = $conn->stream; |
49 |
| - } |
| 13 | + declare(ticks=1); |
| 14 | + $this->host = $host; |
| 15 | + $this->port = $port; |
| 16 | + $this->app = $app; |
| 17 | + $this->in = array(); |
| 18 | + $this->out = array(); |
50 | 19 | }
|
51 |
| - $read[] = $this->master; |
52 |
| - |
53 |
| - if(@stream_select($read, $write, $except, null) < 1) return $this->running; |
54 | 20 |
|
55 |
| - if(in_array($this->master, $read)) |
| 21 | + public function start() |
56 | 22 | {
|
57 |
| - $client = stream_socket_accept($this->master); |
58 |
| - $this->in[(int)$client] = new Connection($client); |
| 23 | + $this->init(); |
| 24 | + $this->running = true; |
59 | 25 |
|
60 |
| - $key = array_search($this->master, $read); |
61 |
| - unset($read[$key]); |
| 26 | + while($this->step()) { /*BOOM*/ } |
62 | 27 | }
|
63 | 28 |
|
64 |
| - foreach($read as $stream) |
| 29 | + public function step() |
65 | 30 | {
|
66 |
| - if(isset($this->out[(int)$stream])) $this->out[(int)$stream]->read(); |
67 |
| - else $this->read_request($stream); |
| 31 | + $read = array(); |
| 32 | + $write = array(); |
| 33 | + $except = null; |
| 34 | + |
| 35 | + foreach($this->in as $id => $conn) { |
| 36 | + if(!$conn->is_request_complete()) { |
| 37 | + $read[] = $conn->socket; |
| 38 | + } else { |
| 39 | + if($conn->socket) $write[] = $conn->socket; |
| 40 | + if(!$conn->is_response_complete()) $read[] = $conn->stream; |
| 41 | + } |
| 42 | + } |
| 43 | + $read[] = $this->master; |
| 44 | + |
| 45 | + if(@stream_select($read, $write, $except, null) < 1) return $this->running; |
| 46 | + |
| 47 | + if(in_array($this->master, $read)) { |
| 48 | + $client = stream_socket_accept($this->master); |
| 49 | + $this->in[(int)$client] = new Connection($client); |
| 50 | + |
| 51 | + $key = array_search($this->master, $read); |
| 52 | + unset($read[$key]); |
| 53 | + } |
| 54 | + |
| 55 | + foreach($read as $stream) { |
| 56 | + if(isset($this->out[(int)$stream])) $this->out[(int)$stream]->read(); |
| 57 | + else $this->read_request($stream); |
| 58 | + } |
| 59 | + |
| 60 | + foreach($write as $client) $this->write($client); |
| 61 | + |
| 62 | + return $this->running; |
68 | 63 | }
|
69 | 64 |
|
70 |
| - foreach($write as $client) $this->write($client); |
71 |
| - |
72 |
| - return $this->running; |
73 |
| - } |
| 65 | + public function read_request($socket) |
| 66 | + { |
| 67 | + $conn = $this->in[(int)$socket]; |
| 68 | + $data = @fread($socket, 30000); |
74 | 69 |
|
75 |
| - public function read_request($socket) |
76 |
| - { |
77 |
| - $conn = $this->in[(int)$socket]; |
78 |
| - $data = @fread($socket, 30000); |
| 70 | + if($data === false || $data == '') return $this->close_connection($conn); |
79 | 71 |
|
80 |
| - if($data === false || $data == '') return $this->close_connection($conn); |
| 72 | + $conn->data($data); |
| 73 | + if($conn->is_request_complete()) { |
| 74 | + $conn->process($this->app); |
| 75 | + $this->out[(int)$conn->stream] = $conn; |
| 76 | + } |
| 77 | + } |
81 | 78 |
|
82 |
| - $conn->data($data); |
83 |
| - if($conn->is_request_complete()) |
| 79 | + public function write($socket) |
84 | 80 | {
|
85 |
| - $stream = $conn->process($this->app); |
86 |
| - $this->out[(int)$stream] = $conn; |
| 81 | + $conn = $this->in[(int)$socket]; |
| 82 | + |
| 83 | + $bytes = @fwrite($socket, $conn->buffer); |
| 84 | + if($bytes === false) return $this->close_connection($conn); |
| 85 | + |
| 86 | + $conn->bytes_written += $bytes; |
| 87 | + $conn->buffer = substr($conn->buffer, $bytes); |
| 88 | + if($conn->bytes_written < $conn->response_length) return; |
| 89 | + if($conn->is_response_complete()) $this->complete_response($conn); |
87 | 90 | }
|
88 |
| - } |
89 | 91 |
|
90 |
| - public function write($socket) |
91 |
| - { |
92 |
| - $conn = $this->in[(int)$socket]; |
| 92 | + public function complete_response($conn) |
| 93 | + { |
| 94 | + fwrite(STDERR, $this->log_request($conn)); |
| 95 | + if($conn->get_header('Connection') === 'close' || $conn->version !== 'HTTP/1.1') { |
| 96 | + $this->close_connection($conn); |
| 97 | + } else { |
| 98 | + $conn->cleanup(); |
| 99 | + $this->close_response($conn); |
| 100 | + $this->in[(int)$conn->socket] = new Connection($conn->socket); |
| 101 | + } |
| 102 | + } |
93 | 103 |
|
94 |
| - $bytes = @fwrite($socket, $conn->buffer); |
95 |
| - if($bytes === false) return $this->close_connection($conn); |
| 104 | + public function close_connection($conn) |
| 105 | + { |
| 106 | + $conn->cleanup(); |
| 107 | + @fclose($conn->socket); |
| 108 | + unset($this->in[(int)$conn->socket]); |
| 109 | + $conn->socket = null; |
96 | 110 |
|
97 |
| - $conn->bytes_written += $bytes; |
98 |
| - $conn->buffer = substr($conn->buffer, $bytes); |
| 111 | + $this->close_response($conn); |
| 112 | + } |
99 | 113 |
|
100 |
| - if($conn->is_response_complete()) $this->complete_response($conn); |
101 |
| - } |
| 114 | + public function close_response($conn) |
| 115 | + { |
| 116 | + if(!$conn->stream) return; |
| 117 | + @fclose($conn->stream); |
| 118 | + unset($this->out[(int)$conn->stream]); |
| 119 | + $conn->stream = null; |
| 120 | + if($conn->proc) { |
| 121 | + proc_close($conn->proc); |
| 122 | + $conn->proc = null; |
| 123 | + } |
| 124 | + } |
102 | 125 |
|
103 |
| - public function complete_response($conn) |
104 |
| - { |
105 |
| - fwrite(STDERR, $this->log_request($conn)); |
106 |
| - if($conn->get_header('Connection') === 'close' || $conn->version !== 'HTTP/1.1') |
| 126 | + public function stop() |
107 | 127 | {
|
108 |
| - $this->close_connection($conn); |
109 |
| - }else |
| 128 | + $this->running = false; |
| 129 | + fclose($this->master); |
| 130 | + echo ">> Stopping...\n"; |
| 131 | + exit(0); |
| 132 | + } |
| 133 | + |
| 134 | + public function help() |
110 | 135 | {
|
111 |
| - $conn->cleanup(); |
112 |
| - $this->close_response($conn); |
113 |
| - $this->in[(int)$conn->socket] = new Connection($conn->socket); |
| 136 | + echo "Usage:\n"; |
| 137 | + echo "rackem [options] [config]\n\n"; |
| 138 | + echo "Options:\n"; |
| 139 | + echo " --basic run a basic HTTP server\n"; |
| 140 | + echo " --host HOST listen on HOST (default: 127.0.0.1)\n"; |
| 141 | + echo " --port PORT use PORT (default: 9393)\n"; |
| 142 | + echo " -h show this message\n"; |
| 143 | + echo " -v, --version show version.\n"; |
114 | 144 | }
|
115 |
| - } |
116 |
| - |
117 |
| - public function close_connection($conn) |
118 |
| - { |
119 |
| - $conn->cleanup(); |
120 |
| - @fclose($conn->socket); |
121 |
| - unset($this->in[(int)$conn->socket]); |
122 |
| - $conn->socket = null; |
123 |
| - |
124 |
| - $this->close_response($conn); |
125 |
| - } |
126 |
| - |
127 |
| - public function close_response($conn) |
128 |
| - { |
129 |
| - if(!$conn->stream) return; |
130 |
| - @fclose($conn->stream); |
131 |
| - unset($this->out[(int)$conn->stream]); |
132 |
| - $conn->stream = null; |
133 |
| - if($conn->proc) |
| 145 | + |
| 146 | + public function version() |
134 | 147 | {
|
135 |
| - proc_close($conn->proc); |
136 |
| - $conn->proc = null; |
| 148 | + echo explode(".", \Rackem::version()) ."\n"; |
137 | 149 | }
|
138 |
| - } |
139 |
| - |
140 |
| - public function stop() |
141 |
| - { |
142 |
| - $this->running = false; |
143 |
| - fclose($this->master); |
144 |
| - echo ">> Stopping...\n"; |
145 |
| - exit(0); |
146 |
| - } |
147 |
| - |
148 |
| - public function help() |
149 |
| - { |
150 |
| - echo "Usage:\n"; |
151 |
| - echo "rackem [options] [config]\n\n"; |
152 |
| - echo "Options:\n"; |
153 |
| - echo " --basic run a basic HTTP server\n"; |
154 |
| - echo " --host HOST listen on HOST (default: 127.0.0.1)\n"; |
155 |
| - echo " --port PORT use PORT (default: 9393)\n"; |
156 |
| - echo " -h show this message\n"; |
157 |
| - echo " -v, --version show version.\n"; |
158 |
| - } |
159 |
| - |
160 |
| - public function version() |
161 |
| - { |
162 |
| - echo explode(".", \Rackem::version()) ."\n"; |
163 |
| - } |
164 | 150 |
|
165 | 151 | /* private */
|
166 | 152 |
|
167 |
| - protected function init() |
168 |
| - { |
169 |
| - set_time_limit(0); |
170 |
| - $this->master = @stream_socket_server("tcp://{$this->host}:{$this->port}", $errno, $errstr); |
171 |
| - if($this->master === false) |
| 153 | + protected function init() |
172 | 154 | {
|
173 |
| - echo ">> Failed to bind socket.\n", $errno, " - ", $errstr, "\n"; |
174 |
| - exit(2); |
| 155 | + set_time_limit(0); |
| 156 | + $this->master = @stream_socket_server("tcp://{$this->host}:{$this->port}", $errno, $errstr); |
| 157 | + if($this->master === false) { |
| 158 | + echo ">> Failed to bind socket.\n", $errno, " - ", $errstr, "\n"; |
| 159 | + exit(2); |
| 160 | + } |
| 161 | + stream_set_blocking($this->master, 0); |
| 162 | + |
| 163 | + echo "== Rack'em on http://{$this->host}:{$this->port}\n"; |
| 164 | + echo ">> Rack'em web server\n"; |
| 165 | + echo ">> Listening on {$this->host}:{$this->port}, CTRL+C to stop\n"; |
| 166 | + if(function_exists('pcntl_signal')) { |
| 167 | + pcntl_signal(SIGINT, array($this, "stop")); |
| 168 | + pcntl_signal(SIGTERM, array($this, "stop")); |
| 169 | + } |
175 | 170 | }
|
176 |
| - stream_set_blocking($this->master, 0); |
177 | 171 |
|
178 |
| - echo "== Rack'em on http://{$this->host}:{$this->port}\n"; |
179 |
| - echo ">> Rack'em web server\n"; |
180 |
| - echo ">> Listening on {$this->host}:{$this->port}, CTRL+C to stop\n"; |
181 |
| - if(function_exists('pcntl_signal')) |
| 172 | + protected function log_request($conn) |
182 | 173 | {
|
183 |
| - pcntl_signal(SIGINT, array($this, "stop")); |
184 |
| - pcntl_signal(SIGTERM, array($this, "stop")); |
185 |
| - } |
186 |
| - } |
| 174 | + $date = @date("d/M/Y H:i:s"); |
| 175 | + $time = sprintf('%.4f', microtime(true) - $conn->start_time); |
187 | 176 |
|
188 |
| - protected function log_request($conn) |
189 |
| - { |
190 |
| - $date = @date("d/M/Y H:i:s"); |
191 |
| - $time = sprintf('%.4f', microtime(true) - $conn->start_time); |
192 |
| - |
193 |
| - return "{$conn->client} - - [{$date}] \"{$conn->request}\" {$conn->status} - {$time}\n"; |
194 |
| - } |
| 177 | + return "{$conn->client} - - [{$date}] \"{$conn->request}\" {$conn->status} - {$time}\n"; |
| 178 | + } |
195 | 179 |
|
196 | 180 | }
|
0 commit comments