Пример #1
0
        /// <summary>
        /// NetPeerConfiguration constructor
        /// </summary>
        public NetPeerConfiguration(string appIdentifier, System.Net.Sockets.AddressFamily addressFamily = System.Net.Sockets.AddressFamily.InterNetwork)
        {
            if (string.IsNullOrEmpty(appIdentifier))
            {
                throw new NetException("App identifier must be at least one character long");
            }
            m_appIdentifier = appIdentifier;
            m_addressFamily = (int)addressFamily;

            //
            // default values
            //
            m_disabledTypes     = NetIncomingMessageType.ConnectionApproval | NetIncomingMessageType.UnconnectedData | NetIncomingMessageType.VerboseDebugMessage | NetIncomingMessageType.ConnectionLatencyUpdated | NetIncomingMessageType.NatIntroductionSuccess;
            m_networkThreadName = "Lidgren network thread";
            if (addressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
            {
                m_localAddress     = IPAddress.IPv6Any;
                m_broadcastAddress = IPAddress.Broadcast.MapToIPv6();
            }
            else
            {
                m_localAddress     = IPAddress.Any;
                m_broadcastAddress = IPAddress.Broadcast;
            }
            var ip = NetUtility.GetBroadcastAddress();

            if (ip != null)
            {
                m_broadcastAddress = ip;
            }
            m_port = 0;
            m_receiveBufferSize              = 131071;
            m_sendBufferSize                 = 131071;
            m_acceptIncomingConnections      = false;
            m_maximumConnections             = 32;
            m_defaultOutgoingMessageCapacity = 16;
            m_pingInterval                    = 4.0f;
            m_connectionTimeout               = 25.0f;
            m_useMessageRecycling             = true;
            m_recycledCacheMaxCount           = 64;
            m_resendHandshakeInterval         = 3.0f;
            m_maximumHandshakeAttempts        = 5;
            m_autoFlushSendQueue              = true;
            m_suppressUnreliableUnorderedAcks = false;

            m_maximumTransmissionUnit = kDefaultMTU;
            m_autoExpandMTU           = false;
            m_expandMTUFrequency      = 2.0f;
            m_expandMTUFailAttempts   = 5;
            m_unreliableSizeBehaviour = NetUnreliableSizeBehaviour.IgnoreMTU;

            m_loss = 0.0f;
            m_minimumOneWayLatency = 0.0f;
            m_randomOneWayLatency  = 0.0f;
            m_duplicates           = 0.0f;

            m_isLocked = false;
        }
        /// <summary>
        /// Emit a discovery signal to all hosts on your subnet
        /// </summary>
        public void DiscoverLocalPeers(int serverPort)
        {
            NetOutgoingMessage um = CreateMessage(0);

            um.m_messageType = NetMessageType.Discovery;
            Interlocked.Increment(ref um.m_recyclingCount);

            m_unsentUnconnectedMessages.Enqueue((new NetEndPoint(NetUtility.GetBroadcastAddress(), serverPort), um));
        }
        /// <summary>
        /// NetPeerConfiguration constructor
        /// </summary>
        public NetPeerConfiguration(string appIdentifier)
        {
            if (string.IsNullOrEmpty(appIdentifier))
            {
                throw new NetException("App identifier must be at least one character long");
            }
            m_appIdentifier = appIdentifier.ToString(System.Globalization.CultureInfo.InvariantCulture);

            //
            // default values
            //
            m_disabledTypes     = NetIncomingMessageType.ConnectionApproval | NetIncomingMessageType.UnconnectedData | NetIncomingMessageType.VerboseDebugMessage | NetIncomingMessageType.ConnectionLatencyUpdated;
            m_networkThreadName = "Lidgren network thread";
            m_localAddress      = IPAddress.Any;
            m_broadcastAddress  = IPAddress.Broadcast;
            var ip = NetUtility.GetBroadcastAddress();

            if (ip != null)
            {
                m_broadcastAddress = ip;
            }
            m_port = 0;
            m_receiveBufferSize              = 131071;
            m_sendBufferSize                 = 131071;
            m_acceptIncomingConnections      = false;
            m_maximumConnections             = 32;
            m_defaultOutgoingMessageCapacity = 16;
            m_pingInterval             = 4.0f;
            m_connectionTimeout        = 25.0f;
            m_useMessageRecycling      = true;
            m_resendHandshakeInterval  = 3.0f;
            m_maximumHandshakeAttempts = 5;
            m_autoFlushSendQueue       = true;

            // Maximum transmission unit
            // Ethernet can take 1500 bytes of payload, so lets stay below that.
            // The aim is for a max full packet to be 1440 bytes (30 x 48 bytes, lower than 1468)
            // -20 bytes IP header
            //  -8 bytes UDP header
            //  -4 bytes to be on the safe side and align to 8-byte boundary
            // Total 1408 bytes
            // Note that lidgren headers (5 bytes) are not included here; since it's part of the "mtu payload"
            m_maximumTransmissionUnit = 1408;
            m_autoExpandMTU           = false;
            m_expandMTUFrequency      = 2.0f;
            m_expandMTUFailAttempts   = 5;

            m_loss = 0.0f;
            m_minimumOneWayLatency = 0.0f;
            m_randomOneWayLatency  = 0.0f;
            m_duplicates           = 0.0f;

            m_assumedNATMappingTime = 10 * 60 * 60;

            m_isLocked = false;
        }
        internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target, out bool connectionReset)
        {
            connectionReset = false;
            try
            {
                // TODO: refactor this check outta here
                if (target.Address == NetUtility.GetBroadcastAddress())
                {
                    // Some networks do not allow
                    // a global broadcast so we use the BroadcastAddress from the configuration
                    // this can be resolved to a local broadcast addresss e.g 192.168.x.255
                    target.Address = m_configuration.BroadcastAddress;
                    m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
                }

                int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, target);
                if (numBytes != bytesSent)
                {
                    LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
                }

                // LogDebug("Sent " + numBytes + " bytes");
            }
            catch (SocketException sx)
            {
                if (sx.SocketErrorCode == SocketError.WouldBlock)
                {
                    // send buffer full?
                    LogWarning("Socket threw exception; would block - send buffer full? Increase in NetPeerConfiguration");
                    return(false);
                }
                if (sx.SocketErrorCode == SocketError.ConnectionReset)
                {
                    // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                    connectionReset = true;
                    return(false);
                }
                LogError("Failed to send packet: " + sx);
            }
            catch (Exception ex)
            {
                LogError("Failed to send packet: " + ex);
            }
            finally
            {
                if (target.Address == IPAddress.Broadcast)
                {
                    m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false);
                }
            }
            return(true);
        }
        //
        // Release - just send the packet straight away
        //
        internal void SendPacket(int numBytes, NetEndPoint target, int numMessages, out bool connectionReset)
        {
#if USE_RELEASE_STATISTICS
            m_statistics.PacketSent(numBytes, numMessages);
#endif
            connectionReset = false;
            try
            {
                // TODO: refactor this check outta here
                if (target.Address == NetUtility.GetBroadcastAddress())
                {
                    m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
                }

                int bytesSent = m_socket.SendTo(m_sendBuffer, 0, numBytes, SocketFlags.None, target);
                if (numBytes != bytesSent)
                {
                    LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
                }
            }
            catch (SocketException sx)
            {
                if (sx.SocketErrorCode == SocketError.WouldBlock)
                {
                    // send buffer full?
                    LogWarning("Socket threw exception; would block - send buffer full? Increase in NetPeerConfiguration");
                    return;
                }
                if (sx.SocketErrorCode == SocketError.ConnectionReset)
                {
                    // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                    connectionReset = true;
                    return;
                }
                LogError("Failed to send packet: " + sx);
            }
            catch (Exception ex)
            {
                LogError("Failed to send packet: " + ex);
            }
            finally
            {
                if (target.Address == NetUtility.GetBroadcastAddress())
                {
                    m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false);
                }
            }
            return;
        }
Пример #6
0
        internal void Discover(NetPeer peer)
        {
            string str =
                "M-SEARCH * HTTP/1.1\r\n" +
                "HOST: 239.255.255.250:1900\r\n" +
                "ST:upnp:rootdevice\r\n" +
                "MAN:\"ssdp:discover\"\r\n" +
                "MX:3\r\n\r\n";

            m_discoveryResponseDeadline = NetTime.Now + 6.0;             // arbitrarily chosen number, router gets 6 seconds to respond
            m_status = UPnPStatus.Discovering;

            byte[] arr = System.Text.Encoding.UTF8.GetBytes(str);

            m_peer.LogDebug("Attempting UPnP discovery");
            peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
            peer.RawSend(arr, 0, arr.Length, new NetEndPoint(NetUtility.GetBroadcastAddress(), 1900));
            peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false);
        }
Пример #7
0
        /// <summary>
        /// Add a forwarding rule to the router using UPnP
        /// </summary>
        public bool ForwardPort(int port, string description)
        {
            //if (!CheckAvailability())
            //	return false;

            IPAddress mask;
            var       client = NetUtility.GetMyAddress(out mask);

            if (client == null)
            {
                client = NetUtility.GetBroadcastAddress();
            }
            //return false;

            try
            {
                SOAPRequest(m_serviceUrl,
                            "<u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:" + m_serviceName + ":1\">" +
                            "<NewRemoteHost></NewRemoteHost>" +
                            "<NewExternalPort>" + port.ToString() + "</NewExternalPort>" +
                            "<NewProtocol>" + ProtocolType.Udp.ToString().ToUpper(System.Globalization.CultureInfo.InvariantCulture) + "</NewProtocol>" +
                            "<NewInternalPort>" + port.ToString() + "</NewInternalPort>" +
                            "<NewInternalClient>" + client.ToString() + "</NewInternalClient>" +
                            "<NewEnabled>1</NewEnabled>" +
                            "<NewPortMappingDescription>" + description + "</NewPortMappingDescription>" +
                            "<NewLeaseDuration>0</NewLeaseDuration>" +
                            "</u:AddPortMapping>",
                            "AddPortMapping");

                m_peer.LogDebug("Sent UPnP port forward request");
                NetUtility.Sleep(50);
            }
            catch (Exception ex)
            {
                m_peer.LogWarning("UPnP port forward failed: " + ex.Message);
                return(false);
            }
            return(true);
        }
        // TODO: replace byte[] with Memory<byte> in the future (held back by Socket.SendTo)
        // https://github.com/dotnet/runtime/issues/33418
        internal NetSocketResult ActuallySendPacket(byte[] data, int byteCount, IPEndPoint target)
        {
            Socket?socket = Socket;

            Debug.Assert(socket != null);

            bool broadcasting = false;

            try
            {
                IPAddress?ba = NetUtility.GetBroadcastAddress();

                // TODO: refactor this check outta here
                if (target.Address.Equals(ba))
                {
                    // Some networks do not allow
                    // a global broadcast so we use the BroadcastAddress from the configuration
                    // this can be resolved to a local broadcast addresss e.g 192.168.x.255
                    _targetCopy.Address = Configuration.BroadcastAddress;
                    _targetCopy.Port    = target.Port;

                    socket.EnableBroadcast = true;
                    broadcasting           = true;
                }
                else if (
                    Configuration.DualStack &&
                    Configuration.LocalAddress.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    // Maps to IPv6 for Dual Mode
                    NetUtility.MapToIPv6(target, _targetCopy);
                }
                else
                {
                    _targetCopy.Port    = target.Port;
                    _targetCopy.Address = target.Address;
                }

                int bytesSent = socket.SendTo(data, 0, byteCount, SocketFlags.None, _targetCopy);
                if (byteCount != bytesSent)
                {
                    LogWarning(NetLogMessage.FromValues(NetLogCode.FullSendFailure,
                                                        endPoint: target,
                                                        value: bytesSent,
                                                        maxValue: byteCount));
                }
                //LogDebug("Sent " + numBytes + " bytes");
            }
            catch (SocketException sx)
            {
                switch (sx.SocketErrorCode)
                {
                case SocketError.WouldBlock:
                    // send buffer full?
                    LogDebug(new NetLogMessage(NetLogCode.SocketWouldBlock, sx));
                    return(new NetSocketResult(false, false));

                case SocketError.ConnectionReset:
                    // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                    return(new NetSocketResult(false, true));

                default:
                    LogError(new NetLogMessage(NetLogCode.SendFailure, sx, target));
                    break;
                }
            }
            catch (Exception ex)
            {
                LogError(new NetLogMessage(NetLogCode.SendFailure, ex, target));
            }
            finally
            {
                if (broadcasting)
                {
                    socket.EnableBroadcast = false;
                }
            }
            return(new NetSocketResult(true, false));
        }