public DownstreamPayload Decode(byte[] bytes) { var(headerLength, payloadLength) = DecodeLengths(bytes); PacketHeader header = DecodeHeader(bytes, headerLength, PrintHeader); byte[] payload; if (header.EncryptionMode == PacketHeader.Types.EncryptionMode.KEncryptionNone) { payload = new byte[payloadLength]; Array.Copy(bytes, Offset + headerLength, payload, 0, payloadLength); } else { var key = header.EncryptionMode == PacketHeader.Types.EncryptionMode.KEncryptionServiceToken ? SecurityKey : SessionKey; payload = Decrypt(bytes, headerLength, payloadLength, key); } if (payload.Length != header.DecodedPayloadLen) { #if DEBUG Console.WriteLine("Payload length does not match"); Console.WriteLine(Convert.ToBase64String(payload)); #endif return(null); } DownstreamPayload downstream = DownstreamPayload.Parser.ParseFrom(payload); if (downstream.Command == "Push.ZtLiveInteractive.Message") { HeaderSeqId = header.SeqId; } return(downstream); }
async void HandleCommand(DownstreamPayload stream, System.Timers.Timer heartbeatTimer) { if (stream == null) { return; } switch (stream.Command) { case Command.GLOBAL_COMMAND: ZtLiveCsCmdAck cmd = ZtLiveCsCmdAck.Parser.ParseFrom(stream.PayloadData); switch (cmd.CmdAckType) { case GlobalCommand.ENTER_ROOM_ACK: var enterRoom = ZtLiveCsEnterRoomAck.Parser.ParseFrom(cmd.Payload); heartbeatTimer.Interval = enterRoom.HeartbeatIntervalMs; heartbeatTimer.Start(); break; case GlobalCommand.HEARTBEAT_ACK: var heartbeat = ZtLiveCsHeartbeatAck.Parser.ParseFrom(cmd.Payload); break; default: Console.WriteLine("Unhandled Global.ZtLiveInteractive.CsCmd: {0}", cmd.CmdAckType); Console.WriteLine(cmd); break; } break; case Command.KEEP_ALIVE: var keepalive = KeepAliveResponse.Parser.ParseFrom(stream.PayloadData); break; case Command.PING: var ping = PingResponse.Parser.ParseFrom(stream.PayloadData); break; case Command.UNREGISTER: var unregister = UnregisterResponse.Parser.ParseFrom(stream.PayloadData); await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Unregister", default); break; case Command.PUSH_MESSAGE: if (client.State == WebSocketState.Open) { await client.SendAsync(PushMessage(), WebSocketMessageType.Binary, true, default); } ZtLiveScMessage message = ZtLiveScMessage.Parser.ParseFrom(stream.PayloadData); var payload = message.CompressionType == ZtLiveScMessage.Types.CompressionType.Gzip ? Decompress(message.Payload) : message.Payload; switch (message.MessageType) { case Enums.PushMessage.ACTION_SIGNAL: // Handled by user Handler(message.MessageType, payload.ToByteArray()); break; case Enums.PushMessage.STATE_SIGNAL: // Handled by user Handler(message.MessageType, payload.ToByteArray()); break; case Enums.PushMessage.STATUS_CHANGED: var statusChanged = ZtLiveScStatusChanged.Parser.ParseFrom(payload); if (statusChanged.Type == ZtLiveScStatusChanged.Types.Type.LiveClosed || statusChanged.Type == ZtLiveScStatusChanged.Types.Type.LiveBanned) { await Stop("Live closed"); } break; case Enums.PushMessage.TICKET_INVALID: var ticketInvalid = ZtLiveScTicketInvalid.Parser.ParseFrom(payload); TicketIndex = (TicketIndex + 1) % Tickets.Length; await client.SendAsync(EnterRoom(), WebSocketMessageType.Binary, true, default); break; } break; default: if (stream.ErrorCode > 0) { Console.WriteLine("Error: {0} - {1}", stream.ErrorCode, stream.ErrorMsg); Console.WriteLine(stream.ErrorData.ToBase64()); } else { Console.WriteLine("Unhandled DownstreamPayload command: {0}", stream.Command); Console.WriteLine(stream); } break; } }