| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- <?php
- namespace app\lib\wclient;
- /**
- * Created by PhpStorm.
- * User: marsnowxiao
- * Date: 2017/6/15
- * Time: 下午5:12
- */
- use app\lib\wclient\WebSocketFrame as WebSocketFrame;
- class PacketHandler
- {
- const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
- const TOKEN_LENGHT = 16;
- const maxPacketSize = 2000000;
- private $key = "";
- private static function generateToken($length)
- {
- $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"§$%&/()=[]{}';
- $useChars = array();
- // select some random chars:
- for ($i = 0; $i < $length; $i++) {
- $useChars[] = $characters[mt_rand(0, strlen($characters) - 1)];
- }
- // Add numbers
- array_push($useChars, rand(0, 9), rand(0, 9), rand(0, 9));
- shuffle($useChars);
- $randomString = trim(implode('', $useChars));
- $randomString = substr($randomString, 0, self::TOKEN_LENGHT);
- return base64_encode($randomString);
- }
- public function buildHandShakeRequest($host, $port, $getParas)
- {
- $this->key = static::generateToken(self::TOKEN_LENGHT);
- return "GET /{$getParas} HTTP/1.1" . "\r\n" .
- "Origin: null" . "\r\n" .
- "Host: {$host}:{$port}" . "\r\n" .
- "Sec-WebSocket-Key: {$this->key}" . "\r\n" .
- "User-Agent: SwooleWebsocketClient" . "/0.1.4" . "\r\n" .
- "Upgrade: Websocket" . "\r\n" .
- "Connection: Upgrade" . "\r\n" .
- "Sec-WebSocket-Protocol: wamp" . "\r\n" .
- "Sec-WebSocket-Version: 13" . "\r\n" . "\r\n";
- }
- public function verifyUpgrade($packet)
- {
- $headers = explode("\r\n", $packet);
- unset($headers[0]);
- $headerInfo = [];
- foreach ($headers as $header) {
- $arr = explode(":", $header);
- if (count($arr) == 2) {
- list($field, $value) = $arr;
- $headerInfo[trim($field)] = trim($value);
- }
- }
- return (isset($headerInfo['Sec-WebSocket-Accept']) && $headerInfo['Sec-WebSocket-Accept'] == base64_encode(pack('H*', sha1($this->key . self::GUID))));
- }
- public function processDataFrame(&$packet)
- {
- if (strlen($packet) < 2)
- return null;
- $header = substr($packet, 0, 2);
- $index = 0;
- //fin:1 rsv1:1 rsv2:1 rsv3:1 opcode:4
- $handle = ord($packet[$index]);
- $finish = ($handle >> 7) & 0x1;
- $rsv1 = ($handle >> 6) & 0x1;
- $rsv2 = ($handle >> 5) & 0x1;
- $rsv3 = ($handle >> 4) & 0x1;
- $opcode = $handle & 0xf;
- $index++;
- //mask:1 length:7
- $handle = ord($packet[$index]);
- $mask = ($handle >> 7) & 0x1;
- //0-125
- $length = $handle & 0x7f;
- $index++;
- //126 short
- if ($length == 0x7e) {
- if (strlen($packet) < $index + 2)
- return null;
- //2 byte
- $handle = unpack('nl', substr($packet, $index, 2));
- $index += 2;
- $length = $handle['l'];
- } //127 int64
- elseif ($length > 0x7e) {
- if (strlen($packet) < $index + 8)
- return null;
- //8 byte
- $handle = unpack('Nh/Nl', substr($packet, $index, 8));
- $index += 8;
- $length = $handle['l'];
- if ($length > static::maxPacketSize) {
- throw new \Exception("frame length is too big.\n");
- }
- }
- //mask-key: int32
- if ($mask) {
- if (strlen($packet) < $index + 4)
- return null;
- $mask = array_map('ord', str_split(substr($packet, $index, 4)));
- $index += 4;
- }
- if (strlen($packet) < $index + $length)
- return null;
- $data = substr($packet, $index, $length);
- $index += $length;
- $packet = substr($packet, $index);
- $frame = new WebSocketFrame;
- $frame->finish = $finish;
- $frame->opcode = $opcode;
- $frame->data = $data;
- return $frame;
- }
- }
|