internal WebSocket(TcpSocket socket, HttpServerRequest context, ArraySegment <byte> head) { _context = context; _socket = socket; _socket.OnData += OnData; _socket.OnDisconnected += OnSocketDisconnected; _recvstate = RecvStat.Start1; _fragmented = 0; _payloadData = new BufferData(); _sendingQueue = new BufferData(); _sendingTextMode = false; _sendingMaskMode = false; _isserver = true; _state = SocketStat.Open; if (head.Count > 0) { OnData(_socket, head); } _socket.NoDelay = true; _socket.ReceiveStart(); }
private void OnData(TcpSocket socket, ArraySegment <byte> data) { var buf = data.Array; var start = data.Offset; var end = data.Offset + data.Count; var p = start; while (p < end) { switch (_recvstate) { case RecvStat.Start1: { byte tmp = buf[p]; if ((tmp & 0x70) != 0) { Error("RSV1, RSV2 and RSV3 must be clear", 1002); } _fin = (tmp & 0x80) == 0x80; _opcode = (byte)(tmp & 0x0f); if (_opcode == 0) { if (_fragmented == 0) { Error("invalid opcode: " + _opcode, 1002); return; } else { _opcode = _fragmented; } } else if (_opcode == 0x01 || _opcode == 0x02) { if (_fragmented != 0) { Error("invalid opcode: " + _opcode, 1002); return; } } else if (_opcode > 0x07 && _opcode < 0x0b) { if (!_fin) { Error("FIN must be set", 1002); return; } } else { Error("invalid opcode: " + _opcode, 1002); return; } p++; _recvstate = RecvStat.PayloadLength1; break; } case RecvStat.PayloadLength1: { _payloadLength = (long)(buf[p] & 0x7f); _masked = (buf[p] & 0x80) == 0x80; _maskValue = 0; _maskPos = 0; if (_payloadLength == 126) { _payloadLength = 0; _index = 2; _recvstate = RecvStat.PayloadLength2; } else if (_payloadLength == 127) { _payloadLength = 0; _index = 8; _recvstate = RecvStat.PayloadLength2; } else { _recvstate = _masked ? RecvStat.Mask : RecvStat.Data; _index = 4; } p++; break; } case RecvStat.PayloadLength2: { while (_index > 0 && p < end) { _index--; _payloadLength |= ((long)buf[p] << (8 * _index)); p++; } if (_index == 0) { _recvstate = _masked ? RecvStat.Mask : RecvStat.Data; _index = 4; } break; } case RecvStat.Mask: { while (_index > 0 && p < end) { _index--; _maskValue |= ((uint)buf[p] << (8 * (3 - _index))); p++; } if (_index == 0) { _recvstate = RecvStat.Data; } break; } case RecvStat.Data: { var len = (int)Math.Min(_payloadLength, end - p); if (_masked) { for (var i = p; i < p + len; i++) { buf[i] ^= (byte)(_maskValue >> (8 * (_maskPos & 3))); _maskPos++; } } _payloadData.Add(buf, p, len); _payloadLength -= len; p += len; if (_payloadLength == 0) { _recvstate = RecvStat.Start1; OnFrameReceived(); } break; } } } if (_recvstate == RecvStat.Data && _payloadLength == 0) { _recvstate = RecvStat.Start1; OnFrameReceived(); } }