/// <summary> /// Callback to <code>TcpClient.BeginReceive</code>. If we are accepting connections (<see cref="AcceptingConnections"/>), /// and the sender is <see cref="InviteStatus.None"/>, their invite is registered /// </summary> private void AcceptConnection(IAsyncResult result) { TcpClient client = _listener.EndAcceptTcpClient(result); _listener.BeginAcceptTcpClient(AcceptConnection, null); IPEndPoint player = (IPEndPoint)client.Client.RemoteEndPoint; var wrapper = new TcpWrapper <GameInitializationPacket>(client); if (!AcceptingConnections) { Program.Log(this).Warning("TcpListener recieved connection while not AcceptingConnections"); wrapper.Send(new GameInitializationPacket(InitRequest.Reject)); wrapper.Dispose(); return; } // can only accept invitations from remotes with no preexisting invites if (!_connections.ContainsKey(player) || _connections[player].Item1 == InviteStatus.None) { _connections[player] = Tuple.Create(InviteStatus.SentByRemote, wrapper); // If a withdrawal is received wrapper.ReceiveEvent += () => { wrapper.Dispose(); _connections[player] = NewEmptyConnection(); }; } else { Program.Log(this).Warning("TcpListener received invalid request"); } }
internal void SendInvitationTo(IPEndPoint player) { if (_connections[player].Item1 != InviteStatus.None) { throw new ArgumentException("Passed player must not be invited/have invited us"); } TcpClient client = new TcpClient(); client.Connect(player); var wrapper = new TcpWrapper <GameInitializationPacket>(client); wrapper.ReceiveEvent += () => { while (wrapper.Received.Any()) { GameInitializationPacket packet; wrapper.Received.TryDequeue(out packet); switch (packet.Request) { case InitRequest.Accept: JoinGameWith(player); break; case InitRequest.Reject: wrapper.Dispose(); _connections[player] = NewEmptyConnection(); break; } } }; _connections[player] = Tuple.Create(InviteStatus.SentByUs, wrapper); }
/// <summary> /// Helper function for withdrawing and rejecting, i.e. when something is sent to a player before closing the connection /// </summary> private void SendAndClose(IPEndPoint player, InviteStatus expectedStatus, InitRequest request) { if (expectedStatus == InviteStatus.SentByUs && _connections[player].Item1 != InviteStatus.SentByUs) { throw new ArgumentException("Passed player must already be invited"); } if (expectedStatus == InviteStatus.SentByRemote && _connections[player].Item1 != InviteStatus.SentByRemote) { throw new ArgumentException("Passed player must already have sent an invitation"); } TcpWrapper <GameInitializationPacket> wrapper = _connections[player].Item2; wrapper.Send(new GameInitializationPacket(request)); wrapper.Dispose(); _connections[player] = NewEmptyConnection(); }