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; } }
public void SendMessage(IMessage msg, NetConnection conn) { NetOutgoingMessage om = server.CreateMessage(); om.Write(msg.Id); msg.Write(om); server.SendMessage(om, conn, NetDeliveryMethod.Unreliable); }
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); }
public static KSPClient getClient(NetConnection clientConnection) { KSPClient returnVal; connectionToClient.TryGetValue(clientConnection, out returnVal); // F**K IT THIS SHOULDNT EVER BE NULL ANYWAY return returnVal; }
public void Remove(NetConnection conn) { if (ConnectionDictionary.ContainsKey(conn)) { ConnectionDictionary.Remove(conn); } }
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);*/ }
/// <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" } }
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); } }
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); }
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" } }
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); }
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); }
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); }
public void fireStatusChanged(NetServer server, NetBuffer buffer, NetConnection sender) { if (StatusChanged != null) { StatusChanged(server, buffer, sender); } }
public void fireClientApproval(NetServer server, NetBuffer buffer, NetConnection sender) { if (ClientApproval != null) { ClientApproval(server, buffer, sender); } }
public void fireDataRecieved(NetServer server, NetBuffer buffer, NetConnection sender) { if (DataRecieved != null) { DataRecieved(server, buffer, sender); } }
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; } } }
internal override void OnDisconnected(NetConnection conn) { //vij dali e igral if (!clients.Contains(conn)) return; }
public PlayerClient(NetConnection Connection) : base() { Location = new Vector2((375 * 40) + 1, (375 * 40) + 1); ClientConnection = Connection; Sex = LastSex; }
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 }
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; } } } }
/// <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 } } }
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); }
/// <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; }
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) { }
/// <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)); }
/// <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); }
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); }
/* * /// <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); }
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); } }
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); }
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; }
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; } } }
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; }
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)); }
/// <summary> /// Write a string using the string table /// </summary> public void Write(NetConnection recipient, string str) { recipient.WriteStringTable(this, str); }
// 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); }
public NetReceiverChannelBase(NetConnection connection) { m_connection = connection; m_peer = connection.m_peer; }