/// <summary> /// Returns true if message should be dropped /// </summary> internal bool HandleNATIntroduction(IncomingNetMessage message) { if (message.m_type == NetMessageLibraryType.System) { if (message.m_data.LengthBytes > 4 && message.m_data.PeekByte() == (byte)NetSystemType.NatIntroduction) { if ((m_enabledMessageTypes & NetMessageType.NATIntroduction) != NetMessageType.NATIntroduction) { return(true); // drop } try { message.m_data.ReadByte(); // step past system type byte IPEndPoint presented = message.m_data.ReadIPEndPoint(); LogVerbose("Received NATIntroduction to " + presented + "; sending punching ping..."); double now = NetTime.Now; NetConnection.SendPing(this, presented, now); if (m_holePunches == null) { m_holePunches = new List <IPEndPoint>(); } for (int i = 0; i < 5; i++) { m_holePunches.Add(new IPEndPoint(presented.Address, presented.Port)); } NetBuffer info = CreateBuffer(); info.Write(presented); NotifyApplication(NetMessageType.NATIntroduction, info, message.m_sender, message.m_senderEndPoint); return(true); } catch (Exception ex) { NotifyApplication(NetMessageType.BadMessageReceived, "Bad NAT introduction message received: " + ex.Message, message.m_sender, message.m_senderEndPoint); return(true); } } } return(false); }
/// <summary> /// Reads all packets and create messages /// </summary> protected void BaseHeartbeat(double now) { if (!m_isBound) { return; } // discovery m_discovery.Heartbeat(now); // hole punching if (m_holePunches != null) { if (now > m_lastHolePunch + NetConstants.HolePunchingFrequency) { if (m_holePunches.Count <= 0) { m_holePunches = null; } else { IPEndPoint dest = m_holePunches[0]; m_holePunches.RemoveAt(0); NotifyApplication(NetMessageType.DebugMessage, "Sending hole punch to " + dest, null); NetConnection.SendPing(this, dest, now); if (m_holePunches.Count < 1) { m_holePunches = null; } m_lastHolePunch = now; } } } // Send queued system messages if (m_susmQueue.Count > 0) { lock (m_susmQueue) { while (m_susmQueue.Count > 0) { SUSystemMessage su = m_susmQueue.Dequeue(); SendSingleUnreliableSystemMessage(su.Type, su.Data, su.Destination, su.UseBroadcast); } } } // Send out-of-band messages if (m_unsentOutOfBandMessages.Count > 0) { lock (m_unsentOutOfBandMessages) { while (m_unsentOutOfBandMessages.Count > 0) { NetBuffer buf = m_unsentOutOfBandMessages.Dequeue(); IPEndPoint ep = m_unsentOutOfBandRecipients.Dequeue(); DoSendOutOfBandMessage(buf, ep); } } } try { #if DEBUG SendDelayedPackets(now); #endif while (true) { if (m_socket == null || m_socket.Available < 1) { return; } m_receiveBuffer.Reset(); int bytesReceived = 0; try { bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer.Data, 0, m_receiveBuffer.Data.Length, SocketFlags.None, ref m_senderRemote); } catch (SocketException) { // no good response to this yet return; } if (bytesReceived < 1) { return; } if (bytesReceived > 0) { m_statistics.CountPacketReceived(bytesReceived); } m_receiveBuffer.LengthBits = bytesReceived * 8; //LogVerbose("Read packet: " + bytesReceived + " bytes"); IPEndPoint ipsender = (IPEndPoint)m_senderRemote; NetConnection sender = GetConnection(ipsender); if (sender != null) { sender.m_statistics.CountPacketReceived(bytesReceived, now); } // create messages from packet while (m_receiveBuffer.Position < m_receiveBuffer.LengthBits) { int beginPosition = m_receiveBuffer.Position; // read message header IncomingNetMessage msg = CreateIncomingMessage(); msg.m_sender = sender; msg.ReadFrom(m_receiveBuffer, ipsender); // statistics if (sender != null) { sender.m_statistics.CountMessageReceived(msg.m_type, msg.m_sequenceChannel, (m_receiveBuffer.Position - beginPosition) / 8, now); } // handle message HandleReceivedMessage(msg, ipsender); } } } catch (SocketException sex) { if (sex.ErrorCode == 10054) { // forcibly closed; but m_senderRemote is unreliable, we can't trust it! //NetConnection conn = GetConnection((IPEndPoint)m_senderRemote); //HandleConnectionForciblyClosed(conn, sex); return; } } catch (Exception ex) { throw new NetException("ReadPacket() exception", ex); } }