예제 #1
0
        internal void CommitAndEnqueueForSending(OutgoingMessage msg, DeliveryType deliveryType, byte channelIndex)
        {
            if (deliveryType != AgNet.DeliveryType.Reliable && msg.BodyLength > PayloadMTU)
            {
                throw new AgNetException(string.Format("You can't send unreliable messages more than {0} bytes", PayloadMTU));
            }

            if (msg.Sealed)
            {
                throw new AgNetException("This message already has been sent. You can't send one message twice. Please use SendMessage() method with multiple recipients");
            }

            msg.Sealed = true;

            IAgNetChannel channel = GetChannel(deliveryType, channelIndex);

            lock (channel)
            {
                IEnumerable <OutgoingMessage> messages = null;
                if (deliveryType == DeliveryType.Reliable)
                {
                    messages = AgNetReliableChannel.TrySplit(msg, PayloadMTU);
                }
                else
                {
                    messages = new OutgoingMessage[1] {
                        msg
                    }
                };

                foreach (OutgoingMessage splittedMsg in messages)
                {
                    splittedMsg.RemoteEP = ClientEndPoint;
                    channel.CommitMessage(splittedMsg);
                    splittedMsg.Status = AgNetSendStatus.Queued;
                }
            }
        }
예제 #2
0
        internal IEnumerable <IncomingMessage> ReceiveMessage(IncomingMessage msg)
        {
            LastIncomingData = DateTime.UtcNow;

            if (msg.DeliveryType == DeliveryType.Reliable && msg.Type != PacketType.ConfirmDelivery)
            {
                reliableChannel.AddToSendConfirmation(msg);
            }

            IAgNetChannel channel = GetChannel(msg.DeliveryType, msg.Channel);
            IEnumerable <IncomingMessage> messages     = channel.ProcessMessage(msg);
            List <IncomingMessage>        userMessages = new List <IncomingMessage>();

            foreach (var message in messages)
            {
                if (ProcessMessage(channel, message))
                {
                    userMessages.Add(message);
                }
            }

            return(userMessages);
        }
예제 #3
0
        bool ProcessMessage(IAgNetChannel channel, IncomingMessage msg)
        {
            if (msg.Type == PacketType.ConfirmDelivery)
            {
                int confirmed = msg.ReadInt32();
                for (int i = 0; i < confirmed; i++)
                {
                    int             sequence    = msg.ReadInt32();
                    OutgoingMessage deliveryFor = reliableChannel.PopFromAwaitConfirmation(sequence);

                    if (deliveryFor == null)
                    {
                        continue;
                    }

                    deliveryFor.Status = AgNetSendStatus.Confirmed;

                    if (State == SessionState.Connecting && deliveryFor.Type == PacketType.ConnectAck)
                    {
                        SetState(SessionState.Connected);
                    }

                    if (State == SessionState.Closing && deliveryFor.Type == PacketType.FinResp)
                    {
                        Close("Shutdown method called");
                    }

                    deliveryFor.Dispose();
                }

                return(false);
            }

            if (msg.Type == PacketType.Ping)
            {
                Pong(msg);
                return(false);
            }

            if (msg.Type == PacketType.MTUExpandRequest)
            {
                ReceivedMtuExpand(msg);
                return(false);
            }

            if (msg.Type == PacketType.MTUSuccess)
            {
                ReceivedMtuResponse(msg);
                return(false);
            }

            if (msg.Type == PacketType.Pong)
            {
                lastPongReceived = DateTime.UtcNow;
                DateTime sent = new DateTime(msg.ReadInt64());
                TimeSpan ts   = DateTime.UtcNow - sent;
                PingRoundtrip = (int)ts.TotalMilliseconds;
                return(false);
            }

            if (msg.Type == PacketType.ConnectionError)
            {
                Close(msg.ReadString());
                return(false);
            }

            if (msg.Type == PacketType.FinAck)
            {
                SetState(SessionState.Closing);
                FinResp();
                return(false);
            }

            if (msg.Type == PacketType.FinResp)
            {
                Close("Connection closed by remote peer");
                return(false);
            }

            if (msg.Type == PacketType.ConnectAck && State == SessionState.Closed)
            {
                var server = peer as AgNetServer;
                if (server != null)
                {
                    if (server.MaximumSessions > 0 && server.SessionsCount >= server.MaximumSessions)
                    {
                        SendError("Server rejected connection");
                    }
                    else
                    {
                        SetState(SessionState.Connected);
                    }
                }
                return(false);
            }


            if (msg.Type == PacketType.Ping)
            {
                return(false);
            }

            if (msg.Type == PacketType.PartialMessage)
            {
                return(false);
            }

            if (State == SessionState.Connected && msg.Type == PacketType.UserData)
            {
                return(true);
            }

            Close("Unknown service packet");
            return(false);
        }