Beispiel #1
0
 private static void SendMessage(NetServer server, MsgBase msg, NetConnection conn)
 {
     NetOutgoingMessage om = server.CreateMessage();
     om.Write(msg.Id);
     msg.W(om);
     server.SendMessage(om, conn, NetDeliveryMethod.Unreliable, 0);
 }
        public override void HandleNetworkMessage(IncomingEntityComponentMessage message, NetConnection client)
        {
            var type = (ComponentMessageType) message.MessageParameters[0];

            switch (type)
            {
                case (ComponentMessageType.RequestActionList):
                    SendFullListing(client);
                    break;

                case (ComponentMessageType.GetActionChecksum):
                    Owner.SendDirectedComponentNetworkMessage(this, NetDeliveryMethod.ReliableUnordered, client,
                                                              ComponentMessageType.GetActionChecksum,
                                                              (uint) (Actions.Sum(x => x.uid)*Actions.Count));
                    break;

                case (ComponentMessageType.DoAction):
                    DoAction(message);
                    break;

                default:
                    base.HandleNetworkMessage(message, client);
                    break;
            }
        }
Beispiel #3
0
 public void SendMessage(IMessage msg, NetConnection conn)
 {
     NetOutgoingMessage om = server.CreateMessage();
     om.Write(msg.Id);
     msg.Write(om);
     server.SendMessage(om, conn, NetDeliveryMethod.Unreliable);
 }
Beispiel #4
0
 private static void SetClientCameraFollow(long ID, NetConnection Connection)
 {
     NetOutgoingMessage Message = NetworkManager.Server.CreateMessage();
     Message.Write((byte)MessageTypes.CameraFocusAt);
     Message.Write(ID);
     NetworkManager.Server.SendMessage(Message, Connection, NetDeliveryMethod.ReliableUnordered);
 }
Beispiel #5
0
 public static KSPClient getClient(NetConnection clientConnection)
 {
     KSPClient returnVal;
     connectionToClient.TryGetValue(clientConnection, out returnVal);
     // F**K IT THIS SHOULDNT EVER BE NULL ANYWAY
     return returnVal;
 }
Beispiel #6
0
 public void Remove(NetConnection conn)
 {
     if (ConnectionDictionary.ContainsKey(conn))
     {
         ConnectionDictionary.Remove(conn);
     }
 }
Beispiel #7
0
 public void Modify(NetConnection conn, uint id)
 {
     if(ConnectionDictionary.ContainsKey(conn))
     {
         ConnectionDictionary[conn] = id;
     }
 }
 public override void HandleNetworkMessage(IncomingEntityComponentMessage message, NetConnection sender)
 {
     /*var x = (float)message.MessageParameters[0];
     var y = (float)message.MessageParameters[1];
     if((bool)message.MessageParameters[2]) //"forced" parameter -- if true forces position update
     PlainTranslate((float)x, (float)y);*/
 }
Beispiel #9
0
        /// <summary>
        /// Send a message to a specific connection
        /// </summary>
        /// <param name="msg">The message to send</param>
        /// <param name="recipient">The recipient connection</param>
        /// <param name="method">How to deliver the message</param>
        /// <param name="sequenceChannel">Sequence channel within the delivery method</param>
        public NetSendResult SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod method, int sequenceChannel)
        {
            if (msg == null)
                throw new ArgumentNullException("msg");
            if (recipient == null)
                throw new ArgumentNullException("recipient");
            if (sequenceChannel >= NetConstants.NetChannelsPerDeliveryMethod)
                throw new ArgumentOutOfRangeException("sequenceChannel");

            NetException.Assert(
                ((method != NetDeliveryMethod.Unreliable && method != NetDeliveryMethod.ReliableUnordered) ||
                ((method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.ReliableUnordered) && sequenceChannel == 0)),
                "Delivery method " + method + " cannot use sequence channels other than 0!"
            );

            NetException.Assert(method != NetDeliveryMethod.Unknown, "Bad delivery method!");

            if (msg.m_isSent)
                throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently");
            msg.m_isSent = true;

            int len = NetConstants.UnfragmentedMessageHeaderSize + msg.LengthBytes; // headers + length, faster than calling msg.GetEncodedSize
            if (len <= recipient.m_currentMTU)
            {
                Interlocked.Increment(ref msg.m_recyclingCount);
                return recipient.EnqueueMessage(msg, method, sequenceChannel);
            }
            else
            {
                // message must be fragmented!
                SendFragmentedMessage(msg, new NetConnection[] { recipient }, method, sequenceChannel);
                return NetSendResult.Queued; // could be different for each connection; Queued is "most true"
            }
        }
Beispiel #10
0
		private static void HandleMessage(NetMessageType type, NetConnection source, NetBuffer buffer)
		{
			switch (type)
			{
				case NetMessageType.StatusChanged:
					if (source.LocalHailData == null)
						source.LocalHailData = Encoding.ASCII.GetBytes("Hi; I'm " + s_peer.GetHashCode());
					if (source.RemoteHailData != null)
						WriteToConsole("New status: " + source.Status + " - remote hail is: " + Encoding.ASCII.GetString(source.RemoteHailData));
					else
						WriteToConsole("New status: " + source.Status + " - remote hail is null");
					break;
				case NetMessageType.DebugMessage:
				case NetMessageType.VerboseDebugMessage:
				case NetMessageType.BadMessageReceived:
				case NetMessageType.ConnectionRejected:
					WriteToConsole(buffer.ReadString());
					break;
				case NetMessageType.Data:
					WriteToConsole(source.RemoteEndpoint + " writes: " + buffer.ReadString());
					break;
				case NetMessageType.ServerDiscovered:
					// discovered another peer!
					s_peer.Connect(buffer.ReadIPEndPoint(), Encoding.ASCII.GetBytes("Hi; I'm " + s_peer.GetHashCode()));
					break;
				default:
					// unhandled
					break;
			}
		}
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="manager">Local NetPeer</param>
        /// <param name="con">NetConnection</param>
        /// <param name="key">Encryption key</param>
        /// <param name="nodeId">Node Id</param>
        public Connection(NetPeer manager, NetConnection con, INetEncryption encryption, String nodeId)
        {
            // This keep alive timer is used to overcome BAD connections that drop ping/pong messages a lot.
            // It simply sends an empty message every five seconds. As long as some messages are retained
            // and received on the connection, all will be well
            _keepAliveTimer = new System.Timers.Timer(5000);
            _keepAliveTimer.Elapsed += new ElapsedEventHandler((Object state, ElapsedEventArgs args) =>
                this.SendMessage(this.NetManager.CreateMessage(0), NetDeliveryMethod.Unreliable));

            this.Username = (con.Tag as Handshake).Username;
            this.NetManager = manager;
            this.NetConnection = con;
            this.NetConnection.Tag = this;
            this.NodeId = nodeId;

            if (encryption != null)
            {
                _netEncryption = encryption;
            }
            else
            {
                // You could write code that makes it possible to transfer users between server
                // where you don't have any encryption key YET. The place to start that would
                // be here.
                this.IsTransfering = true;
                _netEncryption = new NetXtea(new Byte[16]);
            }

            // Not connected until everything is done.
            System.Threading.Thread.MemoryBarrier();

            _connected = true;
            _keepAliveTimer.Start();
        }
        void SendCheckpoint(NetConnection sendTo)
        {
            Log("SendCheckpoint");
            var checkpointEvent = new MyEventCheckpoint();
            checkpointEvent.Checkpoint = GetCheckpoint();

            Peers.NetworkClient.Send(ref checkpointEvent, sendTo, NetDeliveryMethod.ReliableOrdered, 0, 1024 * 1024);

            // Send missiles, cannon shots etc.
            m_entitiesToTransfer.Clear();
            MyEntities.FindEntities(AmmoEntitiesPredicate, m_entitiesToTransfer);
            foreach (var e in m_entitiesToTransfer)
            {
                var ammo = (MyAmmoBase)e;

                var weapon = MyGuiSmallShipHelpers.GetFirstWeaponType(ammo.AmmoType);
                if (!weapon.HasValue) continue;

                MyEventShoot shootMsg = new MyEventShoot();
                shootMsg.Ammo = ammo.AmmoType;
                shootMsg.Position = new MyMwcPositionAndOrientation(ammo.WorldMatrix);
                shootMsg.ProjectileEntityId = MyEntityIdentifier.ToNullableInt(ammo.EntityId);
                shootMsg.ShooterEntityId = (ammo.OwnerEntity != null && ammo.OwnerEntity.EntityId.HasValue) ? ammo.OwnerEntity.EntityId.Value.NumericValue : 0;
                shootMsg.TargetEntityId = null;
                shootMsg.Weapon = weapon.Value;
                Peers.NetworkClient.Send(ref shootMsg, sendTo, NetDeliveryMethod.ReliableOrdered, 0);
            }
        }
Beispiel #13
0
 public Character(string name, int x, int y, NetConnection conn)
 {
     Name = name;
     X = x;
     Y = y;
     Connection = conn;
 }
		public NetReliableOrderedReceiver(NetConnection connection, int windowSize)
			: base(connection)
		{
			m_windowSize = windowSize;
			m_withheldMessages = new NetIncomingMessage[windowSize];
			m_earlyReceived = new NetBitVector(windowSize);
		}
Beispiel #15
0
 private static void HandleMessage(NetMessageType type, NetConnection source, NetBuffer buffer)
 {
     switch (type)
     {
         case NetMessageType.DebugMessage:
             Console.WriteLine(buffer.ReadString());
             break;
         case NetMessageType.StatusChanged:
             NetConnectionStatus status = source.Status;
             if (status == NetConnectionStatus.Connected)
             {
                 source.Tag = ImageClientStatus.JustConnected;
                 s_nextPixelToSend[source] = 0;
             }
             else if (status == NetConnectionStatus.Disconnected)
             {
                 if (s_nextPixelToSend.ContainsKey(source))
                     s_nextPixelToSend.Remove(source);
             }
             break;
         case NetMessageType.Receipt:
             source.Tag = ImageClientStatus.Running;
             break;
         default:
             // unhandled
             break;
     }
 }
        /// <summary>
        /// Send a message to a specific connection
        /// </summary>
        /// <param name="msg">The message to send</param>
        /// <param name="recipient">The recipient connection</param>
        /// <param name="method">How to deliver the message</param>
        /// <param name="sequenceChannel">Sequence channel within the delivery method</param>
        public NetSendResult SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod method, int sequenceChannel)
        {
            if (msg == null)
                throw new ArgumentNullException("msg");
            if (recipient == null)
                throw new ArgumentNullException("recipient");

            NetException.Assert(
                ((method != NetDeliveryMethod.Unreliable && method != NetDeliveryMethod.ReliableUnordered) ||
                ((method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.ReliableUnordered) && sequenceChannel == 0)),
                "Delivery method " + method + " cannot use sequence channels other than 0!"
            );

            NetException.Assert(method != NetDeliveryMethod.Unknown, "Bad delivery method!");

            if (msg.m_isSent)
                throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently");

            int len = msg.LengthBytes;
            if (len <= m_configuration.MaximumTransmissionUnit)
            {
                Interlocked.Increment(ref msg.m_recyclingCount);
                return recipient.EnqueueMessage(msg, method, sequenceChannel);
            }
            else
            {
                // message must be fragmented!
                SendFragmentedMessage(msg, new NetConnection[] { recipient }, method, sequenceChannel);
                return NetSendResult.Queued; // could be different for each connection; Queued is "most true"
            }
        }
Beispiel #17
0
        public void AddConnection(NetConnection connection)
        {
            var lobbyPlayer = new LobbyPlayer();
            lobbyPlayer.Id = idToGive;
            connection.Tag = lobbyPlayer;
            clients.Add(connection);
            idToGive++;

            var memory = new MemoryStream();
            var writer = new BinaryWriter(memory);
            writer.Write((byte) LobbyProtocol.SetID);
            writer.Write(lobbyPlayer.Id);
            myServer.SendLobbyData(memory.ToArray(), connection);

            memory = new MemoryStream();
            writer = new BinaryWriter(memory);
            writer.Write((byte)LobbyProtocol.SendAllPlayers);
            writer.Write(AllPlayersData());
            myServer.SendLobbyData(memory.ToArray());

            SendData(new byte[1]{MaxSlots}, LobbyProtocol.SendMaxSlots );

            memory = new MemoryStream();
            writer = new BinaryWriter(memory);
            writer.Write(Name);
            writer.Write(Description);
            SendData(memory.ToArray(), LobbyProtocol.SendLobbyName);
        }
Beispiel #18
0
 public static void ChatMessage(NetConnection c, String data)
 {
     var msg = Network.Server.CreateMessage();
     msg.Write((byte)NetMsgType.Chat);
     msg.Write(data);
     Network.Server.SendMessage(msg, c, NetDeliveryMethod.ReliableUnordered);
 }
Beispiel #19
0
 public static void ClientEntityCreationMessage(NetConnection c, ushort id, Vector3 position, Quaternion orientation, int nose, int core, int tail, int[] weapons, long ownerID)
 {
     var msg = Network.Server.CreateMessage();
     msg.Write((byte)NetMsgType.CreateOnClient);
     msg.Write((byte)NetEntityType.Ship);
     msg.Write(id);
     msg.Write(position.X); msg.Write(position.Y); msg.Write(position.Z);
     msg.Write(orientation.X); msg.Write(orientation.Y);
     msg.Write(orientation.Z); msg.Write(orientation.W);
         msg.Write(nose);
         msg.Write(core);
         msg.Write(tail);
         if (weapons != null && weapons.Length > 0)
         {
             msg.Write(weapons.Length);
             for (int i = 0; i < weapons.Length; i++)
                 msg.Write(weapons[i]);
         }
         else
         {
             msg.Write((int)0);
         }
     msg.Write(ownerID);
     if (c != null)
         Network.Server.SendMessage(msg, c, NetDeliveryMethod.ReliableOrdered);
     else
         Network.Server.SendToAll(msg, NetDeliveryMethod.ReliableOrdered);
 }
Beispiel #20
0
 public void fireStatusChanged(NetServer server, NetBuffer buffer, NetConnection sender)
 {
     if (StatusChanged != null)
     {
         StatusChanged(server, buffer, sender);
     }
 }
Beispiel #21
0
 public void fireClientApproval(NetServer server, NetBuffer buffer, NetConnection sender)
 {
     if (ClientApproval != null)
     {
         ClientApproval(server, buffer, sender);
     }
 }
Beispiel #22
0
 public void fireDataRecieved(NetServer server, NetBuffer buffer, NetConnection sender)
 {
     if (DataRecieved != null)
     {
         DataRecieved(server, buffer, sender);
     }
 }
Beispiel #23
0
        public static void Process(NetServer server, NetBuffer buffer, NetConnection sender)
        {
            Config config = Config.Instance;

            List<NetConnection> connections = server.Connections;

            //Lets send that message onto any plugin clients
            foreach (NetConnection connection in connections)
            {
                if (config.Server.client_connections.ContainsKey(connection.RemoteEndpoint.ToString()))
                {
                    string client_type = (string)config.Server.client_connections[connection.RemoteEndpoint.ToString()];

                    if (client_type.ToLower() == "plugin")
                    {
                        string msg = buffer.ReadString();

                        Console.WriteLine("Slave: Data sent - " + msg);

                        NetBuffer slavebuf = server.CreateBuffer();

                        slavebuf.Write(msg);

                        server.SendMessage(slavebuf, connection, NetChannel.ReliableInOrder4);
                    }
                }
            }
        }
 public override void HandleNetworkMessage(IncomingEntityComponentMessage message, NetConnection client)
 {
     if (message.ComponentFamily == ComponentFamily.Equipment)
     {
         var type = (ComponentMessageType) message.MessageParameters[0];
         var replies = new List<ComponentReplyMessage>();
         switch (type) //Why does this send messages to itself THIS IS DUMB AND WILL BREAK THINGS. BZZZ
         {
             case ComponentMessageType.EquipItem:
                 EquipEntity(Owner.EntityManager.GetEntity((int) message.MessageParameters[1]));
                 break;
             case ComponentMessageType.EquipItemInHand:
                 EquipEntityInHand();
                 break;
             case ComponentMessageType.EquipItemToPart:
                 EquipEntityToPart((EquipmentSlot) message.MessageParameters[1],
                                   Owner.EntityManager.GetEntity((int) message.MessageParameters[2]));
                 break;
             case ComponentMessageType.UnEquipItemToFloor:
                 UnEquipEntity(Owner.EntityManager.GetEntity((int) message.MessageParameters[1]));
                 break;
             case ComponentMessageType.UnEquipItemToHand:
                 if (!Owner.HasComponent(ComponentFamily.Hands))
                     return; //TODO REAL ERROR MESSAGE OR SOME F**K SHIT
                 UnEquipEntityToHand(Owner.EntityManager.GetEntity((int) message.MessageParameters[1]));
                 break;
             case ComponentMessageType.UnEquipItemToSpecifiedHand:
                 if (!Owner.HasComponent(ComponentFamily.Hands))
                     return; //TODO REAL ERROR MESSAGE OR SOME F**K SHIT
                 UnEquipEntityToHand(Owner.EntityManager.GetEntity((int) message.MessageParameters[1]),
                                     (Hand) message.MessageParameters[2]);
                 break;
         }
     }
 }
Beispiel #25
0
        internal override void OnDisconnected(NetConnection conn)
        {
            //vij dali e igral
            if (!clients.Contains(conn))
                return;

        }
Beispiel #26
0
 public PlayerClient(NetConnection Connection)
     : base()
 {
     Location = new Vector2((375 * 40) + 1, (375 * 40) + 1);
         ClientConnection = Connection;
         Sex = LastSex;
 }
Beispiel #27
0
 public Client(string name, NetConnection connection, int score, byte[] buffer)
 {
     Name = name; //Name
     Connection = connection; //ServerConnection for that Client
     Score = score; //Score
     Buffer = buffer; //The avatar in a Byte Array
 }
Beispiel #28
0
 public static void RecvMCL()
 {
     while(true) {
         Thread.Sleep(10);
         NetIncomingMessage msg;
         while((msg = peer.ReadMessage()) != null) {
             switch(msg.MessageType) {
                 case NetIncomingMessageType.VerboseDebugMessage:
                 case NetIncomingMessageType.DebugMessage:
                 case NetIncomingMessageType.WarningMessage:
                 case NetIncomingMessageType.ErrorMessage:
                     Console.WriteLine(msg.ReadString());
                     break;
                 case NetIncomingMessageType.StatusChanged:
                     Console.WriteLine(((NetConnectionStatus)msg.ReadByte()).ToString());
                     break;
                 case NetIncomingMessageType.DiscoveryResponse:
                     Console.WriteLine("Found server at " + msg.SenderEndPoint + " name: " + msg.ReadString());
                     peerConnect = peer.Connect(msg.SenderEndPoint);
                     break;
                 case NetIncomingMessageType.Data:
                     Console.WriteLine(msg.LengthBytes);
                     break;
                 default:
                     Console.WriteLine("Unhandled type: " + msg.MessageType);
                     break;
             }
         }
     }
 }
Beispiel #29
0
 /// <summary>
 /// Creates a new connection instance.
 /// </summary>
 /// <param name="messagingSettings">Qbes messaging configuration
 /// node</param>
 /// <param name="connection">NetConnection object</param>
 /// <param name="callback">Callback for completed received multipart
 /// messages</param>
 public Connection(MessagingConfiguration messagingSettings, NetConnection connection, CompletedReceivedMultipartMessage callback)
 {
     _MaxMessageSize = messagingSettings.MaxMessageSize;
      _Connection = connection;
      _RemoteEndPoint = connection.RemoteEndPoint;
      _CompletedReceivedMultipartCallback = callback;
 }
        private void InterpretMessageStartRandomGame(NetConnection senderConn, XDocument xmlMessage)
        {
            int enteredRoomId = UserEnter(senderConn);
            SendMessage(senderConn, string.Format(
                    "<Message><Type>Game</Type><Time>{1}</Time><Info><Action>EnterRoom</Action><RoomId>{0}</RoomId></Info></Message>"
                    , enteredRoomId
                    , DateTime.Now));
            if (_roomList[enteredRoomId].Status == Room.RoomStatus.Idle)
            {
                SendMessage(senderConn, string.Format(
                    "<Message><Type>Game</Type><Time>{0}</Time><Info><Action>WaitingEnemy</Action></Info></Message>"
                    , DateTime.Now));
            }
            else
            {
                int seed = gameStartSeed.Next();
                SendMessage(enteredRoomId, string.Format(
                    "<Message><Type>Game</Type><Time>{1}</Time><Info><Action>GenerateSeed</Action><Seed>{0}</Seed></Info></Message>"
                    , seed
                    , DateTime.Now));
                foreach (var playerConn in _roomList[enteredRoomId].PlayerConns)
                {
                    //Random who start the 1st turn
                    SendMessage(playerConn
                        , string.Format("<Message><Type>Game</Type><Time>{1}</Time><Info><Action>StartGame</Action><StartGameIndex>{0}</StartGameIndex></Info></Message>"
                        , Math.Abs(_roomList[enteredRoomId].GetPlayerIndex(playerConn.RemoteUniqueIdentifier) - seed % 2)
                        , DateTime.Now));
                    //SendMessage(playerConn
                    //    , string.Format("startgame {0} {1}", enteredRoomId
                    //    , _roomList[enteredRoomId].GetPlayerIndex(playerConn.RemoteUniqueIdentifier)));//Temporarily let playerindex be the same as enter room order

                }
            }
        }
Beispiel #31
0
        public void SendStatus(Lidgren.Network.NetConnection connection)
        {
            var Ammo = new ushort[Data.WeaponIDs.Length];
            int i    = 0;

            foreach (WeaponData weapon in Data.Weapons.Values)
            {
                Ammo[i++] = weapon.CurrentAmmo;
            }
            MessageWriter.StatusMessage(connection, Health, throttle, Ammo);
        }
Beispiel #32
0
 /// <summary>
 /// Отправить сообщение для конкретного соединения.
 /// </summary>
 /// <param name="msg">Сообщение для отправки.</param>
 /// <param name="recipient">Соединение получатель.</param>
 /// <param name="method">Как доставить сообщение</param>
 public NetSendResult SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod method)
 {
     return(SendMessage(msg, recipient, method, 0));
 }
 public NetUnreliableUnorderedReceiver(NetConnection connection)
     : base(connection)
 {
     m_doFlowControl = connection.Peer.Configuration.SuppressUnreliableUnorderedAcks == false;
 }
Beispiel #34
0
 internal NetConnectionStatistics(NetConnection conn)
 {
     m_connection = conn;
     Reset();
 }
        private void ReceivedUnconnectedLibraryMessage(double now, NetEndPoint senderEndPoint, NetMessageType tp, int ptr, int payloadByteLength)
        {
            NetConnection shake;

            if (m_handshakes.TryGetValue(senderEndPoint, out shake))
            {
                shake.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;
            }

            //
            // Library message from a completely unknown sender; lets just accept Connect
            //
            switch (tp)
            {
            case NetMessageType.Discovery:
                HandleIncomingDiscoveryRequest(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.DiscoveryResponse:
                HandleIncomingDiscoveryResponse(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.NatIntroduction:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatIntroduction(ptr);
                }
                return;

            case NetMessageType.NatPunchMessage:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatPunch(ptr, senderEndPoint);
                }
                return;

            case NetMessageType.ConnectResponse:

                lock (m_handshakes)
                {
                    foreach (var hs in m_handshakes)
                    {
                        if (hs.Key.Address.Equals(senderEndPoint.Address))
                        {
                            if (hs.Value.m_connectionInitiator)
                            {
                                //
                                // We are currently trying to connection to XX.XX.XX.XX:Y
                                // ... but we just received a ConnectResponse from XX.XX.XX.XX:Z
                                // Lets just assume the router decided to use this port instead
                                //
                                var hsconn = hs.Value;
                                m_connectionLookup.Remove(hs.Key);
                                m_handshakes.Remove(hs.Key);

                                LogDebug("Detected host port change; rerouting connection to " + senderEndPoint);
                                hsconn.MutateEndPoint(senderEndPoint);

                                m_connectionLookup.Add(senderEndPoint, hsconn);
                                m_handshakes.Add(senderEndPoint, hsconn);

                                hsconn.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                                return;
                            }
                        }
                    }
                }

                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;

            case NetMessageType.Connect:
                if (m_configuration.AcceptIncomingConnections == false)
                {
                    LogWarning("Received Connect, but we're not accepting incoming connections!");
                    return;
                }
                // handle connect
                // It's someone wanting to shake hands with us!

                int reservedSlots = m_handshakes.Count + m_connections.Count;
                if (reservedSlots >= m_configuration.m_maximumConnections)
                {
                    // server full
                    NetOutgoingMessage full = CreateMessage("Server full");
                    full.m_messageType = NetMessageType.Disconnect;
                    SendLibrary(full, senderEndPoint);
                    return;
                }

                // Ok, start handshake!
                NetConnection conn = new NetConnection(this, senderEndPoint);
                conn.m_status = NetConnectionStatus.ReceivedInitiation;
                m_handshakes.Add(senderEndPoint, conn);
                conn.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;

            case NetMessageType.Disconnect:
                // this is probably ok
                LogVerbose("Received Disconnect from unconnected source: " + senderEndPoint);
                return;

            default:
                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;
            }
        }
        private void Heartbeat()
        {
            VerifyNetworkThread();

            double now   = NetTime.Now;
            double delta = now - m_lastHeartbeat;

            int maxCHBpS = 1250 - m_connections.Count;

            if (maxCHBpS < 250)
            {
                maxCHBpS = 250;
            }
            if (delta > (1.0 / (double)maxCHBpS) || delta < 0.0)             // max connection heartbeats/second max
            {
                m_frameCounter++;
                m_lastHeartbeat = now;

                // do handshake heartbeats
                if ((m_frameCounter % 3) == 0)
                {
                    foreach (var kvp in m_handshakes)
                    {
                        NetConnection conn = kvp.Value as NetConnection;
#if DEBUG
                        // sanity check
                        if (kvp.Key != kvp.Key)
                        {
                            LogWarning("Sanity fail! Connection in handshake list under wrong key!");
                        }
#endif
                        conn.UnconnectedHeartbeat(now);
                        if (conn.m_status == NetConnectionStatus.Connected || conn.m_status == NetConnectionStatus.Disconnected)
                        {
#if DEBUG
                            // sanity check
                            if (conn.m_status == NetConnectionStatus.Disconnected && m_handshakes.ContainsKey(conn.RemoteEndPoint))
                            {
                                LogWarning("Sanity fail! Handshakes list contained disconnected connection!");
                                m_handshakes.Remove(conn.RemoteEndPoint);
                            }
#endif
                            break;                             // collection has been modified
                        }
                    }
                }

#if DEBUG
                SendDelayedPackets();
#endif

                // update m_executeFlushSendQueue
                if (m_configuration.m_autoFlushSendQueue && m_needFlushSendQueue == true)
                {
                    m_executeFlushSendQueue = true;
                    m_needFlushSendQueue    = false;                  // a race condition to this variable will simply result in a single superfluous call to FlushSendQueue()
                }

                // do connection heartbeats
                lock (m_connections)
                {
                    for (int i = m_connections.Count - 1; i >= 0; i--)
                    {
                        var conn = m_connections[i];
                        conn.Heartbeat(now, m_frameCounter);
                        if (conn.m_status == NetConnectionStatus.Disconnected)
                        {
                            //
                            // remove connection
                            //
                            m_connections.RemoveAt(i);
                            m_connectionLookup.Remove(conn.RemoteEndPoint);
                        }
                    }
                }
                m_executeFlushSendQueue = false;

                // send unsent unconnected messages
                NetTuple <NetEndPoint, NetOutgoingMessage> unsent;
                while (m_unsentUnconnectedMessages.TryDequeue(out unsent))
                {
                    NetOutgoingMessage om = unsent.Item2;

                    int len = om.Encode(m_sendBuffer, 0, 0);

                    Interlocked.Decrement(ref om.m_recyclingCount);
                    if (om.m_recyclingCount <= 0)
                    {
                        Recycle(om);
                    }

                    bool connReset;
                    SendPacket(len, unsent.Item1, 1, out connReset);
                }
            }

            //
            // read from socket
            //
            if (m_socket == null)
            {
                return;
            }

            if (!m_socket.Poll(1000, SelectMode.SelectRead))             // wait up to 1 ms for data to arrive
            {
                return;
            }

            //if (m_socket == null || m_socket.Available < 1)
            //	return;

            // update now
            now = NetTime.Now;

            do
            {
                int bytesReceived = 0;
                try
                {
                    bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);
                }
                catch (SocketException sx)
                {
                    switch (sx.SocketErrorCode)
                    {
                    case SocketError.ConnectionReset:
                        // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                        // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
                        // So, what to do?
                        LogWarning("ConnectionReset");
                        return;

                    case SocketError.NotConnected:
                        // socket is unbound; try to rebind it (happens on mobile when process goes to sleep)
                        BindSocket(true);
                        return;

                    default:
                        LogWarning("Socket exception: " + sx.ToString());
                        return;
                    }
                }

                if (bytesReceived < NetConstants.HeaderByteSize)
                {
                    return;
                }

                //LogVerbose("Received " + bytesReceived + " bytes");

                var ipsender = (NetEndPoint)m_senderRemote;

                if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32)
                {
                    // is this an UPnP response?
                    string resp = System.Text.Encoding.ASCII.GetString(m_receiveBuffer, 0, bytesReceived);
                    if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0"))
                    {
                        try
                        {
                            resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
                            resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
                            m_upnp.ExtractServiceUrl(resp);
                            return;
                        }
                        catch (Exception ex)
                        {
                            LogDebug("Failed to parse UPnP response: " + ex.ToString());

                            // don't try to parse this packet further
                            return;
                        }
                    }
                }

                NetConnection sender = null;
                m_connectionLookup.TryGetValue(ipsender, out sender);

                //
                // parse packet into messages
                //
                int numMessages  = 0;
                int numFragments = 0;
                int ptr          = 0;
                while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize)
                {
                    // decode header
                    //  8 bits - NetMessageType
                    //  1 bit  - Fragment?
                    // 15 bits - Sequence number
                    // 16 bits - Payload length in bits

                    numMessages++;

                    NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++];

                    byte low  = m_receiveBuffer[ptr++];
                    byte high = m_receiveBuffer[ptr++];

                    bool   isFragment     = ((low & 1) == 1);
                    ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7));

                    numFragments++;

                    ushort payloadBitLength  = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8));
                    int    payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength);

                    if (bytesReceived - ptr < payloadByteLength)
                    {
                        LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr));
                        return;
                    }

                    if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29)
                    {
                        ThrowOrLog("Unexpected NetMessageType: " + tp);
                        return;
                    }

                    try
                    {
                        if (tp >= NetMessageType.LibraryError)
                        {
                            if (sender != null)
                            {
                                sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
                            }
                            else
                            {
                                ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength);
                            }
                        }
                        else
                        {
                            if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData))
                            {
                                return;                                 // dropping unconnected message since it's not enabled
                            }
                            NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
                            msg.m_isFragment          = isFragment;
                            msg.m_receiveTime         = now;
                            msg.m_sequenceNumber      = sequenceNumber;
                            msg.m_receivedMessageType = tp;
                            msg.m_senderConnection    = sender;
                            msg.m_senderEndPoint      = ipsender;
                            msg.m_bitLength           = payloadBitLength;

                            Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength);
                            if (sender != null)
                            {
                                if (tp == NetMessageType.Unconnected)
                                {
                                    // We're connected; but we can still send unconnected messages to this peer
                                    msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                    ReleaseMessage(msg);
                                }
                                else
                                {
                                    // connected application (non-library) message
                                    sender.ReceivedMessage(msg);
                                }
                            }
                            else
                            {
                                // at this point we know the message type is enabled
                                // unconnected application (non-library) message
                                msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                ReleaseMessage(msg);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogError("Packet parsing error: " + ex.Message + " from " + ipsender);
                    }
                    ptr += payloadByteLength;
                }

                m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
                if (sender != null)
                {
                    sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
                }
            } while (m_socket.Available > 0);
        }
        /// <summary>
        /// Create a connection to a remote endpoint
        /// </summary>
        public virtual NetConnection Connect(NetEndPoint remoteEndPoint, NetOutgoingMessage hailMessage)
        {
            if (remoteEndPoint == null)
            {
                throw new ArgumentNullException("remoteEndPoint");
            }

            lock (m_connections)
            {
                if (m_status == NetPeerStatus.NotRunning)
                {
                    throw new NetException("Must call Start() first");
                }

                if (m_connectionLookup.ContainsKey(remoteEndPoint))
                {
                    throw new NetException("Already connected to that endpoint!");
                }

                NetConnection hs;
                if (m_handshakes.TryGetValue(remoteEndPoint, out hs))
                {
                    // already trying to connect to that endpoint; make another try
                    switch (hs.m_status)
                    {
                    case NetConnectionStatus.InitiatedConnect:
                        // send another connect
                        hs.m_connectRequested = true;
                        break;

                    case NetConnectionStatus.RespondedConnect:
                        // send another response
                        hs.SendConnectResponse(NetTime.Now, false);
                        break;

                    case NetConnectionStatus.None:
                    case NetConnectionStatus.ReceivedInitiation:
                    case NetConnectionStatus.RespondedAwaitingApproval:
                    case NetConnectionStatus.Connected:
                    case NetConnectionStatus.Disconnecting:
                    case NetConnectionStatus.Disconnected:
                    default:
                        // weird
                        LogWarning("Weird situation; Connect() already in progress to remote endpoint; but hs status is " + hs.m_status);
                        break;
                    }
                    return(hs);
                }

                NetConnection conn = new NetConnection(this, remoteEndPoint);
                conn.m_status           = NetConnectionStatus.InitiatedConnect;
                conn.m_localHailMessage = hailMessage;

                // handle on network thread
                conn.m_connectRequested    = true;
                conn.m_connectionInitiator = true;

                m_handshakes.Add(remoteEndPoint, conn);

                return(conn);
            }
        }
 public NetUnreliableSequencedReceiver(NetConnection connection)
     : base(connection)
 {
 }
Beispiel #39
0
        /// <summary>
        /// Read any received message in any connection queue
        /// </summary>
        public bool ReadMessage(NetBuffer intoBuffer, out NetMessageType type, out NetConnection sender)
        {
            IPEndPoint senderEndPoint;

            return(ReadMessage(intoBuffer, out type, out sender, out senderEndPoint));
        }
Beispiel #40
0
        /// <summary>
        /// Read any received message in any connection queue
        /// </summary>
        public bool ReadMessage(
            NetBuffer intoBuffer,
            out NetMessageType type,
            out NetConnection sender,
            out IPEndPoint senderEndPoint)
        {
            if (intoBuffer == null)
            {
                throw new ArgumentNullException("intoBuffer");
            }

            if (m_receivedMessages.Count < 1)
            {
                sender         = null;
                senderEndPoint = null;
                type           = NetMessageType.None;
                m_dataReceivedEvent.Reset();
                return(false);
            }

            IncomingNetMessage msg;

            lock (m_receivedMessages)
                msg = m_receivedMessages.Dequeue();

            if (msg == null)
            {
                sender         = null;
                type           = NetMessageType.None;
                senderEndPoint = null;
                return(false);
            }

#if DEBUG
            if (msg.m_data == null)
            {
                throw new NetException("Ouch, no data!");
            }
            if (msg.m_data.Position != 0)
            {
                throw new NetException("Ouch, stale data!");
            }
#endif

            senderEndPoint = msg.m_senderEndPoint;
            sender         = msg.m_sender;

            intoBuffer.Tag = msg.m_data.Tag;

            //
            // recycle NetMessage object and NetBuffer
            //

            NetBuffer content = msg.m_data;

            msg.m_data = null;
            type       = msg.m_msgType;

            // swap content of buffers
            byte[] tmp = intoBuffer.Data;
            intoBuffer.Data = content.Data;
            if (tmp == null)
            {
                tmp = new byte[8];                 // application must have lost it somehow
            }
            content.Data = tmp;

            // set correct values for returning value (ignore the other, it's being recycled anyway)
            intoBuffer.m_bitLength    = content.m_bitLength;
            intoBuffer.m_readPosition = 0;

            // recycle message
            // m_messagePool.Push(msg);

            // recycle buffer
            RecycleBuffer(content);

            return(true);
        }
Beispiel #41
0
        internal override void HandleReceivedMessage(IncomingNetMessage message, IPEndPoint senderEndpoint)
        {
            double now = NetTime.Now;

            int payLen = message.m_data.LengthBytes;

            // NAT introduction?
            if (HandleNATIntroduction(message))
            {
                return;
            }

            // Out of band?
            if (message.m_type == NetMessageLibraryType.OutOfBand)
            {
                if ((m_enabledMessageTypes & NetMessageType.OutOfBandData) != NetMessageType.OutOfBandData)
                {
                    return;                     // drop
                }
                // just deliever
                message.m_msgType        = NetMessageType.OutOfBandData;
                message.m_senderEndPoint = senderEndpoint;

                EnqueueReceivedMessage(message);
                return;
            }

            if (message.m_sender == null)
            {
                //
                // Handle unconnected message
                //

                // not a connected sender; only allow System messages
                if (message.m_type != NetMessageLibraryType.System)
                {
                    if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                    {
                        NotifyApplication(NetMessageType.BadMessageReceived, "Rejecting non-system message from unconnected source: " + message, null, message.m_senderEndPoint);
                    }
                    return;
                }

                // read type of system message
                NetSystemType sysType = (NetSystemType)message.m_data.ReadByte();
                switch (sysType)
                {
                case NetSystemType.Connect:

                    LogVerbose("Connection request received from " + senderEndpoint);

                    // check app ident
                    if (payLen < 4)
                    {
                        if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                        {
                            NotifyApplication(NetMessageType.BadMessageReceived, "Malformed Connect message received from " + senderEndpoint, null, senderEndpoint);
                        }
                        return;
                    }
                    string appIdent = message.m_data.ReadString();
                    if (appIdent != m_config.ApplicationIdentifier)
                    {
                        if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                        {
                            NotifyApplication(NetMessageType.BadMessageReceived, "Connect for different application identification received: " + appIdent, null, senderEndpoint);
                        }
                        return;
                    }

                    // read random identifer
                    byte[] rnd = message.m_data.ReadBytes(8);
                    if (NetUtility.CompareElements(rnd, m_randomIdentifier))
                    {
                        // don't allow self-connect
                        if ((m_enabledMessageTypes & NetMessageType.ConnectionRejected) == NetMessageType.ConnectionRejected)
                        {
                            NotifyApplication(NetMessageType.ConnectionRejected, "Connection to self not allowed", null, senderEndpoint);
                        }
                        return;
                    }

                    int    bytesReadSoFar = (message.m_data.Position / 8);
                    int    hailLen        = message.m_data.LengthBytes - bytesReadSoFar;
                    byte[] hailData       = null;
                    if (hailLen > 0)
                    {
                        hailData = new byte[hailLen];
                        Buffer.BlockCopy(message.m_data.Data, bytesReadSoFar, hailData, 0, hailLen);
                    }

                    if (m_connections.Count >= m_config.m_maxConnections)
                    {
                        if ((m_enabledMessageTypes & NetMessageType.ConnectionRejected) == NetMessageType.ConnectionRejected)
                        {
                            NotifyApplication(NetMessageType.ConnectionRejected, "Server full; rejecting connect from " + senderEndpoint, null, senderEndpoint);
                        }
                        return;
                    }

                    // Create connection
                    LogWrite("New connection: " + senderEndpoint);
                    NetConnection conn = new NetConnection(this, senderEndpoint, null, hailData);

                    // Connection approval?
                    if ((m_enabledMessageTypes & NetMessageType.ConnectionApproval) == NetMessageType.ConnectionApproval)
                    {
                        // Ask application if this connection is allowed to proceed
                        IncomingNetMessage app = CreateIncomingMessage();
                        app.m_msgType = NetMessageType.ConnectionApproval;
                        if (hailData != null)
                        {
                            app.m_data.Write(hailData);
                        }
                        app.m_sender    = conn;
                        conn.m_approved = false;
                        EnqueueReceivedMessage(app);
                        // Don't add connection; it's done as part of the approval procedure
                        return;
                    }

                    // it's ok
                    AddConnection(now, conn);
                    break;

                case NetSystemType.ConnectionEstablished:
                    if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                    {
                        NotifyApplication(NetMessageType.BadMessageReceived, "Connection established received from non-connection! " + senderEndpoint, null, senderEndpoint);
                    }
                    return;

                case NetSystemType.Discovery:
                    if (m_config.AnswerDiscoveryRequests)
                    {
                        m_discovery.HandleRequest(message, senderEndpoint);
                    }
                    break;

                case NetSystemType.DiscoveryResponse:
                    if (m_allowOutgoingConnections)
                    {
                        // NetPeer
                        IncomingNetMessage resMsg = m_discovery.HandleResponse(message, senderEndpoint);
                        if (resMsg != null)
                        {
                            resMsg.m_senderEndPoint = senderEndpoint;
                            EnqueueReceivedMessage(resMsg);
                        }
                    }
                    break;

                default:
                    if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                    {
                        NotifyApplication(NetMessageType.BadMessageReceived, "Undefined behaviour for " + this + " receiving system type " + sysType + ": " + message + " from unconnected source", null, senderEndpoint);
                    }
                    break;
                }
                // done
                return;
            }

            // ok, we have a sender
            if (message.m_type == NetMessageLibraryType.Acknowledge)
            {
                message.m_sender.HandleAckMessage(message);
                return;
            }

            if (message.m_type == NetMessageLibraryType.System)
            {
                //
                // Handle system messages from connected source
                //

                if (payLen < 1)
                {
                    if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                    {
                        NotifyApplication(NetMessageType.BadMessageReceived, "Received malformed system message; payload length less than 1 byte", null, senderEndpoint);
                    }
                    return;
                }
                NetSystemType sysType = (NetSystemType)message.m_data.ReadByte();
                switch (sysType)
                {
                case NetSystemType.Connect:
                case NetSystemType.ConnectionEstablished:
                case NetSystemType.Ping:
                case NetSystemType.Pong:
                case NetSystemType.Disconnect:
                case NetSystemType.ConnectionRejected:
                case NetSystemType.StringTableAck:
                    message.m_sender.HandleSystemMessage(message, now);
                    break;

                case NetSystemType.ConnectResponse:
                    if (m_allowOutgoingConnections)
                    {
                        message.m_sender.HandleSystemMessage(message, now);
                    }
                    else
                    {
                        if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                        {
                            NotifyApplication(NetMessageType.BadMessageReceived, "Undefined behaviour for server and system type " + sysType, null, senderEndpoint);
                        }
                    }
                    break;

                case NetSystemType.Discovery:
                    // Allow discovery even if connected
                    if (m_config.AnswerDiscoveryRequests)
                    {
                        m_discovery.HandleRequest(message, senderEndpoint);
                    }
                    break;

                default:
                    if ((m_enabledMessageTypes & NetMessageType.BadMessageReceived) == NetMessageType.BadMessageReceived)
                    {
                        NotifyApplication(NetMessageType.BadMessageReceived, "Undefined behaviour for server and system type " + sysType, null, senderEndpoint);
                    }
                    break;
                }
                return;
            }

            message.m_sender.HandleUserMessage(message);
        }
Beispiel #42
0
        /*
         * /// <summary>
         * /// Read any received message in any connection queue
         * /// </summary>
         * public NetBuffer ReadMessage(out NetConnection sender)
         * {
         *      if (m_receivedMessages.Count < 1)
         *      {
         *              sender = null;
         *              return null;
         *      }
         *
         *      NetMessage msg = m_receivedMessages.Dequeue();
         *      sender = msg.m_sender;
         *
         *      NetBuffer retval = msg.m_data;
         *      msg.m_data = null;
         *      m_messagePool.Push(msg);
         *
         *      Debug.Assert(retval.Position == 0);
         *
         *      return retval;
         * }
         */

        /// <summary>
        /// Read any received message in any connection queue
        /// </summary>
        public bool ReadMessage(
            NetBuffer intoBuffer,
            IList <NetConnection> onlyFor,
            bool includeNullConnectionMessages,
            out NetMessageType type,
            out NetConnection sender)
        {
            if (m_receivedMessages.Count < 1)
            {
                sender = null;
                type   = NetMessageType.None;
                m_dataReceivedEvent.Reset();
                return(false);
            }

            IncomingNetMessage msg = null;

            lock (m_receivedMessages)
            {
                int sz = m_receivedMessages.Count;
                for (int i = 0; i < sz; i++)
                {
                    msg = m_receivedMessages.Peek(i);
                    if (msg != null)
                    {
                        if ((msg.m_sender == null && includeNullConnectionMessages) ||
                            onlyFor.Contains(msg.m_sender))
                        {
                            m_receivedMessages.Dequeue(i);
                            break;
                        }
                        msg = null;
                    }
                }
            }

            if (msg == null)
            {
                sender = null;
                type   = NetMessageType.None;
                return(false);
            }

            sender = msg.m_sender;

            // recycle NetMessage object
            NetBuffer content = msg.m_data;

            msg.m_data = null;
            type       = msg.m_msgType;

            // m_messagePool.Push(msg);

            Debug.Assert(content.Position == 0);

            // swap content of buffers
            byte[] tmp = intoBuffer.Data;
            intoBuffer.Data = content.Data;
            content.Data    = tmp;

            // set correct values for returning value (ignore the other, it's being recycled anyway)
            intoBuffer.m_bitLength    = content.m_bitLength;
            intoBuffer.m_readPosition = 0;

            // recycle NetBuffer object (incl. old intoBuffer byte array)
            RecycleBuffer(content);

            return(true);
        }
Beispiel #43
0
        private void ReceiveSocketData(double now)
        {
            int bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);

            if (bytesReceived < NetConstants.HeaderByteSize)
            {
                return;
            }

            //LogVerbose("Received " + bytesReceived + " bytes");

            var ipsender = (NetEndPoint)m_senderRemote;

            if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32)
            {
                // is this an UPnP response?
                string resp = System.Text.Encoding.UTF8.GetString(m_receiveBuffer, 0, bytesReceived);
                if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0"))
                {
                    try
                    {
                        resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
                        resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
                        m_upnp.ExtractServiceUrl(resp);
                        return;
                    }
                    catch (Exception ex)
                    {
                        LogDebug("Failed to parse UPnP response: " + ex.ToString());

                        // don't try to parse this packet further
                        return;
                    }
                }
            }

            NetConnection sender = null;

            m_connectionLookup.TryGetValue(ipsender, out sender);

            //
            // parse packet into messages
            //
            int numMessages  = 0;
            int numFragments = 0;
            int ptr          = 0;

            while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize)
            {
                // decode header
                //  8 bits - NetMessageType
                //  1 bit  - Fragment?
                // 15 bits - Sequence number
                // 16 bits - Payload length in bits

                numMessages++;

                NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++];

                byte low  = m_receiveBuffer[ptr++];
                byte high = m_receiveBuffer[ptr++];

                bool   isFragment     = ((low & 1) == 1);
                ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7));

                if (isFragment)
                {
                    numFragments++;
                }

                ushort payloadBitLength  = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8));
                int    payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength);

                if (bytesReceived - ptr < payloadByteLength)
                {
                    LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr));
                    return;
                }

                if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29)
                {
                    ThrowOrLog("Unexpected NetMessageType: " + tp);
                    return;
                }

                try
                {
                    if (tp >= NetMessageType.LibraryError)
                    {
                        if (sender != null)
                        {
                            sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
                        }
                        else
                        {
                            ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength);
                        }
                    }
                    else
                    {
                        if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData))
                        {
                            return;                             // dropping unconnected message since it's not enabled
                        }
                        NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
                        msg.m_isFragment          = isFragment;
                        msg.m_receiveTime         = now;
                        msg.m_sequenceNumber      = sequenceNumber;
                        msg.m_receivedMessageType = tp;
                        msg.m_senderConnection    = sender;
                        msg.m_senderEndPoint      = ipsender;
                        msg.m_bitLength           = payloadBitLength;

                        Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength);
                        if (sender != null)
                        {
                            if (tp == NetMessageType.Unconnected)
                            {
                                // We're connected; but we can still send unconnected messages to this peer
                                msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                ReleaseMessage(msg);
                            }
                            else
                            {
                                // connected application (non-library) message
                                sender.ReceivedMessage(msg);
                            }
                        }
                        else
                        {
                            // at this point we know the message type is enabled
                            // unconnected application (non-library) message
                            msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                            ReleaseMessage(msg);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogError("Packet parsing error: " + ex.Message + " from " + ipsender);
                }
                ptr += payloadByteLength;
            }

            m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
            if (sender != null)
            {
                sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
            }
        }
Beispiel #44
0
        private void Heartbeat()
        {
            VerifyNetworkThread();

            double dnow = NetTime.Now;
            float  now  = (float)dnow;

            double delta = dnow - m_lastHeartbeat;

            int maxCHBpS = 1250 - m_connections.Count;

            if (maxCHBpS < 250)
            {
                maxCHBpS = 250;
            }
            if (delta > (1.0 / (double)maxCHBpS))             // max connection heartbeats/second max
            {
                m_frameCounter++;
                m_lastHeartbeat = dnow;

                // do handshake heartbeats
                if ((m_frameCounter % 3) == 0)
                {
                    foreach (var kvp in m_handshakes)
                    {
                        NetConnection conn = kvp.Value as NetConnection;
#if DEBUG
                        // sanity check
                        if (kvp.Key != kvp.Key)
                        {
                            LogWarning("Sanity fail! Connection in handshake list under wrong key!");
                        }
#endif
                        conn.UnconnectedHeartbeat(now);
                        if (conn.m_status == NetConnectionStatus.Connected || conn.m_status == NetConnectionStatus.Disconnected)
                        {
#if DEBUG
                            // sanity check
                            if (conn.m_status == NetConnectionStatus.Disconnected && m_handshakes.ContainsKey(conn.RemoteEndpoint))
                            {
                                LogWarning("Sanity fail! Handshakes list contained disconnected connection!");
                                m_handshakes.Remove(conn.RemoteEndpoint);
                            }
#endif
                            break;                             // collection has been modified
                        }
                    }
                }

#if DEBUG
                SendDelayedPackets();
#endif

                // do connection heartbeats
                lock (m_connections)
                {
                    foreach (NetConnection conn in m_connections)
                    {
                        conn.Heartbeat(now, m_frameCounter);
                        if (conn.m_status == NetConnectionStatus.Disconnected)
                        {
                            //
                            // remove connection
                            //
                            m_connections.Remove(conn);
                            m_connectionLookup.Remove(conn.RemoteEndpoint);
                            break;                             // can't continue iteration here
                        }
                    }
                }

                // send unsent unconnected messages
                NetTuple <IPEndPoint, NetOutgoingMessage> unsent;
                while (m_unsentUnconnectedMessages.TryDequeue(out unsent))
                {
                    NetOutgoingMessage om = unsent.Item2;
#if DEBUG
                    if (om.m_messageType == NetMessageType.NatPunchMessage)
                    {
                        LogDebug("Sending Nat Punch Message to " + unsent.Item1.ToString());
                    }
#endif

                    bool connReset;
                    int  len = om.Encode(m_sendBuffer, 0, 0);
                    SendPacket(len, unsent.Item1, 1, out connReset);

                    Interlocked.Decrement(ref om.m_recyclingCount);
                    if (om.m_recyclingCount <= 0)
                    {
                        Recycle(om);
                    }
                }
            }

            //
            // read from socket
            //
            if (m_socket == null)
            {
                return;
            }

            if (!m_socket.Poll(1000, SelectMode.SelectRead))             // wait up to 1 ms for data to arrive
            {
                return;
            }

            //if (m_socket == null || m_socket.Available < 1)
            //	return;

            do
            {
                int bytesReceived = 0;
                try
                {
                    bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);
                }
                catch (SocketException sx)
                {
                    if (sx.SocketErrorCode == SocketError.ConnectionReset)
                    {
                        // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                        // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
                        // So, what to do?
                        return;
                    }

                    LogWarning(sx.ToString());
                    return;
                }

                if (bytesReceived < NetConstants.HeaderByteSize)
                {
                    return;
                }

                //LogVerbose("Received " + bytesReceived + " bytes");

                IPEndPoint ipsender = (IPEndPoint)m_senderRemote;

                if (ipsender.Port == 1900)
                {
                    // UPnP response
                    try
                    {
                        string resp = System.Text.Encoding.ASCII.GetString(m_receiveBuffer, 0, bytesReceived);
                        if (resp.Contains("upnp:rootdevice"))
                        {
                            resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
                            resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
                            m_upnp.ExtractServiceUrl(resp);
                            return;
                        }
                    }
                    catch { }
                }

                NetConnection sender = null;
                m_connectionLookup.TryGetValue(ipsender, out sender);

                double receiveTime = NetTime.Now;
                //
                // parse packet into messages
                //
                int numMessages = 0;
                int ptr         = 0;
                while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize)
                {
                    // decode header
                    //  8 bits - NetMessageType
                    //  1 bit  - Fragment?
                    // 15 bits - Sequence number
                    // 16 bits - Payload length in bits

                    numMessages++;

                    NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++];

                    byte low  = m_receiveBuffer[ptr++];
                    byte high = m_receiveBuffer[ptr++];

                    bool   isFragment     = ((low & 1) == 1);
                    ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7));

                    ushort payloadBitLength  = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8));
                    int    payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength);

                    if (bytesReceived - ptr < payloadByteLength)
                    {
                        LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr));
                        return;
                    }

                    try
                    {
                        NetException.Assert(tp <NetMessageType.Unused1 || tp> NetMessageType.Unused29);

                        if (tp >= NetMessageType.LibraryError)
                        {
                            if (sender != null)
                            {
                                sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
                            }
                            else
                            {
                                ReceivedUnconnectedLibraryMessage(receiveTime, ipsender, tp, ptr, payloadByteLength);
                            }
                        }
                        else
                        {
                            if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData))
                            {
                                return;                                 // dropping unconnected message since it's not enabled
                            }
                            NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
                            msg.m_isFragment          = isFragment;
                            msg.m_receiveTime         = receiveTime;
                            msg.m_sequenceNumber      = sequenceNumber;
                            msg.m_receivedMessageType = tp;
                            msg.m_senderConnection    = sender;
                            msg.m_senderEndpoint      = ipsender;
                            msg.m_bitLength           = payloadBitLength;
                            Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength);
                            if (sender != null)
                            {
                                if (tp == NetMessageType.Unconnected)
                                {
                                    // We're connected; but we can still send unconnected messages to this peer
                                    msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                    ReleaseMessage(msg);
                                }
                                else
                                {
                                    // connected application (non-library) message
                                    sender.ReceivedMessage(msg);
                                }
                            }
                            else
                            {
                                // at this point we know the message type is enabled
                                // unconnected application (non-library) message
                                msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                ReleaseMessage(msg);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogError("Packet parsing error: " + ex.Message + " from " + ipsender);
                    }
                    ptr += payloadByteLength;
                }

                m_statistics.PacketReceived(bytesReceived, numMessages);
                if (sender != null)
                {
                    sender.m_statistics.PacketReceived(bytesReceived, numMessages);
                }
            } while (m_socket.Available > 0);
        }
Beispiel #45
0
        private void ReceivedUnconnectedLibraryMessage(double now, IPEndPoint senderEndpoint, NetMessageType tp, int ptr, int payloadByteLength)
        {
            NetConnection shake;

            if (m_handshakes.TryGetValue(senderEndpoint, out shake))
            {
                shake.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;
            }

            //
            // Library message from a completely unknown sender; lets just accept Connect
            //
            switch (tp)
            {
            case NetMessageType.Discovery:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.DiscoveryRequest))
                {
                    NetIncomingMessage dm = CreateIncomingMessage(NetIncomingMessageType.DiscoveryRequest, payloadByteLength);
                    if (payloadByteLength > 0)
                    {
                        Buffer.BlockCopy(m_receiveBuffer, ptr, dm.m_data, 0, payloadByteLength);
                    }
                    dm.m_receiveTime    = now;
                    dm.m_bitLength      = payloadByteLength * 8;
                    dm.m_senderEndpoint = senderEndpoint;
                    ReleaseMessage(dm);
                }
                return;

            case NetMessageType.DiscoveryResponse:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.DiscoveryResponse))
                {
                    NetIncomingMessage dr = CreateIncomingMessage(NetIncomingMessageType.DiscoveryResponse, payloadByteLength);
                    if (payloadByteLength > 0)
                    {
                        Buffer.BlockCopy(m_receiveBuffer, ptr, dr.m_data, 0, payloadByteLength);
                    }
                    dr.m_receiveTime    = now;
                    dr.m_bitLength      = payloadByteLength * 8;
                    dr.m_senderEndpoint = senderEndpoint;
                    ReleaseMessage(dr);
                }
                return;

            case NetMessageType.NatIntroduction:
                HandleNatIntroduction(ptr);
                return;

            case NetMessageType.NatPunchMessage:
                HandleNatPunch(ptr, senderEndpoint);
                return;

            case NetMessageType.Connect:
                // proceed
                break;

            case NetMessageType.Disconnect:
                // this is probably ok
                LogVerbose("Received Disconnect from unconnected source: " + senderEndpoint);
                return;

            default:
                LogWarning("Received unhandled library message " + tp + " from " + senderEndpoint);
                return;
            }

            // It's someone wanting to shake hands with us!

            int reservedSlots = m_handshakes.Count + m_connections.Count;

            if (reservedSlots >= m_configuration.m_maximumConnections)
            {
                // server full
                NetOutgoingMessage full = CreateMessage("Server full");
                full.m_messageType = NetMessageType.Disconnect;
                SendLibrary(full, senderEndpoint);
                return;
            }

            // Ok, start handshake!
            NetConnection conn = new NetConnection(this, senderEndpoint);

            m_handshakes.Add(senderEndpoint, conn);
            conn.ReceivedHandshake(now, tp, ptr, payloadByteLength);

            return;
        }
Beispiel #46
0
        private void Heartbeat()
        {
            VerifyNetworkThread();

            double now   = NetTime.Now;
            double delta = now - m_lastHeartbeat;

            int maxCHBpS = 1250 - m_connections.Count;

            if (maxCHBpS < 250)
            {
                maxCHBpS = 250;
            }
            if (delta > (1.0 / (double)maxCHBpS) || delta < 0.0)             // max connection heartbeats/second max
            {
                m_frameCounter++;
                m_lastHeartbeat = now;

                // do handshake heartbeats
                if ((m_frameCounter % 3) == 0)
                {
                    foreach (var kvp in m_handshakes)
                    {
                        NetConnection conn = kvp.Value as NetConnection;
#if DEBUG
                        // sanity check
                        if (kvp.Key != kvp.Key)
                        {
                            LogWarning("Sanity fail! Connection in handshake list under wrong key!");
                        }
#endif
                        conn.UnconnectedHeartbeat(now);
                        if (conn.m_status == NetConnectionStatus.Connected || conn.m_status == NetConnectionStatus.Disconnected)
                        {
#if DEBUG
                            // sanity check
                            if (conn.m_status == NetConnectionStatus.Disconnected && m_handshakes.ContainsKey(conn.RemoteEndPoint))
                            {
                                LogWarning("Sanity fail! Handshakes list contained disconnected connection!");
                                m_handshakes.Remove(conn.RemoteEndPoint);
                            }
#endif
                            break;                             // collection has been modified
                        }
                    }
                }

#if DEBUG
                SendDelayedPackets();
#endif

                // update m_executeFlushSendQueue
                if (m_configuration.m_autoFlushSendQueue && m_needFlushSendQueue == true)
                {
                    m_executeFlushSendQueue = true;
                    m_needFlushSendQueue    = false;                  // a race condition to this variable will simply result in a single superfluous call to FlushSendQueue()
                }

                // do connection heartbeats
                lock (m_connections)
                {
                    for (int i = m_connections.Count - 1; i >= 0; i--)
                    {
                        var conn = m_connections[i];
                        conn.Heartbeat(now, m_frameCounter);
                        if (conn.m_status == NetConnectionStatus.Disconnected)
                        {
                            //
                            // remove connection
                            //
                            m_connections.RemoveAt(i);
                            m_connectionLookup.Remove(conn.RemoteEndPoint);
                        }
                    }
                }
                m_executeFlushSendQueue = false;

                // send unsent unconnected messages
                NetTuple <NetEndPoint, NetOutgoingMessage> unsent;
                while (m_unsentUnconnectedMessages.TryDequeue(out unsent))
                {
                    NetOutgoingMessage om = unsent.Item2;

                    int len = om.Encode(m_sendBuffer, 0, 0);

                    Interlocked.Decrement(ref om.m_recyclingCount);
                    if (om.m_recyclingCount <= 0)
                    {
                        Recycle(om);
                    }

                    bool connReset;
                    SendPacket(len, unsent.Item1, 1, out connReset);
                }
            }

            if (m_upnp != null)
            {
                m_upnp.CheckForDiscoveryTimeout();
            }

            //
            // read from socket
            //
            if (m_socket == null)
            {
                return;
            }

            if (!m_socket.Poll(5000, SelectMode.SelectRead))             // wait up to 10 ms for data to arrive
            {
                return;
            }

            //if (m_socket == null || m_socket.Available < 1)
            //	return;

            // update now
            now = NetTime.Now;

            try
            {
                do
                {
                    ReceiveSocketData(now);
                } while (m_socket.Available > 0);
            }
            catch (SocketException sx)
            {
                switch (sx.SocketErrorCode)
                {
                case SocketError.ConnectionReset:
                    // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                    // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
                    // So, what to do?
                    LogWarning("ConnectionReset");
                    return;

                case SocketError.NotConnected:
                    // socket is unbound; try to rebind it (happens on mobile when process goes to sleep)
                    BindSocket(true);
                    return;

                default:
                    LogWarning("Socket exception: " + sx.ToString());
                    return;
                }
            }
        }
Beispiel #47
0
        private void ReceivedUnconnectedLibraryMessage(double now, NetEndPoint senderEndPoint, long connectionId, NetMessageType tp, int ptr, int payloadByteLength)
        {
            NetConnection shake;

            if (m_handshakes.TryGetValue(connectionId, out shake))
            {
                shake.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;
            }

            //
            // Library message from a completely unknown sender; lets just accept Connect
            //
            switch (tp)
            {
            case NetMessageType.Discovery:
                HandleIncomingDiscoveryRequest(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.DiscoveryResponse:
                HandleIncomingDiscoveryResponse(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.NatIntroduction:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatIntroduction(ptr);
                }
                return;

            case NetMessageType.NatPunchMessage:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatPunch(ptr, senderEndPoint);
                }
                return;

            case NetMessageType.NatIntroductionConfirmRequest:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatPunchConfirmRequest(ptr, senderEndPoint);
                }
                return;

            case NetMessageType.NatIntroductionConfirmed:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatPunchConfirmed(ptr, senderEndPoint);
                }
                return;

            case NetMessageType.ConnectResponse:
                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;

            case NetMessageType.Connect:
                if (m_configuration.AcceptIncomingConnections == false)
                {
                    LogWarning("Received Connect, but we're not accepting incoming connections!");
                    return;
                }
                // handle connect
                // It's someone wanting to shake hands with us!

                int reservedSlots = m_handshakes.Count + m_connections.Count;
                if (reservedSlots >= m_configuration.m_maximumConnections)
                {
                    // server full
                    NetOutgoingMessage full = CreateMessage("Server full");
                    full.m_messageType = NetMessageType.Disconnect;
                    SendLibrary(connectionId, full, senderEndPoint);
                    return;
                }

                if (connectionId == 0 || m_handshakes.ContainsKey(connectionId) || m_connectionLookup.ContainsKey(connectionId))
                {
                    // duplicate connection id
                    NetOutgoingMessage full = CreateMessage("Duplicate connection id");
                    full.m_messageType = NetMessageType.Disconnect;
                    SendLibrary(connectionId, full, senderEndPoint);
                    return;
                }

                // Ok, start handshake!
                NetConnection conn = new NetConnection(this, senderEndPoint, connectionId);
                conn.m_status = NetConnectionStatus.ReceivedInitiation;
                m_handshakes.Add(connectionId, conn);
                conn.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;

            case NetMessageType.Disconnect:
                // this is probably ok
                LogVerbose("Received Disconnect from unconnected source: " + senderEndPoint);
                return;

            default:
                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;
            }
        }
 public NetReliableSequencedReceiver(NetConnection connection, int windowSize)
     : base(connection)
 {
     m_windowSize = windowSize;
 }
Beispiel #49
0
 public Soul(Lidgren.Network.NetConnection owner)
 {
     this.Owner = owner;
 }
 /// <summary>
 /// Reads a string using the string table
 /// </summary>
 public string ReadString(NetConnection sender)
 {
     return(sender.ReadStringTable(this));
 }
Beispiel #51
0
 /// <summary>
 /// Write a string using the string table
 /// </summary>
 public void Write(NetConnection recipient, string str)
 {
     recipient.WriteStringTable(this, str);
 }
Beispiel #52
0
        // on user thread
        private void SendFragmentedMessage(NetOutgoingMessage msg, IList <NetConnection> recipients, NetDeliveryMethod method, int sequenceChannel)
        {
            // Note: this group id is PER SENDING/NetPeer; ie. same id is sent to all recipients;
            // this should be ok however; as long as recipients differentiate between same id but different sender
            int group = Interlocked.Increment(ref m_lastUsedFragmentGroup);

            if (group >= NetConstants.MaxFragmentationGroups)
            {
                // @TODO: not thread safe; but in practice probably not an issue
                m_lastUsedFragmentGroup = 1;
                group = 1;
            }
            msg.m_fragmentGroup = group;

            // do not send msg; but set fragmentgroup in case user tries to recycle it immediately

            // create fragmentation specifics
            int totalBytes = msg.LengthBytes;

            // determine minimum mtu for all recipients
            int mtu           = GetMTU(recipients);
            int bytesPerChunk = NetFragmentationHelper.GetBestChunkSize(group, totalBytes, mtu);

            int numChunks = totalBytes / bytesPerChunk;

            if (numChunks * bytesPerChunk < totalBytes)
            {
                numChunks++;
            }

            int bitsPerChunk = bytesPerChunk * 8;
            int bitsLeft     = msg.LengthBits;

            for (int i = 0; i < numChunks; i++)
            {
                NetOutgoingMessage chunk = CreateMessage(mtu);

                chunk.m_bitLength              = (bitsLeft > bitsPerChunk ? bitsPerChunk : bitsLeft);
                chunk.m_data                   = msg.m_data;
                chunk.m_fragmentGroup          = group;
                chunk.m_fragmentGroupTotalBits = totalBytes * 8;
                chunk.m_fragmentChunkByteSize  = bytesPerChunk;
                chunk.m_fragmentChunkNumber    = i;

                NetException.Assert(chunk.m_bitLength != 0);
                NetException.Assert(chunk.GetEncodedSize() < mtu);

                Interlocked.Add(ref chunk.m_recyclingCount, recipients.Count);

                int ct = recipients.Count;
                for (int ix = 0; ix < ct; ++ix)
                {
                    NetConnection recipient = recipients[ix];
                    recipient.EnqueueMessage(chunk, method, sequenceChannel);
                }

                bitsLeft -= bitsPerChunk;
            }

            return;
        }
 public NetReliableUnorderedReceiver(NetConnection connection, int windowSize)
     : base(connection)
 {
     m_windowSize    = windowSize;
     m_earlyReceived = new NetBitVector(windowSize);
 }
Beispiel #54
0
 public NetReceiverChannelBase(NetConnection connection)
 {
     m_connection = connection;
     m_peer       = connection.m_peer;
 }