private void ProcessConnectRequest( IPEndPoint remoteEndPoint, NetPeer netPeer, NetConnectRequestPacket connRequest) { byte connectionNumber = connRequest.ConnectionNumber; NetUtils.DebugWrite("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}", netPeer.ConnectId, connRequest.ConnectionId, remoteEndPoint); //if we have peer if (netPeer != null) { var processResult = netPeer.ProcessConnectRequest(connRequest); switch (processResult) { case ConnectRequestResult.Reconnection: _connectedPeersCount--; CreateEvent(NetEvent.EType.Disconnect, netPeer, disconnectReason: DisconnectReason.RemoteConnectionClose); _peers.RemovePeer(netPeer); //go to new connection break; case ConnectRequestResult.NewConnection: _peers.RemovePeer(netPeer); //go to new connection break; case ConnectRequestResult.P2PConnection: CreateEvent( NetEvent.EType.ConnectionRequest, connectionRequest: new ConnectionRequest( netPeer.ConnectId, connectionNumber, ConnectionRequestType.PeerToPeer, connRequest.Data, netPeer, this) ); return; default: //no operations needed return; } //ConnectRequestResult.NewConnection //Set next connection number connectionNumber = (byte)((netPeer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber); //To reconnect peer } //Add new peer and craete ConnectRequest event NetUtils.DebugWrite("[NM] Creating request event: " + connRequest.ConnectionId); netPeer = new NetPeer(this, remoteEndPoint); if (_peers.TryAdd(netPeer)) { CreateEvent(NetEvent.EType.ConnectionRequest, connectionRequest: new ConnectionRequest( connRequest.ConnectionId, connectionNumber, ConnectionRequestType.Incoming, connRequest.Data, netPeer, this)); } }
private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEndPoint) { #if STATS_ENABLED Statistics.PacketsReceived++; Statistics.BytesReceived += (uint)count; #endif //Try read packet NetPacket packet = NetPacketPool.GetPacket(count, false); if (!packet.FromBytes(reusableBuffer, 0, count)) { NetPacketPool.Recycle(packet); NetUtils.DebugWriteError("[NM] DataReceived: bad!"); return; } //Check unconnected switch (packet.Property) { case PacketProperty.DiscoveryRequest: if (DiscoveryEnabled) { var netEvent = CreateEvent(NetEventType.DiscoveryRequest); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count); EnqueueEvent(netEvent); } return; case PacketProperty.DiscoveryResponse: { var netEvent = CreateEvent(NetEventType.DiscoveryResponse); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count); EnqueueEvent(netEvent); } return; case PacketProperty.UnconnectedMessage: if (UnconnectedMessagesEnabled) { var netEvent = CreateEvent(NetEventType.ReceiveUnconnected); netEvent.RemoteEndPoint = remoteEndPoint; netEvent.DataReader.SetSource(packet.RawData, NetConstants.HeaderSize, count); EnqueueEvent(netEvent); } return; case PacketProperty.NatIntroduction: case PacketProperty.NatIntroductionRequest: case PacketProperty.NatPunchMessage: { if (NatPunchEnabled) { NatPunchModule.ProcessMessage(remoteEndPoint, packet); } return; } } //Check normal packets NetPeer netPeer; bool isPeerConnecting; lock (_connectingPeers) { isPeerConnecting = _connectingPeers.Contains(remoteEndPoint); _peers.TryGetValue(remoteEndPoint, out netPeer); } if (netPeer != null) { if (netPeer.ConnectionState == ConnectionState.Disconnected) { return; } NetEvent netEvent; switch (packet.Property) { case PacketProperty.Disconnect: if (netPeer.ConnectionState == ConnectionState.InProgress || netPeer.ConnectionState == ConnectionState.Connected) { if (BitConverter.ToInt64(packet.RawData, 1) != netPeer.ConnectId) { //Old or incorrect disconnect NetPacketPool.Recycle(packet); return; } netEvent = CreateEvent(NetEventType.Disconnect); netEvent.Peer = netPeer; netEvent.DataReader.SetSource(packet.RawData, 9, packet.Size); netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose; EnqueueEvent(netEvent); netPeer.ProcessPacket(packet); SendRaw(new[] { (byte)PacketProperty.ShutdownOk }, 0, 1, remoteEndPoint); } return; case PacketProperty.ConnectAccept: if (netPeer.ProcessConnectAccept(packet)) { var connectEvent = CreateEvent(NetEventType.Connect); connectEvent.Peer = netPeer; EnqueueEvent(connectEvent); } return; case PacketProperty.ConnectRequest: long newId = BitConverter.ToInt64(packet.RawData, NetConstants.RequestConnectIdIndex); NetUtils.DebugWrite("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}", netPeer.ConnectId, newId, remoteEndPoint); //Remove old peer and connect new if (newId > netPeer.ConnectId) { netEvent = CreateEvent(NetEventType.Disconnect); netEvent.Peer = netPeer; netEvent.DataReader.SetSource(packet.RawData, 9, packet.Size); netEvent.DisconnectReason = DisconnectReason.RemoteConnectionClose; _peers.RemovePeer(netPeer); break; //To reconnect peer } else { //Just answer accept netPeer.ProcessPacket(packet); return; } default: netPeer.ProcessPacket(packet); return; } } //Unacked shutdown if (packet.Property == PacketProperty.Disconnect) { SendRaw(new[] { (byte)PacketProperty.ShutdownOk }, 0, 1, remoteEndPoint); return; } if (packet.Property == PacketProperty.ConnectRequest && packet.Size >= 12) { NetUtils.DebugWrite("[NM] Received ConnectionRequest"); if (isPeerConnecting) { NetUtils.DebugWrite("[NM] Peer already connecting"); return; } if (GetPeersCount(ConnectionState.Connected | ConnectionState.InProgress) < _maxConnections) { int protoId = BitConverter.ToInt32(packet.RawData, 1); if (protoId != NetConstants.ProtocolId) { NetUtils.DebugWrite(ConsoleColor.Cyan, "[NM] Peer connect reject. Invalid protocol ID: " + protoId); return; } //Getting new id for peer long connectionId = BitConverter.ToInt64(packet.RawData, 5); // Read data and create request var reader = new NetDataReader(null, 0, 0); if (packet.Size > 12) { reader.SetSource(packet.RawData, 13, packet.Size); } NetUtils.DebugWrite("[NM] Creating request event: " + connectionId); lock (_connectingPeers) { _connectingPeers.Add(remoteEndPoint); } var netEvent = CreateEvent(NetEventType.ConnectionRequest); netEvent.ConnectionRequest = new ConnectionRequest(connectionId, remoteEndPoint, reader, OnConnectionSolved); EnqueueEvent(netEvent); } } }