private void _Room(Connection connection, NetIncomingMessage inMessage) { RoomCommand command = RoomCommand.Unknown; try { command = (RoomCommand)inMessage.ReadByte(); } catch { } switch (command) { default: case RoomCommand.Unknown: break; case RoomCommand.Create: case RoomCommand.Destroy: // Unexpected break; case RoomCommand.Update: // Server to Client _handler.RoomOperation( RoomOperation.Update, new Room( connection.IPEndPoint.ToString().MD5String(), connection, new Packet(inMessage))); break; case RoomCommand.GetRoom: { string roomId = null; try { roomId = inMessage.ReadString(); } catch { } if (roomId == null) { break; } _handler.Room(new Room(roomId, null, new Packet(inMessage))); } break; case RoomCommand.GetRoomsPage: { byte reqId = 0; byte page = 0; byte pages = 0; byte roomCount = 0; try { reqId = inMessage.ReadByte(); page = inMessage.ReadByte(); pages = inMessage.ReadByte(); roomCount = inMessage.ReadByte(); } catch { } if (reqId == 0 || reqId != _roomsPageReqId || page == 0 || roomCount == 0) { return; } string[] roomIds = new string[roomCount]; try { for (int i = 0; i < roomCount; i++) { roomIds[i] = inMessage.ReadString(); } } catch { return; } _handler.RoomsPage(roomIds, page, pages); } break; case RoomCommand.Auth: // Master to Server { if (!IsHosting) { return; } IPEndPoint ipEndPoint = null; try { ipEndPoint = inMessage.ReadIPEndPoint(); } catch { } if (ipEndPoint == null) { return; } // Create auth string token = (ipEndPoint + DateTime.Now.ToString()).MD5String(); Pair <IPEndPoint, string> auth = new Pair <IPEndPoint, string>(ipEndPoint, token); lock (_auths) { Pair <IPEndPoint, string> oldAuth = _auths.FirstOrDefault(x => x.Left.Equals(ipEndPoint)); if (oldAuth != null) { _auths.Remove(oldAuth); } _auths.Add(auth); _authsCache = _auths.ToArray(); } // Send 'Hello' to client (NAT Punchthrough) byte[] data = "SA".GetBytes(); SendToForeign(ipEndPoint, data, 0, data.Length); // Send accept to Master NetOutgoingMessage outMessage = _peer.CreateMessage(); outMessage.Write((byte)DataType.Room); outMessage.Write((byte)RoomCommand.Accept); outMessage.Write(ipEndPoint); outMessage.Write(token); _master.NetConnection.SendMessage(outMessage, NetDeliveryMethod.ReliableOrdered, 0); } break; case RoomCommand.Connect: // Master to Client { string id = null; IPEndPoint ipEndPoint = null; string token = null; try { id = inMessage.ReadString(); ipEndPoint = inMessage.ReadIPEndPoint(); token = inMessage.ReadString(); } catch { } if (id == null || ipEndPoint == null || token == null || string.IsNullOrEmpty(_targetRoomId) || id != _targetRoomId || _joinPacket == null) { return; } // Connect to Server NetOutgoingMessage outMessage = _peer.CreateMessage(); outMessage.Write(token); _joinPacket.Serialize(outMessage); _server = new Connection(ConnectionType.Server, _peer.Connect(ipEndPoint, outMessage), ConnectionStatus.Connecting); _targetRoomId = null; _joinPacket = null; } break; } }
private void _Callback(object peer) { if (!IsAlive) { return; } try { NetIncomingMessage inMessage = _peer.ReadMessage(); if (inMessage == null) { return; } switch (inMessage.MessageType) { default: break; case NetIncomingMessageType.ConnectionApproval: // Client to Server { if (!IsHosting) { inMessage.SenderConnection.Deny("Peer not hosting!"); break; } string token = null; try { token = inMessage.ReadString(); } catch { } if (token == null) { inMessage.SenderConnection.Deny("Bad authentication data"); break; } Pair <IPEndPoint, string> auth = _authsCache.FirstOrDefault(x => x.Left.Equals(inMessage.SenderEndPoint)); if (auth == null) { inMessage.SenderConnection.Deny("Authentication not found"); break; } lock (_auths) { _auths.Remove(auth); _authsCache = _auths.ToArray(); } if (auth.Right != token) { inMessage.SenderConnection.Deny("Authentication failed"); break; } Connection connection = new Connection(ConnectionType.Client, inMessage.SenderConnection, ConnectionStatus.Connecting); Pair <bool, Packet> result = _handler.Login(connection, new Packet(inMessage)); if (result == null) { inMessage.SenderConnection.Deny("Failed to perform login"); break; } if (!result.Left) { if (string.IsNullOrEmpty(result.Right.GetString("Reason"))) { result.Right.SetString("Reason", "Login refused"); } inMessage.SenderConnection.Deny("_" + result.Right.ToBase64String()); break; } lock (_clients) { if (!_clients.Contains(connection)) { _clients.Add(connection); _clientsCache = _clients.ToArray(); } } inMessage.SenderConnection.Approve(); } break; case NetIncomingMessageType.StatusChanged: { NetConnectionStatus status = (NetConnectionStatus)inMessage.ReadByte(); if (status != NetConnectionStatus.Connected && status != NetConnectionStatus.Disconnected) { break; } Connection connection = null; if (_master != null && _master.IPEndPoint.Equals(inMessage.SenderEndPoint)) { connection = _master; } else if (_server != null && _server.IPEndPoint.Equals(inMessage.SenderEndPoint)) { connection = _server; } else { connection = _clientsCache.FirstOrDefault(x => x.IPEndPoint.Equals(inMessage.SenderEndPoint)); } if (connection == null) { if (status == NetConnectionStatus.Connected) { inMessage.SenderConnection.Disconnect("Connection not found"); } break; } if (status == NetConnectionStatus.Connected) { connection.Status = ConnectionStatus.Connected; _handler.Connect(connection); } else { // Drop/Remove connection by 'Type' switch (connection.Type) { case ConnectionType.Master: { _master = null; // Server if (IsHosting) { IsHosting = false; } _serverRoom = null; lock (_clients) { foreach (Connection conn in _clients) { conn.NetConnection.Disconnect("Server closed the room and connection"); conn.Status = ConnectionStatus.Disconnecting; } _clients.Clear(); _clientsCache = new Connection[0]; } lock (_auths) { _auths.Clear(); _authsCache = new Pair <IPEndPoint, string> [0]; } // Client if (_server != null) { _server.NetConnection.Disconnect("Left"); _server = null; } } break; case ConnectionType.Server: _server = null; break; case ConnectionType.Client: { lock (_clients) { if (_clients.Remove(connection)) { _clientsCache = _clients.ToArray(); } } } break; } connection.Status = ConnectionStatus.Disconnected; string reason = inMessage.ReadString(); if (reason.StartsWith("_")) { Packet packet = reason.Substring(1).ToPacket(); if (string.IsNullOrEmpty(packet.GetString("Reason"))) { packet.SetString("Reason", "Unknown"); } _handler.Disconnect(connection, packet); } else { Packet packet = new Packet(); packet.SetString("Reason", reason); _handler.Disconnect(connection, packet); } } } break; case NetIncomingMessageType.Data: { Connection connection = null; if (_master != null && _master.IPEndPoint.Equals(inMessage.SenderEndPoint)) { connection = _master; } else if (_server != null && _server.IPEndPoint.Equals(inMessage.SenderEndPoint)) { connection = _server; } else { connection = _clientsCache.FirstOrDefault(x => x.IPEndPoint.Equals(inMessage.SenderEndPoint)); } if (connection == null) { inMessage.SenderConnection.Disconnect("Connection not found"); break; } DataType type = DataType.Unknown; try { type = (DataType)inMessage.ReadByte(); } catch { } switch (type) { default: case DataType.Unknown: break; case DataType.Room: if (inMessage.DeliveryMethod == NetDeliveryMethod.ReliableOrdered || inMessage.DeliveryMethod == NetDeliveryMethod.ReliableSequenced) { _Room(connection, inMessage); } break; case DataType.Data: _handler.Data(connection, (Delivery)inMessage.DeliveryMethod, new Packet(inMessage), (Channel)inMessage.SequenceChannel); break; } } break; case NetIncomingMessageType.ConnectionLatencyUpdated: { Connection connection = null; if (_master != null && _master.IPEndPoint.Equals(inMessage.SenderEndPoint)) { connection = _master; } else if (_server != null && _server.IPEndPoint.Equals(inMessage.SenderEndPoint)) { connection = _server; } else { connection = _clientsCache.FirstOrDefault(x => x.IPEndPoint.Equals(inMessage.SenderEndPoint)); } if (connection == null) { inMessage.SenderConnection.Disconnect("Connection not found"); break; } connection.Latency = inMessage.ReadFloat(); _handler.Latency(connection, connection.Latency); } break; case NetIncomingMessageType.UnconnectedData: { _handler.ForeignData(inMessage.SenderEndPoint, inMessage.Data); } break; case NetIncomingMessageType.DebugMessage: _handler.Log(LogType.Info, inMessage.ReadString()); break; case NetIncomingMessageType.WarningMessage: _handler.Log(LogType.Warning, inMessage.ReadString()); break; case NetIncomingMessageType.ErrorMessage: _handler.Log(LogType.Error, inMessage.ReadString()); break; } _peer.Recycle(inMessage); } catch (Exception exception) { _Reset(); _handler.Terminate(true, exception); } }