123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- <?php
- namespace Mall\Framework\Swoole\WebsocketClient;
- class WebsocketParser
- {
- public $maxFrameSize = 2000000;
- protected $buffer = '';
-
- protected $frame = null;
- const ERR_TOO_LONG = 10001;
-
- function push($data)
- {
- $this->buffer .= $data;
- }
-
- function pop()
- {
-
- if ($this->frame)
- {
- if (strlen($this->buffer) >= $this->frame->length)
- {
-
- $this->frame->data = substr($this->buffer, 0, $this->frame->length);
- self::unMask($this->frame);
- $frame = $this->frame;
-
- $this->frame = null;
- $this->buffer = substr($this->buffer, $frame->length);
- return $frame;
- }
- else
- {
- return false;
- }
- }
- $buffer = &$this->buffer;
- if (strlen($buffer) < 2)
- {
- return false;
- }
- $frame = new WebSocketFrame;
- $data_offset = 0;
-
- $handle = ord($buffer[$data_offset]);
- $frame->finish = ($handle >> 7) & 0x1;
- $frame->rsv1 = ($handle >> 6) & 0x1;
- $frame->rsv2 = ($handle >> 5) & 0x1;
- $frame->rsv3 = ($handle >> 4) & 0x1;
- $frame->opcode = $handle & 0xf;
- $data_offset++;
-
- $handle = ord($buffer[$data_offset]);
- $frame->mask = ($handle >> 7) & 0x1;
-
- $frame->length = $handle & 0x7f;
- $length = &$frame->length;
- $data_offset++;
-
- if ($length == 0x7e)
- {
-
- $handle = unpack('nl', substr($buffer, $data_offset, 2));
- $data_offset += 2;
- $length = $handle['l'];
- }
-
- elseif ($length > 0x7e)
- {
-
- $handle = unpack('Nh/Nl', substr($buffer, $data_offset, 8));
- $data_offset += 8;
- $length = $handle['l'];
-
- if ($length > $this->maxFrameSize)
- {
- throw new \Exception("frame length is too big.", self::ERR_TOO_LONG);
- }
- }
-
- if ($frame->mask)
- {
- $frame->mask = array_map('ord', str_split(substr($buffer, $data_offset, 4)));
- $data_offset += 4;
- }
-
- $buffer = substr($buffer, $data_offset);
-
- if (0 === $length)
- {
- $frame->finish = true;
- $frame->data = '';
- return $frame;
- }
-
- if (strlen($buffer) >= $length)
- {
- $frame->finish = true;
- $frame->data = substr($buffer, 0, $length);
-
- $buffer = substr($buffer, $length);
- self::unMask($frame);
- return $frame;
- }
-
- else
- {
- $frame->finish = false;
- $this->frame = $frame;
- return false;
- }
- }
-
- static function unMask($frame)
- {
- if ($frame->mask)
- {
- $maskC = 0;
- $data = $frame->data;
- for ($j = 0, $_length = $frame->length; $j < $_length; ++$j)
- {
- $data[$j] = chr(ord($frame->data[$j]) ^ $frame->mask[$maskC]);
- $maskC = ($maskC + 1) % 4;
- }
- $frame->data = $data;
- }
- }
- }
- class WebSocketFrame
- {
- public $finish = false;
- public $opcode;
- public $data;
- public $length;
- public $rsv1;
- public $rsv2;
- public $rsv3;
- public $mask;
- }
|