private void MessageLoop() { var packet = new List <byte>(); var messageOpcode = 0x0; using (var messageBuffer = new MemoryStream()) { while (_client.Connected) { packet.Clear(); var ab = _client.Available; if (ab == 0) { continue; } packet.Add((byte)_clientStream.ReadByte()); var fin = (packet[0] & (1 << 7)) != 0; var rsv1 = (packet[0] & (1 << 6)) != 0; var rsv2 = (packet[0] & (1 << 5)) != 0; var rsv3 = (packet[0] & (1 << 4)) != 0; // Must error if is set. //if (rsv1 || rsv2 || rsv3) // return; var opcode = packet[0] & ((1 << 4) - 1); switch (opcode) { case 0x0: // Continuation Frame break; case 0x1: // Text case 0x2: // Binary case 0x8: // Connection Close messageOpcode = opcode; break; case 0x9: continue; // Ping case 0xA: continue; // Pong default: continue; // Reserved } packet.Add((byte)_clientStream.ReadByte()); var masked = IsMasking = (packet[1] & (1 << 7)) != 0; var pseudoLength = packet[1] - (masked ? 128 : 0); ulong actualLength = 0; if (pseudoLength > 0 && pseudoLength < 125) { actualLength = (ulong)pseudoLength; } else if (pseudoLength == 126) { var length = new byte[2]; _clientStream.Read(length, 0, length.Length); packet.AddRange(length); Array.Reverse(length); actualLength = BitConverter.ToUInt16(length, 0); } else if (pseudoLength == 127) { var length = new byte[8]; _clientStream.Read(length, 0, length.Length); packet.AddRange(length); Array.Reverse(length); actualLength = BitConverter.ToUInt64(length, 0); } var mask = new byte[4]; if (masked) { _clientStream.Read(mask, 0, mask.Length); packet.AddRange(mask); } if (actualLength > 0) { var data = new byte[actualLength]; _clientStream.Read(data, 0, data.Length); packet.AddRange(data); if (masked) { data = ApplyMask(data, mask); } messageBuffer.Write(data, 0, data.Length); } LogRequest?.Invoke(this, new LogEventArgs($@"RECV: {BitConverter.ToString(packet.ToArray())}")); if (!fin) { continue; } var message = messageBuffer.ToArray(); switch (messageOpcode) { case 0x1: AnyMessageReceived?.Invoke(this, message); TextMessageReceived?.Invoke(this, Encoding.UTF8.GetString(message)); break; case 0x2: AnyMessageReceived?.Invoke(this, message); BinaryMessageReceived?.Invoke(this, Encoding.UTF8.GetString(message)); break; case 0x8: Close(); break; default: throw new Exception("Invalid opcode: " + messageOpcode); } messageBuffer.SetLength(0); } } }
private void MessageLoop() { WebSocketSession session = this; TcpClient client = session.Client; Stream stream = session.ClientStream; List <byte> packet = new List <byte>(); int messageOpcode = 0x0; using (MemoryStream messageBuffer = new MemoryStream()) while (client.Connected) { packet.Clear(); int ab = client.Available; if (ab == 0) { continue; } packet.Add((byte)stream.ReadByte()); bool fin = (packet[0] & (1 << 7)) != 0; bool rsv1 = (packet[0] & (1 << 6)) != 0; bool rsv2 = (packet[0] & (1 << 5)) != 0; bool rsv3 = (packet[0] & (1 << 4)) != 0; // Must error if is set. //if (rsv1 || rsv2 || rsv3) // return; int opcode = packet[0] & ((1 << 4) - 1); switch (opcode) { case 0x0: // Continuation Frame break; case 0x1: // Text case 0x2: // Binary case 0x8: // Connection Close messageOpcode = opcode; break; case 0x9: continue; // Ping case 0xA: continue; // Pong default: continue; // Reserved } packet.Add((byte)stream.ReadByte()); bool masked = (packet[1] & (1 << 7)) != 0; int pseudoLength = packet[1] - (masked ? 128 : 0); ulong actualLength = 0; if (pseudoLength > 0 && pseudoLength < 125) { actualLength = (ulong)pseudoLength; } else if (pseudoLength == 126) { byte[] length = new byte[2]; stream.Read(length, 0, length.Length); packet.AddRange(length); Array.Reverse(length); actualLength = BitConverter.ToUInt16(length, 0); } else if (pseudoLength == 127) { byte[] length = new byte[8]; stream.Read(length, 0, length.Length); packet.AddRange(length); Array.Reverse(length); actualLength = BitConverter.ToUInt64(length, 0); } byte[] mask = new byte[4]; if (masked) { stream.Read(mask, 0, mask.Length); packet.AddRange(mask); } if (actualLength > 0) { byte[] data = new byte[actualLength]; stream.Read(data, 0, data.Length); packet.AddRange(data); if (masked) { data = ApplyMask(data, mask); } messageBuffer.Write(data, 0, data.Length); } Console.WriteLine($@"RECV: {BitConverter.ToString(packet.ToArray())}"); if (!fin) { continue; } byte[] message = messageBuffer.ToArray(); switch (messageOpcode) { case 0x1: AnyMessageReceived?.Invoke(session, message); TextMessageReceived?.Invoke(session, Encoding.UTF8.GetString(message)); break; case 0x2: AnyMessageReceived?.Invoke(session, message); BinaryMessageReceived?.Invoke(session, Encoding.UTF8.GetString(message)); break; case 0x8: Close(); break; default: throw new Exception("Invalid opcode: " + messageOpcode); } messageBuffer.SetLength(0); } }
public void MessageReceiver(object sender, SPPMessage e) { BaseMessageParser parser = SPPMessageParserFactory.BuildParser(e); AnyMessageReceived?.Invoke(this, parser); switch (e.Id) { case SPPMessage.MessageIds.MSG_ID_RESET: ResetResponse?.Invoke(this, ((ResetResponseParser)parser).ResultCode); break; case SPPMessage.MessageIds.MSG_ID_FOTA_DEVICE_INFO_SW_VERSION: SwVersionResponse?.Invoke(this, ((SoftwareVersionOTAParser)parser).SoftwareVersion); break; case SPPMessage.MessageIds.MSG_ID_BATTERY_TYPE: BatteryTypeResponse?.Invoke(this, (BatteryTypeParser)parser); break; case SPPMessage.MessageIds.MSG_ID_AMBIENT_MODE_UPDATED: AmbientEnabledUpdateResponse?.Invoke(this, ((AmbientModeUpdateParser)parser).Enabled); break; case SPPMessage.MessageIds.MSG_ID_DEBUG_BUILD_INFO: BuildStringResponse?.Invoke(this, ((DebugBuildInfoParser)parser).BuildString); break; case SPPMessage.MessageIds.MSG_ID_DEBUG_GET_ALL_DATA: GetAllDataResponse?.Invoke(this, (DebugGetAllDataParser)parser); break; case SPPMessage.MessageIds.MSG_ID_DEBUG_SERIAL_NUMBER: SerialNumberResponse?.Invoke(this, (DebugSerialNumberParser)parser); break; case SPPMessage.MessageIds.MSG_ID_EXTENDED_STATUS_UPDATED: ExtendedStatusUpdate?.Invoke(this, (ExtendedStatusUpdateParser)parser); break; case SPPMessage.MessageIds.MSG_ID_FIND_MY_EARBUDS_STOP: FindMyGearStopped?.Invoke(this, null); break; case SPPMessage.MessageIds.MSG_ID_RESP: GenericResponse?.Invoke(this, (GenericResponseParser)parser); break; case SPPMessage.MessageIds.MSG_ID_SELF_TEST: SelfTestResponse?.Invoke(this, (SelfTestParser)parser); break; case SPPMessage.MessageIds.MSG_ID_SET_TOUCHPAD_OTHER_OPTION: OtherOption?.Invoke(this, ((SetOtherOptionParser)parser).OptionType); break; case SPPMessage.MessageIds.MSG_ID_STATUS_UPDATED: StatusUpdate?.Invoke(this, (StatusUpdateParser)parser); break; case SPPMessage.MessageIds.MSG_ID_USAGE_REPORT: UsageReport?.Invoke(this, (UsageReportParser)parser); break; case SPPMessage.MessageIds.MSG_ID_MUTE_EARBUD_STATUS_UPDATED: FindMyGearMuteUpdate?.Invoke(this, (MuteUpdateParser)parser); break; case SPPMessage.MessageIds.MSG_ID_ANC_STATUS_UPDATED: NoiseCancellingUpdated?.Invoke(this, ((NoiseCancellingUpdatedParser)parser).Enabled); break; } }
public void DispatchEvent(BaseMessageParser?parser, SPPMessage.MessageIds?ids = null) { AnyMessageReceived?.Invoke(this, parser); switch (ids ?? parser?.HandledType ?? 0) { case SPPMessage.MessageIds.RESET: ResetResponse?.Invoke(this, (parser as ResetResponseParser)?.ResultCode ?? -1); break; case SPPMessage.MessageIds.FOTA_DEVICE_INFO_SW_VERSION: SwVersionResponse?.Invoke(this, (parser as SoftwareVersionOTAParser)?.SoftwareVersion ?? "null"); break; case SPPMessage.MessageIds.BATTERY_TYPE: BatteryTypeResponse?.Invoke(this, (parser as BatteryTypeParser) !); break; case SPPMessage.MessageIds.AMBIENT_MODE_UPDATED: AmbientEnabledUpdateResponse?.Invoke(this, (parser as AmbientModeUpdateParser)?.Enabled ?? false); break; case SPPMessage.MessageIds.DEBUG_BUILD_INFO: BuildStringResponse?.Invoke(this, (parser as DebugBuildInfoParser)?.BuildString ?? "null"); break; case SPPMessage.MessageIds.DEBUG_GET_ALL_DATA: GetAllDataResponse?.Invoke(this, (parser as DebugGetAllDataParser) !); break; case SPPMessage.MessageIds.DEBUG_SERIAL_NUMBER: SerialNumberResponse?.Invoke(this, (parser as DebugSerialNumberParser) !); break; case SPPMessage.MessageIds.EXTENDED_STATUS_UPDATED: BaseUpdate?.Invoke(this, (parser as IBasicStatusUpdate) !); ExtendedStatusUpdate?.Invoke(this, (parser as ExtendedStatusUpdateParser) !); break; case SPPMessage.MessageIds.FIND_MY_EARBUDS_STOP: FindMyGearStopped?.Invoke(this, EventArgs.Empty); break; case SPPMessage.MessageIds.RESP: GenericResponse?.Invoke(this, (parser as GenericResponseParser) !); break; case SPPMessage.MessageIds.SELF_TEST: SelfTestResponse?.Invoke(this, (parser as SelfTestParser) !); break; case SPPMessage.MessageIds.SET_TOUCHPAD_OTHER_OPTION: OtherOption?.Invoke(this, (parser as SetOtherOptionParser) !.OptionType); break; case SPPMessage.MessageIds.STATUS_UPDATED: StatusUpdate?.Invoke(this, (parser as StatusUpdateParser) !); BaseUpdate?.Invoke(this, (parser as IBasicStatusUpdate) !); break; case SPPMessage.MessageIds.USAGE_REPORT: UsageReport?.Invoke(this, (parser as UsageReportParser) !); break; case SPPMessage.MessageIds.MUTE_EARBUD_STATUS_UPDATED: FindMyGearMuteUpdate?.Invoke(this, (parser as MuteUpdateParser) !); break; case SPPMessage.MessageIds.NOISE_REDUCTION_MODE_UPDATE: AncEnabledUpdateResponse?.Invoke(this, (parser as NoiseReductionModeUpdateParser)?.Enabled ?? false); break; case SPPMessage.MessageIds.NOISE_CONTROLS_UPDATE: NoiseControlUpdateResponse?.Invoke(this, (parser as NoiseControlUpdateParser)?.Mode ?? NoiseControlMode.Off); break; } }