/// <summary> /// 結合されたフレームデータからメッセージを作成 /// </summary> /// <param name="handshakeSession"></param> /// <param name="opcode"></param> /// <param name="payloadData"></param> /// <param name="isCompressed"></param> public WebSocketMessage(IReadOnlySession handshakeSession, WebSocketOpcode opcode, byte[] payloadData, bool isCompressed) { this.HandshakeSession = handshakeSession; this.Opcode = opcode; this.PayloadData = payloadData; this.IsCompressed = isCompressed; }
public WebSocketContent(IWebSocketMessage message, WebSocketOpcode opcode) { if (message == null) throw new ArgumentNullException("message"); if (message == null) throw new ArgumentNullException("opcode"); _message = new WebSocketMessage(opcode); }
public WebSocketFrame( WebSocketFin fin, WebSocketRsv rsv1, WebSocketRsv rsv2, WebSocketRsv rsv3, WebSocketOpcode opcode, WebSocketMask mask, byte[] maskingKey, byte payloadLength, byte[] extPayloadLength, Stream payload ) { if (mask == WebSocketMask.Mask && (maskingKey == null || maskingKey.Length != 4)) throw new ArgumentOutOfRangeException("maskingKey", "must by 4 bytes long"); _fin = fin; _rsv1 = rsv1; _rsv2 = rsv2; _rsv3 = rsv3; _opcode = opcode; _mask = mask; _maskingKey = maskingKey; _payloadLength = payloadLength; _extPayloadLength = extPayloadLength; _payload = payload; }
internal WebSocketFrameHeader(Stream networkStream) { byte[] head = ByteUtil.ReadNBytes(networkStream, 2); fin = (head[0] & 0b10000000) > 0; // The FIN bit tells whether this is the last message in a series. If it's 0, then the server will keep listening for more parts of the message; otherwise, the server should consider the message delivered. opcode = (WebSocketOpcode)(head[0] & 0b00001111); mask = (head[1] & 0b10000000) > 0; // The MASK bit simply tells whether the message is encoded. if (!mask) { throw new WebSocketException(WebSocketCloseCode.ProtocolError, "Client must mask all outgoing frames."); // TODO: Send a "Close frame" with a status code of 1002 (protocol error) // Clients MUST mask all frames they send. } payloadLength = (ulong)(head[1] & 0b01111111); if (payloadLength == 126) { payloadLength = ByteUtil.ReadUInt16(networkStream); } if (payloadLength == 127) { payloadLength = ByteUtil.ReadUInt64(networkStream); } if (isControlFrame && !fin) { throw new WebSocketException(WebSocketCloseCode.ProtocolError, "Control frame was fragmented"); } if (isControlFrame && payloadLength > 125) { throw new WebSocketException(WebSocketCloseCode.ProtocolError, "Control frame exceeded maximum payload length"); } maskBytes = ByteUtil.ReadNBytes(networkStream, 4); }
public void SendData(WebSocketOpcode opcode) { SendData(new WebMessageData() { OpCode = opcode }); }
/// <summary> /// Create a new WebSocket message with predefined payload /// </summary> /// <param name="opcode">opcode</param> /// <param name="payload">payload</param> public WebSocketMessage(WebSocketOpcode opcode, Stream payload) { if (payload == null) throw new ArgumentNullException("payload"); Opcode = opcode; Payload = payload; }
public WebSocketFrame( WebSocketFin fin, WebSocketRsv rsv1, WebSocketRsv rsv2, WebSocketRsv rsv3, WebSocketOpcode opcode, WebSocketMask mask, byte[] maskingKey, Stream payload ) : this(fin, rsv1, rsv2, rsv3, opcode, mask, maskingKey, 0, new byte[0], payload) { if (payload != null) { var len = payload.Length; if (len < 126) { _payloadLength = (byte)len; _extPayloadLength = new byte[0]; } else if (len < 0x010000) { _payloadLength = (byte)126; _extPayloadLength = WebSocketUtils.GetBigEndianBytes((ushort)len); } else { _payloadLength = (byte)127; _extPayloadLength = WebSocketUtils.GetBigEndianBytes((ulong)len); } } }
public void Write(WebSocketOpcode opcode, byte[] data) { using (MemoryStream ms = new MemoryStream()) { byte bitFin = 0x80; byte first = (byte)(bitFin | (byte)opcode); ms.WriteByte(first); byte second; if (data.Length <= 125) { second = (byte)data.Length; ms.WriteByte(second); } else if (data.Length <= 65535) { second = 126; ms.WriteByte(second); WebSocketReaderWriter.WriteNumber(ms, (ushort)data.Length, false); } else { second = 127; ms.WriteByte(second); WebSocketReaderWriter.WriteNumber(ms, (ulong)data.Length, false); } ms.Write(data, 0, data.Length); byte[] buffer = ms.ToArray(); Stream.Write(buffer, 0, buffer.Length); } }
public async Task Broadcast(WebSocketOpcode code, byte[] data) { foreach (var keypair in Users) { await keypair.Value.Writer.Write(code, data); } }
/// <summary> /// 异步发送字节数组并指定内容类型 /// </summary> /// <param name="data"></param> /// <param name="opcode"></param> /// <param name="userState"></param> /// <exception cref="ArgumentNullException">message is null</exception> /// <exception cref="IOException">network is closed</exception> public void SendAsync(byte[] data, WebSocketOpcode opcode, object userState) { //协议要求,客户端向服务端发送数据是mask必需为true if (!this.isConnectioned) { throw new IOException("WebSocket Closed"); } if (data == null) { throw new ArgumentNullException("data"); } var df = new WebSocketDataFrame(data, true, opcode); var buffer = df.GetFrameBytes(); try { lock (this.sendLockObject) { this.stream.BeginWrite(buffer, 0, buffer.Length, this.SendCallback, userState); } } catch (Exception exception) { this.OnError(exception); this.Close(WebSocketCloseReason.IOError); throw; } }
public WebSocketFrame( WebSocketFin fin, WebSocketRsv rsv1, WebSocketRsv rsv2, WebSocketRsv rsv3, WebSocketOpcode opcode, WebSocketMask mask, byte[] maskingKey, byte payloadLength, byte[] extPayloadLength, Stream payload ) { if (mask == WebSocketMask.Mask && (maskingKey == null || maskingKey.Length != 4)) { throw new ArgumentOutOfRangeException("maskingKey", "must by 4 bytes long"); } _fin = fin; _rsv1 = rsv1; _rsv2 = rsv2; _rsv3 = rsv3; _opcode = opcode; _mask = mask; _maskingKey = maskingKey; _payloadLength = payloadLength; _extPayloadLength = extPayloadLength; _payload = payload; }
/// <summary> /// Constructs a non-fragmented WebSocketFrameHeader for the purpose of serializing it to a stream with <see cref="Write(Stream)"/>. /// </summary> /// <param name="opcode">The opcode to include in the header.</param> /// <param name="payloadLength">The payload length to include in the header.</param> internal WebSocketFrameHeader(WebSocketOpcode opcode, int payloadLength) { this.fin = true; this.opcode = opcode; this.mask = false; this.payloadLength = (ulong)payloadLength; }
internal WebSocketFrameHeader(WebSocketFrameHeader other) { fin = other.fin; opcode = other.opcode; mask = other.mask; maskBytes = other.maskBytes; payloadLength = other.payloadLength; }
// Control frames can't have fin=false public Task ReadBinaryFormattedFrames(byte[] rawFrame, byte[] payload, WebSocketOpcode opcode, bool endOfMessage) { return(RunSingleFrameTest( rawFrame, endOfMessage, opcode, b => Assert.Equal(payload, b))); }
/// <summary> /// Creates an instance of a WebSocketHeader. /// </summary> /// <param name="fin">Whether or not this is the final frame in the message.</param> /// <param name="opcode">The opcode of the frame.</param> /// <param name="masked">Whether the frame payload is masked.</param> /// <param name="payloadLength">The length of the frame payload.</param> /// <param name="maskingKey">The masking key used to unmask the payload, if masked. This mask must be a cryptographically random value.</param> public WebSocketHeader(bool fin, WebSocketOpcode opcode, bool masked, ulong payloadLength, int maskingKey) { Fin = fin; Opcode = opcode; Masked = masked; PayloadLength = payloadLength; MaskingKey = maskingKey; }
private void SendData(WebSocketOpcode opcode) { var sendData = PacketResponseData(new WebMessageData() { Data = new byte[1], OpCode = opcode }); _session?.SendDataToServer(sendData); }
public WebSocketFrame( WebSocketFin fin, WebSocketOpcode opcode, WebSocketMask mask, Stream payload ) : this(fin, WebSocketRsv.Off, WebSocketRsv.Off, WebSocketRsv.Off, opcode, mask, mask == WebSocketMask.Mask ? WebSocketUtils.CreateMaskingKey() : new byte[0], payload) { }
/// <summary> /// Create a new WebSocket message with predefined payload /// </summary> /// <param name="opcode">opcode</param> /// <param name="payload">payload</param> public WebSocketMessage(WebSocketOpcode opcode, Stream payload) { if (payload == null) { throw new ArgumentNullException("payload"); } Opcode = opcode; Payload = payload; }
public WebSocketFrame Read(Stream stream, WebSocketClient client) { byte first; try { first = (byte)stream.ReadByte(); } catch (Exception e) { return(null); } if (!WebSocketUtils.IsClientConnected(client)) { return(null); } byte bitFinFlag = 0x80; byte opcodeFlag = 0x0F; bool bitFinSet = (first & bitFinFlag) == bitFinFlag; WebSocketOpcode opcode = (WebSocketOpcode)(first & opcodeFlag); byte bitMaskFlag = 0x80; byte second = (byte)stream.ReadByte(); bool bitMaskSet = (second & bitMaskFlag) == bitMaskFlag; uint length = ReadLength(stream, second); if (length != 0) { byte[] decoded; if (bitMaskSet) { byte[] key = WebSocketReaderWriter.Read(stream, 4); byte[] encoded = WebSocketReaderWriter.Read(stream, length); decoded = new byte[length]; for (int i = 0; i < encoded.Length; i++) { decoded[i] = (byte)(encoded[i] ^ key[i % 4]); } } else { decoded = WebSocketReaderWriter.Read(stream, length); } WebSocketFrame frame = new WebSocketFrame(opcode, decoded); return(frame); } return(null); }
private void LogFrame(ILogger logger, WebSocketOpcode lastFrameOpcode, ref WebSocketFrame frame) { var opcode = frame.Opcode; if (opcode == WebSocketOpcode.Continuation) { opcode = lastFrameOpcode; } logger.LogDebug($"Received {frame.Opcode} frame (FIN={frame.EndOfMessage}, LEN={frame.Payload.Length})"); }
private Task SendCoreAsync <T>(bool fin, WebSocketOpcode opcode, int payloadAllocLength, int payloadLength, Action <WritableBuffer, Span <byte>, int, T> payloadWriter, T payload, CancellationToken cancellationToken) { if (_sendLock.Wait(0)) { return(SendCoreLockAcquiredAsync(fin, opcode, payloadAllocLength, payloadLength, payloadWriter, payload, cancellationToken)); } else { return(SendCoreWaitForLockAsync(fin, opcode, payloadAllocLength, payloadLength, payloadWriter, payload, cancellationToken)); } }
internal void SendFrame(WebSocketOpcode opcode, byte[] data) { lock (sendLock) { // Write frame header WebSocketFrameHeader head = new WebSocketFrameHeader(opcode, data.Length); head.Write(tcpStream); // Write payload tcpStream.Write(data, 0, data.Length); } }
/// <summary> /// 引发消息事件 /// </summary> /// <param name="data"></param> /// <param name="opcode"></param> protected void OnMessage(byte[] data, WebSocketOpcode opcode) { if (this.Message != null) { var args = new WebSocketMessageEventArgs(opcode); args.Buffer = data; if (opcode == WebSocketOpcode.Text) { args.Message = this.encoding.GetString(data); } this.Message(this, args); } }
public WebSocketContent(IWebSocketMessage message, WebSocketOpcode opcode) { if (message == null) { throw new ArgumentNullException("message"); } if (message == null) { throw new ArgumentNullException("opcode"); } _message = new WebSocketMessage(opcode); }
public async Task WriteBinaryFormattedFrames(byte[] payload, WebSocketOpcode opcode, bool endOfMessage, byte[] expectedRawFrame) { var data = await RunSendTest( producer : async(socket) => { await socket.SendAsync(CreateFrame( endOfMessage, opcode, payload: payload)).OrTimeout(); }, options : DefaultTestOptions); Assert.Equal(expectedRawFrame, data); }
public void SendData(WebSocketOpcode opcode, byte[] buffer, int offset, int count) { if (buffer.Length == count && offset == 0) { SendData(opcode, buffer); return; } var data = new byte[count]; System.Buffer.BlockCopy(buffer, offset, data, 0, count); SendData(opcode, data); }
private async Task SendCoreLockAcquiredAsync <T>(bool fin, WebSocketOpcode opcode, int payloadAllocLength, int payloadLength, Action <WritableBuffer, Span <byte>, int, T> payloadWriter, T payload, CancellationToken cancellationToken) { try { // Ensure the lock is held Debug.Assert(_sendLock.CurrentCount == 0); // Base header size is 2 bytes. WritableBuffer buffer; var allocSize = CalculateAllocSize(payloadAllocLength, payloadLength); // Allocate a buffer buffer = _outbound.Alloc(minimumSize: allocSize); Debug.Assert(buffer.Memory.Length >= allocSize); // Write the opcode and FIN flag var opcodeByte = (byte)opcode; if (fin) { opcodeByte |= 0x80; } buffer.WriteBigEndian(opcodeByte); // Write the length and mask flag WritePayloadLength(payloadLength, buffer); var maskingKey = Span <byte> .Empty; if (_maskingKeyBuffer != null) { // Get a span of the output buffer for the masking key, write it there, then advance the write head. maskingKey = buffer.Memory.Slice(0, 4).Span; WriteMaskingKey(maskingKey); buffer.Advance(4); } // Write the payload payloadWriter(buffer, maskingKey, payloadLength, payload); // Flush. await buffer.FlushAsync(); } finally { // Unlock. _sendLock.Release(); } }
/// <summary> /// 初始一个输出内容帧 /// </summary> /// <param name="content"></param> /// <param name="isMask"></param> /// <param name="opcode"></param> public WebSocketDataFrame(byte[] content, bool isMask, WebSocketOpcode opcode = WebSocketOpcode.Text) { this.Content = content; int length = this.Content.Length; if (length < 126) { _extend = new byte[0]; _header = new WebSocketDataFrameHeader(true, false, false, false, (sbyte)opcode, isMask, length); } else if (length < 65536) { _extend = new byte[2]; _header = new WebSocketDataFrameHeader(true, false, false, false, (sbyte)opcode, isMask, 126); _extend[0] = (byte)(length / 256); _extend[1] = (byte)(length % 256); } else { _extend = new byte[8]; _header = new WebSocketDataFrameHeader(true, false, false, false, (sbyte)opcode, isMask, 127); int left = length; int unit = 256; for (int i = 7; i > 1; i--) { _extend[i] = (byte)(left % unit); left = left / unit; if (left == 0) { break; } } } // if (_header.HasMask) { _mask = Adf.BaseDataConverter.ToBytes(Environment.TickCount + content.GetHashCode()); Mask(this.Content, _mask); } }
/// <summary> /// 发送一组数据,并指定消息类型 /// </summary> /// <param name="data"></param> /// <param name="opcode"></param> /// <exception cref="System.Net.Sockets.SocketException"></exception> /// <exception cref="System.ObjectDisposedException"></exception> public void Send(byte[] data, WebSocketOpcode opcode) { //协议原因,一些客户端不支持服务器端的 mask ,因此此值必需为 false var df = new WebSocketDataFrame(data, false, opcode); var buffer = df.GetFrameBytes(); try { lock (this.sendLockObject) { this.socket.Send(buffer); } } catch (Exception exception) { this.Close("IO Error on send," + exception.Message, WebSocketCloseReason.IOError); throw; } }
/// <summary> /// 发送一组数据,并指定消息类型 /// </summary> /// <param name="data"></param> /// <param name="opcode"></param> /// <param name="userSate"></param> /// <exception cref="System.Net.Sockets.SocketException"></exception> /// <exception cref="System.ObjectDisposedException"></exception> public void SendAsync(byte[] data, WebSocketOpcode opcode, object userSate) { //协议原因,一些客户端不支持服务器端的 mask ,因此此值必需为 false var df = new WebSocketDataFrame(data, false, opcode); var buffer = df.GetFrameBytes(); try { lock (this.sendLockObject) { this.socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, this.SendCallback, userSate); } } catch (Exception exception) { this.Close("IO Error on send," + exception.Message, WebSocketCloseReason.IOError); throw; } }
public void SendData(WebSocketOpcode opcode, byte[] data) { if (Interlocked.Read(ref _isDisposed) != 0) { return; } if (data == null || data.Length == 0) { return; } #if ADDMSGID var msgid = Interlocked.Increment(ref _curMsgId); #endif SendData(new WebMessageData() { #if ADDMSGID MessageId = (byte)msgid, #endif Data = data, OpCode = opcode }); }
public void SendData(WebSocketOpcode opcode, byte[] data, bool isFinalFrame) { var buffer = new List <byte>(); long len = data.LongLength; var b1 = (byte)(0x7F & (byte)opcode); if (isFinalFrame) { b1 = (byte)(b1 | 0x80); } buffer.Add(b1); if (len < 126) { var b2 = (byte)(0x7F & data.Length); buffer.Add(b2); } else if (len < 0xFFFF) { buffer.Add(0x7E); buffer.Add((byte)((len & 0xFF00) >> 8)); buffer.Add((byte)((len & 0x00FF) >> 0)); } else if (len < 0x7FFFFFFFFFFFFFFF) { buffer.Add(0x7F); buffer.Add((byte)((len & 0x7F00000000000000) >> 7 * 8)); buffer.Add((byte)((len & 0x00FF000000000000) >> 6 * 8)); buffer.Add((byte)((len & 0x0000FF0000000000) >> 5 * 8)); buffer.Add((byte)((len & 0x000000FF00000000) >> 4 * 8)); buffer.Add((byte)((len & 0x00000000FF000000) >> 3 * 8)); buffer.Add((byte)((len & 0x0000000000FF0000) >> 2 * 8)); buffer.Add((byte)((len & 0x000000000000FF00) >> 1 * 8)); buffer.Add((byte)((len & 0x00000000000000FF) >> 0 * 8)); } buffer.AddRange(data); Write(buffer.ToArray()); }
public async Task Write(WebSocketOpcode opcode, byte[] data) { using (MemoryStream ms = new MemoryStream()) { try { byte bitFin = 0x80; byte first = (byte)(bitFin | (byte)opcode); byte[] firstData = new byte[] { first }; await ms.WriteAsync(firstData, 0, firstData.Length); if (data.Length <= 125) { byte[] secData = new byte[] { (byte)data.Length }; await ms.WriteAsync(secData, 0, secData.Length); } else if (data.Length <= 65535) { byte[] secData = new byte[] { 126 }; await ms.WriteAsync(secData, 0, secData.Length); await WebSocketReaderWriter.WriteNumber(ms, (ushort)data.Length, false); } else { byte[] secData = new byte[] { 127 }; await ms.WriteAsync(secData, 0, secData.Length); await WebSocketReaderWriter.WriteNumber(ms, (ulong)data.Length, false); } await ms.WriteAsync(data, 0, data.Length); byte[] buffer = ms.ToArray(); await Stream.WriteAsync(buffer, 0, buffer.Length); } catch (Exception) { } } }
/// <summary> /// Creates a new WebSocket message with empty payload. This is useful for control messages such as PING, PONG and CLOSE /// </summary> /// <param name="opcode">opcode</param> public WebSocketMessage(WebSocketOpcode opcode) : this(opcode, Stream.Null) { }