private static ISockFilter DecodeCommandFilter(byte[] payload, byte type, byte length, int offset, out ObjectId?serverId) { if (type == 0) { //User ID, not targetting a server ObjectId user = BinaryTool.ReadMongoID(payload, offset); serverId = null; return(new UserSockFilter(user)); } else if (type == 1) { //User ID, targetting server ObjectId user = BinaryTool.ReadMongoID(payload, offset); serverId = BinaryTool.ReadMongoID(payload, offset + 12); return(new UserSockFilter(user)); } else if (type == 2) { //Server ID, all tribes serverId = BinaryTool.ReadMongoID(payload, offset); return(new ServerSockFilter(serverId.Value)); } else if (type == 3) { //Server ID, specific tribe serverId = BinaryTool.ReadMongoID(payload, offset); int tribeId = BinaryTool.ReadInt32(payload, offset + 12); return(new ServerTribeSockFilter(serverId.Value, tribeId)); } else { throw new Exception("Unknown filter type " + type + "!"); } }
/// <summary> /// Handles the first binary message we get. It will always be for authentication. /// </summary> /// <param name="data"></param> /// <param name="length"></param> /// <returns></returns> private async Task HandleAuthentication(byte[] data, int length) { //This message follows the following format: // 256 bytes: Authentication key // 8 bytes: Program identification name // 4 bytes: System version //Verify if (length != 256 + 8 + 4) { Log("AUTHENTICATION", "Authentication length mismatch!"); await DisconnectAsync(WebSocketCloseStatus.InvalidPayloadData, "DELTA_RPC_DISCONNECT_INVALID_AUTHENTICATION_PAYLOAD"); return; } //Extract info byte[] key = BinaryTool.CopyFromArray(data, 0, 256); program_identity = Encoding.ASCII.GetString(data, 256, 8); version = BinaryTool.ReadInt32(data, 264); //Validate the key if (!BinaryTool.CompareBytes(Program.master_key, key)) { authenticated = false; Log("AUTHENTICATION", "Authentication failed!"); await DisconnectAsync(WebSocketCloseStatus.PolicyViolation, "DELTA_RPC_DISCONNECT_INVALID_AUTHENTICATION_KEY"); return; } //We're now ready for authentication! authenticated = true; Log("AUTHENTICATION", "Authentication OK!"); await WriteResponse(0, 0); }
/// <summary> /// Handles an RPC message: opcode 1. This will fire events to clients by a filter /// </summary> /// <param name="data"></param> /// <param name="length"></param> /// <returns></returns> private async Task HandleRPCMessage(byte[] data, int length, ulong index) { //This follows the following format, starting at byte 10 // 4 bytes: int - Payload length "x" // x bytes: string - Payload // 2 bytes: ushort - Filter type // [Dependant on filter type] //Read the length of the payload and read the payload int payloadLength = BinaryTool.ReadInt32(data, 10); byte[] payload = BinaryTool.CopyFromArray(data, 14, payloadLength); Log("RPC-MESSAGE", "Payload length " + payloadLength); //Read the filter code ushort filterCode = BinaryTool.ReadUInt16(data, 14 + payloadLength); Log("RPC-MESSAGE", "Filter type " + filterCode); //Pack contents PackedWebSocketMessage packed = new PackedWebSocketMessage(payload, payloadLength, WebSocketMessageType.Text); //Read the filter and send messages Task pending; if (filterCode == 0) { //USER_ID - Read the user ID // 12 bytes: MongoDB ID - User ID ObjectId userId = BinaryTool.ReadMongoID(data, 14 + payloadLength + 2); pending = RPCEventDispatcher.SendDataToUserById(RPCType.RPCSession, userId, packed); } else if (filterCode == 1) { //SERVER - Sends to all members of a server // 12 bytes: MongoDB ID - Server ID ObjectId serverId = BinaryTool.ReadMongoID(data, 14 + payloadLength + 2); pending = RPCEventDispatcher.SendDataToServerById(RPCType.RPCSession, serverId, packed); } else if (filterCode == 2) { //SERVER_TRIBE - Sends to a tribe of a server // 12 bytes: MongoDB ID - Server ID // 4 bytes: Int - ARK Tribe ID ObjectId serverId = BinaryTool.ReadMongoID(data, 14 + payloadLength + 2); int tribeId = BinaryTool.ReadInt32(data, 14 + payloadLength + 2 + 12); pending = RPCEventDispatcher.SendDataToServerTribeById(RPCType.RPCSession, serverId, tribeId, packed); } else { await WriteResponse(index, 400); return; } //Wait for sending to complete Log("RPC-MESSAGE", "Sending message....pending..."); await pending; Log("RPC-MESSAGE", "Message sent OK!"); //Send OK await WriteResponse(index, 0); }