/// <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; }
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); }
/// <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)); }