public WsFrame( Fin fin, Opcode opcode, Mask mask, PayloadData payload, bool compressed) { Fin = fin; Rsv1 = isData(opcode) && compressed ? Rsv.ON : Rsv.OFF; Rsv2 = Rsv.OFF; Rsv3 = Rsv.OFF; Opcode = opcode; Mask = mask; /* PayloadLen */ var dataLen = payload.Length; var payloadLen = dataLen < 126 ? (byte)dataLen : dataLen < 0x010000 ? (byte)126 : (byte)127; PayloadLen = payloadLen; /* ExtPayloadLen */ ExtPayloadLen = payloadLen < 126 ? new byte [] {} : payloadLen == 126 ? ((ushort)dataLen).ToByteArrayInternally(ByteOrder.BIG) : dataLen.ToByteArrayInternally(ByteOrder.BIG); /* MaskingKey */ var masking = mask == Mask.MASK; var maskingKey = masking ? createMaskingKey() : new byte [] {}; MaskingKey = maskingKey; /* PayloadData */ if (masking) { payload.Mask(maskingKey); } PayloadData = payload; }
private static WsFrame parse(byte [] header, Stream stream, bool unmask) { /* Header */ // FIN var fin = (header [0] & 0x80) == 0x80 ? Fin.FINAL : Fin.MORE; // RSV1 var rsv1 = (header [0] & 0x40) == 0x40 ? Rsv.ON : Rsv.OFF; // RSV2 var rsv2 = (header [0] & 0x20) == 0x20 ? Rsv.ON : Rsv.OFF; // RSV3 var rsv3 = (header [0] & 0x10) == 0x10 ? Rsv.ON : Rsv.OFF; // Opcode var opcode = (Opcode)(header [0] & 0x0f); // MASK var mask = (header [1] & 0x80) == 0x80 ? Mask.MASK : Mask.UNMASK; // Payload len var payloadLen = (byte)(header [1] & 0x7f); // Check if correct frame. var incorrect = isControl(opcode) && fin == Fin.MORE ? "A control frame is fragmented." : !isData(opcode) && rsv1 == Rsv.ON ? "A non data frame is compressed." : null; if (incorrect != null) { throw new WebSocketException(CloseStatusCode.INCORRECT_DATA, incorrect); } // Check if consistent frame. if (isControl(opcode) && payloadLen > 125) { throw new WebSocketException( CloseStatusCode.INCONSISTENT_DATA, "The payload data length of a control frame is greater than 125 bytes."); } var frame = new WsFrame { Fin = fin, Rsv1 = rsv1, Rsv2 = rsv2, Rsv3 = rsv3, Opcode = opcode, Mask = mask, PayloadLen = payloadLen }; /* Extended Payload Length */ var extLen = payloadLen < 126 ? 0 : payloadLen == 126 ? 2 : 8; var extPayloadLen = extLen > 0 ? stream.ReadBytes(extLen) : new byte [] {}; if (extLen > 0 && extPayloadLen.Length != extLen) { throw new WebSocketException( "The 'Extended Payload Length' of a frame cannot be read from the data source."); } frame.ExtPayloadLen = extPayloadLen; /* Masking Key */ var masked = mask == Mask.MASK; var maskingKey = masked ? stream.ReadBytes(4) : new byte [] {}; if (masked && maskingKey.Length != 4) { throw new WebSocketException( "The 'Masking Key' of a frame cannot be read from the data source."); } frame.MaskingKey = maskingKey; /* Payload Data */ ulong dataLen = payloadLen < 126 ? payloadLen : payloadLen == 126 ? extPayloadLen.ToUInt16(ByteOrder.BIG) : extPayloadLen.ToUInt64(ByteOrder.BIG); byte [] data = null; if (dataLen > 0) { // Check if allowable payload data length. if (payloadLen > 126 && dataLen > PayloadData.MaxLength) { throw new WebSocketException( CloseStatusCode.TOO_BIG, "The 'Payload Data' length is greater than the allowable length."); } data = payloadLen > 126 ? stream.ReadBytes((long)dataLen, 1024) : stream.ReadBytes((int)dataLen); if (data.LongLength != (long)dataLen) { throw new WebSocketException( "The 'Payload Data' of a frame cannot be read from the data source."); } } else { data = new byte [] {}; } var payload = new PayloadData(data, masked); if (masked && unmask) { payload.Mask(maskingKey); frame.Mask = Mask.UNMASK; frame.MaskingKey = new byte [] {}; } frame.PayloadData = payload; return(frame); }