Ejemplo n.º 1
0
        private async void ProcessUdp(IAsyncResult ar)
        {
            try
            {
                if (_socket == null)
                {
                    return;
                }

                EndPoint endPoint         = new IPEndPoint(0, 0);
                var      bytesTransferred = _socket.EndReceiveFrom(ar, ref endPoint);
                var      remoteEndPoint   = (IPEndPoint)endPoint;

                if (bytesTransferred == 0)
                {
                    return;
                }

                using (var data = new PooledMemoryStream(_pipe.Service.ArrayPool))
                {
                    data.Write(_buffer, 0, bytesTransferred);
                    data.Position = 0;

                    ushort flag;
                    ushort sessionId;
                    int    length;
                    int    id;
                    int    fragId;
                    using (var r = data.ToBinaryReader(true))
                    {
                        flag      = r.ReadUInt16();
                        sessionId = r.ReadUInt16();
                        length    = r.ReadInt32();
                        id        = r.ReadInt32();
                        fragId    = r.ReadInt32();
                    }

                    if (flag != 43981)
                    {
                        Logger.Warn()
                        .Message("Received Fragment instead of FullFragment")
                        .Write();
                        DoUdpReceive();
                        return;
                    }

                    var message = (CoreMessage)_protocol.Deserialize(null, data);
                    message.IsUdp          = true;
                    message.RemoteEndPoint = remoteEndPoint;

                    Logger.Trace()
                    .Message("Client:{0} Received:{1}", remoteEndPoint.ToString(), message.GetType().Name)
                    .Write();

                    var holepunch = message as ServerHolepunchMessage;
                    if (holepunch != null)
                    {
                        var session = (ProudSession)_pipe.Service[holepunch.MagicNumber];
                        if (session == null)
                        {
                            Logger.Warn()
                            .Message("Client:{0} Invalid MagicNumber", remoteEndPoint.ToString())
                            .Write();
                            DoUdpReceive();
                            return;
                        }

                        Logger.Debug()
                        .Message("Client:{0} Received ServerHolepunch", session.HostId)
                        .Write();

                        if (session.UdpEnabled)
                        {
                            Logger.Warn()
                            .Message("Client:{0} UDP relaying is already enabled", session.HostId)
                            .Write();

                            DoUdpReceive();
                            return;
                        }

                        session.UdpSessionId = sessionId;
                        session.UdpEndPoint  = remoteEndPoint;
                        Send(session, new ServerHolepunchAckMessage(holepunch.MagicNumber, remoteEndPoint));
                    }
                    else
                    {
                        // ToDo Add a lookup for UdpSessionId
                        var session = _pipe.Service.Sessions.Cast <ProudSession>().FirstOrDefault(s => s.UdpSessionId == sessionId);
                        if (session == null)
                        {
                            Logger.Warn()
                            .Message("Client:{0} Invalid session id", remoteEndPoint.ToString())
                            .Write();
                        }
                        else
                        {
                            try
                            {
                                var deferral = new DeferralManager();
                                _pipe.OnMessageReceived(new MessageReceivedEventArgs(session, message, deferral));
                                await deferral.WaitAsync().ConfigureAwait(false);
                            }
                            catch (Exception ex)
                            {
                                _pipe.Service.Pipeline.OnError(new ExceptionEventArgs(session, ex));
                                session.Dispose();
                            }
                        }
                    }

                    DoUdpReceive();
                }
            }
            catch (ObjectDisposedException)
            { }
            catch (Exception ex)
            {
                _pipe.Service.Pipeline.OnError(new ExceptionEventArgs(ex));
            }
        }