Exemple #1
0
        public void EncryptedReliableMessage(IChannelHandlerContext context, ProudSession session, EncryptedReliableMessage message)
        {
            Crypt crypt;
            // TODO Decrypt P2P
            //if (message.IsRelayed)
            //{
            //    //var remotePeer = (ServerRemotePeer)session.P2PGroup?.Members.GetValueOrDefault(message.TargetHostId);
            //    //if (remotePeer == null)
            //    //    return;

            //    //encryptContext = remotePeer.EncryptContext;
            //    //if (encryptContext == null)
            //    //    throw new ProudException($"Received encrypted message but the remote peer has no encryption enabled");
            //}
            //else
            {
                crypt = session.Crypt;
            }

            var buffer = context.Allocator.Buffer(message.Data.Length);

            using (var src = new MemoryStream(message.Data))
                using (var dst = new WriteOnlyByteBufferStream(buffer, false))
                    crypt.Decrypt(src, dst, true);

            context.Channel.Pipeline.Context <ProudFrameDecoder>().FireChannelRead(buffer);
        }
Exemple #2
0
        public void UnreliablePingHandler(IChannelHandlerContext context, ProudSession session, UnreliablePingMessage message)
        {
            session.UnreliablePing = TimeSpan.FromSeconds(message.Ping).TotalMilliseconds;
            var ts = DateTime.Now - _startTime.Value;

            session.SendUdpIfAvailableAsync(new UnreliablePongMessage(message.ClientTime, ts.TotalSeconds));
        }
Exemple #3
0
        public void ReliableRelayHandler(IChannel channel, ProudSession session, ReliableRelay1Message message)
        {
            if (session.P2PGroup == null)
            {
                return;
            }

            foreach (var destination in message.Destination.Where(d => d.HostId != session.HostId))
            {
                if (session.P2PGroup == null)
                {
                    //Logger<>.Debug($"Client {session.HostId} is not in a P2PGroup");
                    return;
                }

                if (!session.P2PGroup.Members.ContainsKey(destination.HostId))
                {
                    //Logger<>.Debug($"Client {session.HostId} trying to relay to non existant {destination.HostId}");
                    return;
                }

                var target = _server.Sessions.GetValueOrDefault(destination.HostId);
                target?.SendAsync(new ReliableRelay2Message(new RelayDestinationDto(session.HostId, destination.FrameNumber), message.Data));
            }
        }
Exemple #4
0
        public void PeerUdp_NotifyHolepunchSuccess(IChannel channel, ProudSession session, PeerUdp_NotifyHolepunchSuccessMessage message)
        {
            session.Logger?.Debug("PeerUdp_NotifyHolepunchSuccess={@Message}", message);
            if (!session.UdpEnabled || !_server.UdpSocketManager.IsRunning)
            {
                return;
            }

            var remotePeer      = session.P2PGroup.Members[session.HostId];
            var connectionState = remotePeer.ConnectionStates.GetValueOrDefault(message.HostId);

            connectionState.PeerUdpHolepunchSuccess = true;
            connectionState.LocalEndPoint           = message.LocalEndPoint;
            connectionState.EndPoint = message.EndPoint;
            var connectionStateB = connectionState.RemotePeer.ConnectionStates[session.HostId];

            if (connectionStateB.PeerUdpHolepunchSuccess)
            {
                remotePeer.SendAsync(new RequestP2PHolepunchMessage(message.HostId, connectionStateB.LocalEndPoint, connectionStateB.EndPoint));
                connectionState.RemotePeer.SendAsync(new RequestP2PHolepunchMessage(session.HostId, connectionState.LocalEndPoint, connectionState.EndPoint));

                //remotePeer.SendAsync(new RequestP2PHolepunchMessage(message.HostId, message.LocalEndPoint, new IPEndPoint(message.EndPoint.Address, message.LocalEndPoint.Port)));
                //connectionState.RemotePeer.SendAsync(new RequestP2PHolepunchMessage(session.HostId, session.UdpLocalEndPoint, new IPEndPoint(session.UdpEndPoint.Address, session.UdpLocalEndPoint.Port)));
                //remotePeer.SendAsync(new RequestP2PHolepunchMessage(message.HostId, message.LocalEndPoint, message.EndPoint));
                //connectionState.RemotePeer.SendAsync(new RequestP2PHolepunchMessage(session.HostId, session.UdpLocalEndPoint, session.UdpEndPoint));
            }
        }
        public void P2P_NotifyDirectP2PDisconnected(ProudSession session, P2P_NotifyDirectP2PDisconnectedMessage message)
        {
            if (session.P2PGroup == null)
            {
                return;
            }

            session.Logger?.Debug("P2P_NotifyDirectP2PDisconnected {@Message}", message);
            var remotePeer = session.P2PGroup.Members.GetValueOrDefault(session.HostId);
            var stateA     = remotePeer?.ConnectionStates.GetValueOrDefault(message.RemotePeerHostId);
            var stateB     = stateA?.RemotePeer.ConnectionStates.GetValueOrDefault(session.HostId);

            if (stateA?.HolepunchSuccess == true)
            {
                session.Logger?.Information("P2P to {TargetHostId} disconnected with {Reason}", message.RemotePeerHostId, message.Reason);
                stateA.HolepunchSuccess = false;
                stateA.RemotePeer.SendAsync(
                    new P2P_NotifyDirectP2PDisconnected2Message(session.HostId, message.Reason));
            }

            if (stateB?.HolepunchSuccess == true)
            {
                stateB.HolepunchSuccess = false;
            }
        }
Exemple #6
0
        public void P2PGroupMemberJoinAck(ProudSession session, P2PGroup_MemberJoin_AckMessage message)
        {
            session.Logger?.Debug("P2PGroupMemberJoinAck {@Message}", message);
            if (session.P2PGroup == null || session.HostId == message.AddedMemberHostId)
            {
                return;
            }

            var remotePeer = session.P2PGroup?.Members[session.HostId];

            if (remotePeer != null)
            {
                //using (remotePeer._sync.Lock())
                {
                    var stateA = remotePeer.ConnectionStates?.GetValueOrDefault(message.AddedMemberHostId);
                    if (stateA?.EventId != message.EventId)
                    {
                        return;
                    }

                    stateA.IsJoined = true;
                    var stateB = stateA.RemotePeer?.ConnectionStates?.GetValueOrDefault(session.HostId);
                    if (stateB?.IsJoined == true)
                    {
                        session.Logger?.Debug("Initialize P2P with {TargetHostId}", stateA.RemotePeer.HostId);
                        stateA.RemotePeer.Session.Logger?.Debug("Initialize P2P with {TargetHostId}", session.HostId);
                        stateA.LastHolepunch = stateB.LastHolepunch = DateTimeOffset.Now;
                        stateA.IsInitialized = stateB.IsInitialized = true;
                        remotePeer.SendAsync(new P2PRecycleCompleteMessage(stateA.RemotePeer.HostId));
                        stateA.RemotePeer?.SendAsync(new P2PRecycleCompleteMessage(session.HostId));
                    }
                }
            }
        }
        public void RmiMessage(ProudSession session, RmiMessage message, MessageReceivedEventArgs e)
        {
            var rmiId = BitConverter.ToUInt16(message.Data, 0);

            if (rmiId >= 60000)
            {
                using (var r = message.Data.ToBinaryReader())
                {
                    var opCode       = r.ReadEnum <ProudOpCode>();
                    var proudMessage = ProudMapper.GetMessage(opCode, r);

                    if (!r.IsEOF())
#if DEBUG
                    {
                        r.BaseStream.Position = 0;
                        throw new ProudBadFormatException(proudMessage.GetType(), r.ReadToEnd());
                    }
#else
                    { throw new ProudBadFormatException(proudMessage.GetType()); }
#endif
                    e.Message = proudMessage;
                    OnProudMessageReceived(e);
                }
                return;
            }

            e.Message = new ProudRmiMessage(message.Data);
            _filter.NextOnMessageReceived(e);
        }
Exemple #8
0
        public async Task DataHandler(AuthServer server, ProudSession session)
        {
            foreach (var xbn in Enum.GetValues(typeof(XBNType)).Cast <XBNType>().ToList())
            {
                if (Program.XBNdata.TryGetValue(xbn, out var xbninfo))
                {
                    var readoffset = 0;
                    while (readoffset != xbninfo.Length)
                    {
                        var size = xbninfo.Length - readoffset;

                        if (size > 40000)
                        {
                            size = 40000;
                        }

                        var data = new byte[size];
                        Array.Copy(xbninfo, readoffset, data, 0, size);

                        session.SendAsync(new GameDataAckMessage((uint)xbn, data, (uint)xbninfo.Length), SendOptions.ReliableSecureCompress).Wait();
                        readoffset += size;
                    }
                }
            }
        }
Exemple #9
0
        public void DataHandler(AuthServer server, ProudSession session)
        {
            string file1  = System.IO.File.ReadAllText(@"XBNFILE_1");
            string file2  = System.IO.File.ReadAllText(@"XBNFILE_2");
            string file3  = System.IO.File.ReadAllText(@"XBNFILE_3");
            string file4  = System.IO.File.ReadAllText(@"XBNFILE_4");
            string file5  = System.IO.File.ReadAllText(@"XBNFILE_5");
            string file6  = System.IO.File.ReadAllText(@"XBNFILE_6");
            string file7  = System.IO.File.ReadAllText(@"XBNFILE_7");
            string file8  = System.IO.File.ReadAllText(@"XBNFILE_8");
            string file9  = System.IO.File.ReadAllText(@"XBNFILE_9");
            string file10 = System.IO.File.ReadAllText(@"XBNFILE_10");
            string file11 = System.IO.File.ReadAllText(@"XBNFILE_11");
            string file12 = System.IO.File.ReadAllText(@"XBNFILE_12");
            string file13 = System.IO.File.ReadAllText(@"XBNFILE_13");
            string file14 = System.IO.File.ReadAllText(@"XBNFILE_14");
            string file15 = System.IO.File.ReadAllText(@"XBNFILE_15");


            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file1)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file2)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file3)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file4)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file5)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file6)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file7)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file8)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file9)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file10)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file11)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file12)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file13)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file14)), SendOptions.ReliableCompress);
            session.SendAsync(new GameDataAckMessage(HexStringToByteArray(file15)), SendOptions.ReliableCompress);
        }
Exemple #10
0
        public void NotifyCSEncryptedSessionKeyMessage(ProudServer server, ProudSession session, NotifyCSEncryptedSessionKeyMessage message)
        {
            session.Logger?.Verbose("Handshake:NotifyCSEncryptedSessionKey");
            var secureKey = server.Rsa.Decrypt(message.SecureKey, true);

            session.Crypt = new Crypt(secureKey);
            session.SendAsync(new NotifyCSSessionKeySuccessMessage());
        }
        public void UnreliableRelayHandler(ProudSession session, UnreliableRelay1Message message, MessageReceivedEventArgs e)
        {
            foreach (var destination in message.Destination.Where(id => id != session.HostId))
            {
                if (session.P2PGroup == null)
                {
                    Logger.Debug()
                    .Message("Client {0} in not a p2pgroup", session.HostId)
                    .Write();
                    return;
                }

                if (!session.P2PGroup.Members.ContainsKey(destination))
                {
                    Logger.Debug()
                    .Message("Client {0} trying to relay to non existant {1}", session.HostId, destination)
                    .Write();
                    return;
                }

                if (destination == 2)
                {
                    #region Hardcoded ServerMember

                    ProudCoreOpCode opCode;
                    byte[]          data;
                    using (var r = message.Data.ToBinaryReader())
                    {
                        opCode = r.ReadEnum <ProudCoreOpCode>();
                        data   = r.ReadToEnd();
                    }

                    if (opCode == ProudCoreOpCode.Rmi)
                    {
                        var core = new RmiMessage(data)
                        {
                            IsRelayed    = true,
                            SenderHostId = session.HostId,
                            TargetHostId = destination
                        };
                        e.Message = core;
                        _filter.OnMessageReceived(e);
                    }
                    else
                    {
                        throw new ProudException($"Invalid opCode {opCode}");
                    }

                    #endregion
                }
                else
                {
                    var target = _filter.SessionLookupByHostId.GetValueOrDefault(destination);
                    target?.Send(new UnreliableRelay2Message(session.HostId, message.Data));
                }
            }
        }
Exemple #12
0
        protected override void OnDisconnected(ProudSession session)
        {
            try
            {
                var gameSession = (GameSession)session;
                if (gameSession.Player != null)
                {
                    using (var db = AuthDatabase.Open())
                    {
                        var accountDto = DbUtil.Find <AccountDto>(db, statement => statement
                                                                  .Include <BanDto>(join => join.LeftOuterJoin())
                                                                  .Where($"{nameof(AccountDto.Id):C} = @Id")
                                                                  .WithParameters(new { Id = gameSession.Player.Account.Id }))
                                         .FirstOrDefault();

                        accountDto.IsConnect = false;
                        accountDto.IsServer  = true;
                        db.Update(accountDto);
                    }

                    gameSession.Player.Room?.Leave(gameSession.Player);
                    gameSession.Player.Channel?.Leave(gameSession.Player);
                    gameSession.Player.Save();

                    PlayerManager.Remove(gameSession.Player);

                    Logger.ForAccount(gameSession.Player)
                    .Information($"Client {session.RemoteEndPoint} disconnected");

                    if (gameSession.Player.ChatSession != null)
                    {
                        Club.LogOff(gameSession.Player);
                        gameSession.Player.ChatSession.GameSession = null;
                        gameSession.Player.ChatSession.Dispose();
                    }

                    if (gameSession.Player.RelaySession != null)
                    {
                        gameSession.Player.RelaySession.GameSession = null;
                        gameSession.Player.RelaySession.Dispose();
                    }

                    gameSession.Player.Session      = null;
                    gameSession.Player.ChatSession  = null;
                    gameSession.Player.RelaySession = null;
                    gameSession.Player.Dispose();
                    gameSession.Player = null;
                }
            }
            catch (Exception e)
            {
                Logger.Error(e.ToString());
            }

            base.OnDisconnected(session);
        }
Exemple #13
0
        public void ServerHolepunch(ProudServer server, ProudSession session, ServerHolepunchMessage message)
        {
            session.Logger?.Debug("ServerHolepunch={@Message}", message);
            if (session.P2PGroup == null || !_server.UdpSocketManager.IsRunning || session.HolepunchMagicNumber != message.MagicNumber)
            {
                return;
            }

            session.SendUdpAsync(new ServerHolepunchAckMessage(session.HolepunchMagicNumber, session.UdpEndPoint));
        }
        public void C2S_CreateUdpSocketAck(ProudServer server, ProudSession session, C2S_CreateUdpSocketAckMessage message)
        {
            if (session.P2PGroup == null || session.UdpSocket == null || !server.UdpSocketManager.IsRunning)
            {
                return;
            }

            //Logger<>.Debug($"Client:{session.HostId} - Starting server holepunch");
            session.SendAsync(new RequestStartServerHolepunchMessage(session.HolepunchMagicNumber));
        }
        public void C2S_CreateUdpSocketAck(ProudSession session, C2S_CreateUdpSocketAckMessage message)
        {
            if (session.P2PGroup == null || _filter.Config.UdpListener == null)
            {
                return;
            }

            Logger.Debug($"Client:{session.HostId} - Starting server holepunch");
            session.Send(new RequestStartServerHolepunchMessage(session.Guid));
        }
        public void NotifyHolepunchSuccess(ProudServer server, ProudSession session, ServerHolepunchMessage message)
        {
            if (session.P2PGroup == null || !_server.UdpSocketManager.IsRunning || session.HolepunchMagicNumber != message.MagicNumber)
            {
                return;
            }

            //Logger<>.Debug($"Client:{session.HostId} - Server holepunch success(EndPoint:{message.EndPoint} LocalEndPoint:{message.LocalEndPoint})");

            session.SendUdpAsync(new ServerHolepunchAckMessage(session.HolepunchMagicNumber, session.UdpEndPoint));
        }
Exemple #17
0
        public void C2S_CreateUdpSocketAck(ProudServer server, ProudSession session, C2S_CreateUdpSocketAckMessage message)
        {
            session.Logger?.Debug("{@Message}", message);
            if (session.P2PGroup == null || session.UdpSocket == null || session.UdpEnabled ||
                !server.UdpSocketManager.IsRunning)
            {
                return;
            }

            session.SendAsync(new RequestStartServerHolepunchMessage(session.HolepunchMagicNumber));
        }
        public void NotifyCSEncryptedSessionKeyMessage(ProudServer server, ProudSession session, NotifyCSEncryptedSessionKeyMessage message)
        {
            var secureKey = server.Rsa.Decrypt(message.SecureKey, true);

            session.Crypt = new Crypt(secureKey);

            var fastKey = session.Crypt.AES.Decrypt(message.FastKey);

            session.Crypt.InitializeFastEncryption(fastKey);
            session.SendAsync(new NotifyCSSessionKeySuccessMessage());
        }
Exemple #19
0
        public void UnreliablePingHandler(ProudSession session, UnreliablePingMessage message, RecvContext recvContext)
        {
            session.UnreliablePing = TimeSpan.FromSeconds(message.Ping).TotalMilliseconds;
            if (recvContext.UdpEndPoint != null)
            {
                session.LastUdpPing = DateTimeOffset.Now;
            }

            var ts = DateTime.Now - _startTime.Value;

            session.SendUdpIfAvailableAsync(new UnreliablePongMessage(message.ClientTime, ts.TotalSeconds));
        }
        public void C2S_RequestCreateUdpSocket(ProudSession session)
        {
            if (session.P2PGroup == null || _filter.Config.UdpListener == null)
            {
                return;
            }

            Logger.Debug($"Client:{session.HostId} - Requesting UdpSocket");
            var endPoint = new IPEndPoint(_filter.Config.UdpAddress, _filter.Config.UdpListener.Port);

            session.Send(new S2C_RequestCreateUdpSocketMessage(endPoint));
        }
Exemple #21
0
        public void NotifyHolepunchSuccess(ProudServer server, ProudSession session, NotifyHolepunchSuccessMessage message)
        {
            session.Logger?.Debug("NotifyHolepunchSuccess={@Message}", message);
            if (session.P2PGroup == null || !_server.UdpSocketManager.IsRunning || session.HolepunchMagicNumber != message.MagicNumber)
            {
                return;
            }

            session.LastUdpPing      = DateTimeOffset.Now;
            session.UdpEnabled       = true;
            session.UdpLocalEndPoint = message.LocalEndPoint;
            session.SendUdpAsync(new NotifyClientServerUdpMatchedMessage(message.MagicNumber));
        }
Exemple #22
0
        public void C2S_RequestCreateUdpSocket(ProudServer server, ProudSession session)
        {
            session.Logger?.Debug("C2S_RequestCreateUdpSocket");
            if (session.P2PGroup == null || session.UdpEnabled || !server.UdpSocketManager.IsRunning)
            {
                return;
            }

            var socket = server.UdpSocketManager.NextSocket();

            session.UdpSocket            = socket;
            session.HolepunchMagicNumber = Guid.NewGuid();
            session.SendAsync(new S2C_RequestCreateUdpSocketMessage(new IPEndPoint(server.UdpSocketManager.Address, ((IPEndPoint)socket.Channel.LocalAddress).Port)));
        }
        public void C2S_RequestCreateUdpSocket(ProudServer server, ProudSession session)
        {
            if (session.P2PGroup == null || !server.UdpSocketManager.IsRunning)
            {
                return;
            }

            // TODO: Don't assign a new socket when the client already has a active socket
            //Logger<>.Debug($"Client:{session.HostId} - Requesting UdpSocket");
            var socket = server.UdpSocketManager.NextSocket();

            session.UdpSocket            = socket;
            session.HolepunchMagicNumber = Guid.NewGuid();
            session.SendAsync(new S2C_RequestCreateUdpSocketMessage(new IPEndPoint(server.UdpSocketManager.Address, ((IPEndPoint)socket.Channel.LocalAddress).Port)));
        }
        protected override void OnDisconnected(ProudSession session)
        {
            var relaySession = (RelaySession)session;

            if (relaySession.GameSession != null && relaySession.Player != null)
            {
                if (relaySession.Player.Room != null)
                {
                    relaySession.GameSession.Dispose();
                }
            }

            relaySession.GameSession = null;
            base.OnDisconnected(session);
        }
        public void PeerUdp_NotifyHolepunchSuccess(ProudSession session, PeerUdp_NotifyHolepunchSuccessMessage message)
        {
            if (!session.UdpEnabled || _filter.Config.UdpListener == null)
            {
                return;
            }

            Logger.Debug($"Client:{session.HostId} - Peer server holepunch success(EndPoint:{message.EndPoint} LocalEndPoint:{message.LocalEndPoint})");

            // ToDo Refactor this shit...
            Task.Delay(2000).ContinueWith(_ =>
            {
                session.Send(new RequestP2PHolepunchMessage(message.HostId, message.LocalEndPoint, message.EndPoint));
            });
        }
        public void NotifyHolepunchSuccess(ProudSession session, NotifyHolepunchSuccessMessage message)
        {
            if (session.P2PGroup == null || _filter.Config.UdpListener == null || session.Guid != message.MagicNumber)
            {
                return;
            }

            Logger.Debug($"Client:{session.HostId} - Server holepunch success(EndPoint:{message.EndPoint} LocalEndPoint:{message.LocalEndPoint})");

            session.UdpEnabled       = true;
            session.UdpEndPoint      = message.EndPoint;
            session.UdpLocalEndPoint = message.LocalEndPoint;
            session.UdpSocket        = _filter.UdpSocket;
            session.Send(new NotifyClientServerUdpMatchedMessage(message.MagicNumber));
        }
Exemple #27
0
        public void NotifyP2PHolepunchSuccess(ProudSession session, NotifyP2PHolepunchSuccessMessage message)
        {
            session.Logger?.Debug("NotifyP2PHolepunchSuccess {@Message}", message);
            var group = session.P2PGroup;

            if (group == null || (session.HostId != message.A && session.HostId != message.B))
            {
                return;
            }

            var remotePeerA = group.Members?.GetValueOrDefault(message.A);
            var remotePeerB = group.Members?.GetValueOrDefault(message.B);

            if (remotePeerA == null || remotePeerB == null)
            {
                return;
            }

            var stateA = remotePeerA.ConnectionStates?.GetValueOrDefault(remotePeerB.HostId);
            var stateB = remotePeerB.ConnectionStates?.GetValueOrDefault(remotePeerA.HostId);

            if (stateA == null || stateB == null)
            {
                return;
            }

            //using (remotePeerA._sync.Lock())
            {
                //using (remotePeerB._sync.Lock())
                {
                    if (session.HostId == remotePeerA.HostId)
                    {
                        stateA.HolepunchSuccess = true;
                    }
                    else if (session.HostId == remotePeerB.HostId)
                    {
                        stateB.HolepunchSuccess = true;
                    }

                    if (stateA.HolepunchSuccess || stateB.HolepunchSuccess)
                    {
                        var notify = new NotifyDirectP2PEstablishMessage(message.A, message.B, message.ABSendAddr, message.ABRecvAddr, message.BASendAddr, message.BARecvAddr);
                        remotePeerA.SendAsync(notify);
                        remotePeerB.SendAsync(notify);
                    }
                }
            }
        }
Exemple #28
0
        public void ReliableRelayUnkHandler(ProudSession session, ReliableRelay1UnkMessage message)
        {
            if (session.P2PGroup == null)
            {
                return;
            }

            if (!session.P2PGroup.Members.ContainsKey(message.Destination.HostId))
            {
                return;
            }

            var target = _server.Sessions.GetValueOrDefault(message.Destination.HostId);

            target?.SendAsync(new ReliableRelay2Message(new RelayDestinationDto(session.HostId, message.Destination.FrameNumber), message.Data));
        }
        public void PeerUdp_ServerHolepunch(ProudSession session, PeerUdp_ServerHolepunchMessage message)
        {
            if (!session.UdpEnabled || _filter.Config.UdpListener == null)
            {
                return;
            }

            var target = _filter.SessionLookupByHostId.GetValueOrDefault(message.HostId);

            if (target == null || !target.UdpEnabled)
            {
                return;
            }

            session.Send(new PeerUdp_ServerHolepunchAckMessage(message.MagicNumber, target.UdpEndPoint, target.HostId));
        }
        public void EncryptedReliableMessage(IChannelHandlerContext context, ProudSession session, EncryptedReliableMessage message, RecvContext recvContext)
        {
            var crypt = session.Crypt;

            if (crypt != null)
            {
                var buffer = context.Allocator.Buffer(message.Data.Length);
                using (var src = new MemoryStream(message.Data))
                    using (var dst = new WriteOnlyByteBufferStream(buffer, false))
                    {
                        crypt.Decrypt(context.Allocator, message.EncryptMode, src, dst, true);
                    }
                recvContext.Message = buffer;
                context.Channel.Pipeline.Context <ProudFrameDecoder>().FireChannelRead(recvContext);
            }
        }