1 | <?php |
||
16 | class SwooleWebSocketWrapper extends SwooleHttpWrapper implements ServerInterface |
||
17 | { |
||
18 | protected $defaultProtocol; |
||
19 | |||
20 | protected $pushProcess; |
||
21 | |||
22 | protected $connections = []; |
||
23 | |||
24 | protected $unfinished = []; |
||
25 | |||
26 | protected static $protocolCodecs = [ |
||
27 | 'json' => Json::class, |
||
28 | 'jsonrpc' => JsonRpc::class, |
||
29 | ]; |
||
30 | |||
31 | 4 | public function __construct($host, $port) |
|
35 | |||
36 | public static function getParams() |
||
43 | |||
44 | 4 | public static function registerCodec($protocol, $class = null) |
|
45 | { |
||
46 | 4 | if (is_string($protocol)) { |
|
47 | if (!class_exists($class)) { |
||
48 | throw new Exception("class $class not found", 1); |
||
49 | } |
||
50 | $protocol = [$protocol => $class]; |
||
51 | } |
||
52 | 4 | static::$protocolCodecs = array_merge(static::$protocolCodecs, $protocol); |
|
53 | 4 | } |
|
54 | |||
55 | 4 | public function start() |
|
71 | |||
72 | public static function onTask($server, $task_id, $from_id, $data) |
||
73 | { |
||
74 | foreach ($data['fds'] as $fd) { |
||
75 | try { |
||
76 | $server->push($fd, $data['params']); |
||
77 | } catch (\ErrorException $e) {} |
||
78 | } |
||
79 | } |
||
80 | |||
81 | public static function onFinish($server, $task_id, $data) |
||
85 | |||
86 | 4 | public function onHandShake(swoole_http_request $request, swoole_http_response $response) |
|
87 | { |
||
88 | 4 | $protocol = false; |
|
89 | 4 | if (isset($request->header['sec-websocket-protocol'])) { |
|
90 | 4 | $protocols = preg_split('~,\s*~', $request->header['sec-websocket-protocol']); |
|
91 | 4 | foreach ($protocols as $protocol) { |
|
92 | 4 | if (isset(static::$protocolCodecs[$protocol])) { |
|
93 | 4 | break; |
|
94 | } |
||
95 | 2 | } |
|
96 | 4 | if ($protocol) { |
|
97 | 4 | $response->header('Sec-WebSocket-Protocol', $protocol); |
|
98 | 2 | } |
|
99 | 2 | } |
|
100 | |||
101 | 4 | if (!$protocol) { |
|
102 | $protocol = $this->defaultProtocol; |
||
103 | } |
||
104 | |||
105 | 4 | $secKey = $request->header['sec-websocket-key']; |
|
106 | 4 | $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); |
|
107 | |||
108 | foreach ([ |
||
109 | 4 | "Upgrade" => "websocket", |
|
110 | 4 | "Connection" => "Upgrade", |
|
111 | 4 | "Sec-WebSocket-Version" => "13", |
|
112 | 4 | "Sec-WebSocket-Accept" => $secAccept, |
|
113 | 2 | ] as $k => $v) { |
|
114 | 4 | $response->header($k, $v); |
|
115 | 2 | } |
|
116 | 4 | $response->status(101); |
|
117 | |||
118 | 4 | $laravooleRequest = new Request($request->fd); |
|
119 | 4 | foreach ($request as $k => $v) { |
|
120 | 4 | $laravooleRequest->$k = $v; |
|
121 | 2 | } |
|
122 | 4 | $this->connections[$request->fd] = ['request' => $laravooleRequest, 'protocol' => static::$protocolCodecs[$protocol]]; |
|
123 | 4 | $this->unfinished[$request->fd] = ''; |
|
124 | 4 | return true; |
|
125 | |||
126 | } |
||
127 | |||
128 | 4 | public function onMessage(swoole_websocket_server $server, $frame) |
|
129 | { |
||
130 | 4 | if (!isset($this->unfinished[$frame->fd])) { |
|
131 | return false; |
||
132 | } |
||
133 | 4 | if (isset($this->connections[$frame->fd]['request']->laravooleInfo->nextMessageRoute)) { |
|
134 | 4 | $request = $this->connections[$frame->fd]['request']; |
|
135 | 4 | $route = $request->laravooleInfo->nextMessageRoute; |
|
136 | 4 | $data['method'] = $route['method']; |
|
137 | 4 | $data['params'] = $route['params']; |
|
138 | 4 | $data['params']['_laravoole_raw'] = $frame->data; |
|
139 | 4 | $data['params']['_laravoole_previous'] = $route['previous']; |
|
140 | |||
141 | 4 | $data['echo'] = $request->echo; |
|
142 | 4 | if ($frame->finish) { |
|
143 | 4 | unset($request->laravooleInfo->nextMessageRoute); |
|
144 | 2 | } |
|
145 | 4 | return $this->dispatch($server, $frame->fd, $data); |
|
146 | |||
147 | } else { |
||
148 | 4 | $this->unfinished[$frame->fd] .= $frame->data; |
|
149 | } |
||
150 | |||
151 | 4 | if (!$frame->finish) { |
|
152 | return; |
||
153 | } |
||
154 | 4 | $protocol = $this->connections[$frame->fd]['protocol']; |
|
155 | 4 | $data = $protocol::decode($this->unfinished[$frame->fd]); |
|
156 | 4 | if (is_null($data)) { |
|
157 | return; |
||
158 | } |
||
159 | |||
160 | 4 | $this->unfinished[$frame->fd] = ''; |
|
161 | |||
162 | 4 | return $this->dispatch($server, $frame->fd, $data); |
|
163 | |||
164 | } |
||
165 | |||
166 | 4 | protected function dispatch($server, $fd, $data) |
|
167 | { |
||
168 | 4 | $request = $this->connections[$fd]['request']; |
|
169 | |||
170 | 4 | $request->method = $request->server['request_uri'] = $data['method']; |
|
171 | 4 | $request->get = (array) ($data['params']); |
|
172 | 4 | $request->echo = isset($data['echo']) ? $data['echo'] : null; |
|
173 | 4 | $request = $this->ucHeaders($request); |
|
174 | |||
175 | 4 | $response = new Response($this, $request); |
|
176 | 4 | $illuminateRequest = $this->convertRequest($request); |
|
177 | |||
178 | 4 | if (isset($request->laravooleInfo)) { |
|
179 | 4 | $illuminateRequest->setLaravooleInfo($request->laravooleInfo); |
|
180 | 2 | } else { |
|
181 | 4 | $illuminateRequest->setLaravooleInfo((object) [ |
|
182 | 4 | 'fd' => $fd, |
|
183 | 4 | 'server' => $server, |
|
184 | 4 | 'codec' => $this->connections[$response->request->fd]['protocol'], |
|
185 | 2 | ]); |
|
186 | 2 | } |
|
187 | 4 | $illuminateResponse = parent::handleRequest($illuminateRequest); |
|
188 | 4 | $this->handleResponse($response, $illuminateResponse, ''); |
|
189 | |||
190 | 4 | $request->laravooleInfo = $illuminateRequest->getLaravooleInfo(); |
|
191 | 4 | } |
|
192 | |||
193 | 4 | public function endResponse($response, $content) |
|
194 | { |
||
195 | 4 | if (isset($response->request)) { |
|
196 | 4 | if (!is_string($content)) { |
|
197 | $content = file_get_contents($content()); |
||
198 | } |
||
199 | // This is a websocket request |
||
200 | 4 | $protocol = $this->connections[$response->request->fd]['protocol']; |
|
201 | 4 | $data = $protocol::encode( |
|
202 | 4 | $response->http_status, |
|
203 | 4 | $response->request->method, |
|
204 | 2 | $content, |
|
205 | 4 | $response->request->echo |
|
206 | 2 | ); |
|
207 | 4 | $this->server->push($response->request->fd, $data); |
|
208 | 2 | } else { |
|
209 | // This is a http request |
||
210 | 4 | parent::endResponse($response, $content); |
|
211 | } |
||
212 | 4 | } |
|
213 | |||
214 | 4 | public function onClose($server, $fd) |
|
226 | } |
||
227 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.