// NAT METHODS private static IceCandidate GatherNAActiveCandidate(IPAddress localIPAddress, IceCandidate baseCandidate) { // exactly the same procedure like GatherSRActiveCandidate() // derived from passive NAT assisted candidate IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0); Socket activeConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // here is no bind, because active candidates don't have to be physically allocated here (allocation in connectivity checks) /* RFC 6544 (ICE TCP), Section 3: In the case of active candidates, both IP address and port are present, but the port is meaningless (it is there only for making encoding of active candidates consistent with the other candidate types and is ignored by the peer). As a consequence, active candidates do not need to be physically allocated at the time of address gathering. Rather, the physical allocations, which occur as a consequence of a connection attempt, occur at the time of the connectivity checks. */ // create candidate object IpAddressPort activeIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, baseCandidate.addr_port.ipaddr, 0); // port is meaningless IceCandidate activeCandidate = new IceCandidate(activeIpAddressPort, Overlay_Link.TLS_TCP_with_FH); activeCandidate.cand_type = CandType.tcp_nat; activeCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, 0); // port is meaningless activeCandidate.activeConnectingSocket = activeConnectingSocket; // TCP Type activeCandidate.tcpType = TcpType.Active; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("active"); activeCandidate.extension_list.Add(iceExtension); return activeCandidate; }
private static IceCandidate GatherNAPassiveCandidate(IPAddress localIPAddress) { // local endpoint IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0); // only one listening socket, because there is no need to use a STUN server. We get the IP and Port from the NAT using UPnP Socket passiveListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); passiveListeningSocket.Bind(localEndpoint); // update localEndpoint with binded Port localEndpoint = (IPEndPoint)passiveListeningSocket.LocalEndPoint; // check if UPnP is available UPnP upnp = new UPnP(); bool foundUPnPDevice = false; try { foundUPnPDevice = upnp.Discover(localIPAddress); } catch (Exception e) { //Console.WriteLine(e.Message); return null; } // IPEndPoint for public mapping IPEndPoint publicMapping = null; // found UPnP internet gateway device? if (foundUPnPDevice) { // try to get public IP and to add a port mapping try { string publicIP = upnp.GetExternalIP().ToString(); // we can use the local Port for the public NAT port mapping too bool addedPortMapping = upnp.AddPortMapping((ushort)localEndpoint.Port, (ushort)localEndpoint.Port, ProtocolType.Tcp, "RELOAD ICE TCP Port mapping"); if (addedPortMapping && !string.IsNullOrEmpty(publicIP)) { publicMapping = new IPEndPoint(IPAddress.Parse(publicIP), localEndpoint.Port); } else return null; } catch (Exception e) { //Console.WriteLine(e.Message); return null; } } // no UPnP IGD found else return null; // got public mapping? if (publicMapping == null) return null; // save data in candidate object IpAddressPort passiveIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, publicMapping.Address, (ushort)publicMapping.Port); IceCandidate passiveCandidate = new IceCandidate(passiveIpAddressPort, Overlay_Link.TLS_TCP_with_FH); passiveCandidate.cand_type = CandType.tcp_nat; passiveCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port); passiveCandidate.passiveListeningSocket = passiveListeningSocket; // TCP Type passiveCandidate.tcpType = TcpType.Passive; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("passive"); passiveCandidate.extension_list.Add(iceExtension); return passiveCandidate; }
private static IceCandidate GatherSRPassiveCandidate(IPAddress localIPAddress) { // local endpoint IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0); // listening socket Socket passiveListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); passiveListeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); passiveListeningSocket.Bind(localEndpoint); // update localEndpoint with binded Port localEndpoint = (IPEndPoint)passiveListeningSocket.LocalEndPoint; // STUN socket Socket passiveSTUNSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); passiveSTUNSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); passiveSTUNSocket.Bind(localEndpoint); // get defined STUN servers List<IPEndPoint> definedSTUNServers = GetDefinedSTUNServers(); // servers defined? if (definedSTUNServers.Count > 0) { // use first server IPEndPoint STUNEndPoint = definedSTUNServers[0]; // try to connect try { passiveSTUNSocket.Connect(STUNEndPoint); } catch (Exception e1) { //Console.WriteLine(e1.Message); // use second STUN server, if defined if (definedSTUNServers.Count == 2) { STUNEndPoint = definedSTUNServers[1]; // try to connect try { passiveSTUNSocket.Connect(STUNEndPoint); } catch (Exception e2) { //Console.WriteLine(e2.Message); // could not establish a connection to a STUN server return null; } } } } // no STUN servers defined else return null; // get public mapping IPEndPoint publicMapping = GetPublicMapping(passiveSTUNSocket); // save data in candidate object IpAddressPort passiveIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, publicMapping.Address, (ushort)publicMapping.Port); IceCandidate passiveCandidate = new IceCandidate(passiveIpAddressPort, Overlay_Link.TLS_TCP_with_FH); passiveCandidate.cand_type = CandType.tcp_srflx; passiveCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port); passiveCandidate.passiveListeningSocket = passiveListeningSocket; passiveCandidate.passiveSTUNSocket = passiveSTUNSocket; // TCP Type passiveCandidate.tcpType = TcpType.Passive; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("passive"); passiveCandidate.extension_list.Add(iceExtension); return passiveCandidate; }
private static IceCandidate GatherSRSOCandidate(IPAddress localIPAddress) { // local endpoint IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0); // listening socket Socket soListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); soListeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); soListeningSocket.Bind(localEndpoint); // update localEndpoint with binded Port localEndpoint = (IPEndPoint)soListeningSocket.LocalEndPoint; // connecting socket Socket soConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); soConnectingSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); soConnectingSocket.Bind(localEndpoint); // STUN1 socket Socket soSTUN1Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); soSTUN1Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); soSTUN1Socket.Bind(localEndpoint); // STUN2 socket Socket soSTUN2Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); soSTUN2Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); soSTUN2Socket.Bind(localEndpoint); // public mapping IPEndPoint publicMapping = null; // get defined STUN servers List<IPEndPoint> definedSTUNServers = GetDefinedSTUNServers(); // no defined STUN servers if (definedSTUNServers.Count == 0) return null; // only one STUN Server defined // so we can't predict the port mapping for two successive outgoing connections // what we can do here is to assume that the outgoing connections get the same port mapping else if (definedSTUNServers.Count == 1) { // try to connect try { soSTUN1Socket.Connect(definedSTUNServers[0]); } catch (Exception e) { //Console.WriteLine(e.Message); // could not connect to STUN server return null; } publicMapping = GetPublicMapping(soSTUN1Socket); } // two STUN servers defined // here we can predict the port mapping for two successive outgoing connections else if (definedSTUNServers.Count == 2) { // try to connect to first STUN server try { // get first public mapping soSTUN1Socket.Connect(definedSTUNServers[0]); IPEndPoint mapping1 = GetPublicMapping(soSTUN1Socket); // now try to connect to second STUN Server try { soSTUN2Socket.Connect(definedSTUNServers[1]); IPEndPoint mapping2 = GetPublicMapping(soSTUN2Socket); // calculate difference between port mappings int portDifference = mapping2.Port - mapping1.Port; // IP will be the same, port will be adapted publicMapping = new IPEndPoint(mapping2.Address, mapping2.Port + portDifference); } catch (Exception e) { //Console.WriteLine(e.Message); // use first mapping and assume port mapping will be equal publicMapping = mapping1; } } catch (Exception e1) { //Console.WriteLine(e1.Message); // could not connect to first STUN server // try second, but then we can't predict port mapping, only assume the port mapping will be equal for next outgoing connection try { soSTUN2Socket.Connect(definedSTUNServers[1]); publicMapping = GetPublicMapping(soSTUN2Socket); } catch (Exception e2) { //Console.WriteLine(e2.Message); // could not connect to first and second STUN Server return null; } } } // got no public mapping if (publicMapping == null) return null; // save data in candidate object IpAddressPort soIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, publicMapping.Address, (ushort)publicMapping.Port); IceCandidate soCandidate = new IceCandidate(soIpAddressPort, Overlay_Link.TLS_TCP_with_FH); soCandidate.cand_type = CandType.tcp_srflx; soCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port); soCandidate.soListeningSocket = soListeningSocket; soCandidate.soConnectingSocket = soConnectingSocket; soCandidate.soSTUN1Socket = soSTUN1Socket; soCandidate.soSTUN2Socket = soSTUN2Socket; // TCP Type soCandidate.tcpType = TcpType.SO; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("so"); soCandidate.extension_list.Add(iceExtension); return soCandidate; }
private static IceCandidate GatherHostSOCandidate(IPAddress localIPAddress) { // local endpoint IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0); // listening socket Socket soListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); soListeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); soListeningSocket.Bind(localEndpoint); // update localEndpoint with binded Port localEndpoint = (IPEndPoint)soListeningSocket.LocalEndPoint; // connecting socket Socket soConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); soConnectingSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); soConnectingSocket.Bind(localEndpoint); // save data in candidate object IpAddressPort soIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port); IceCandidate soCandidate = new IceCandidate(soIpAddressPort, Overlay_Link.TLS_TCP_with_FH); soCandidate.cand_type = CandType.tcp_host; soCandidate.soListeningSocket = soListeningSocket; soCandidate.soConnectingSocket = soConnectingSocket; // TCP Type soCandidate.tcpType = TcpType.SO; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("so"); soCandidate.extension_list.Add(iceExtension); return soCandidate; }
private static IceCandidate GatherHostPassiveCandidate(IPAddress localIPAddress) { // local endpoint IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0); Socket passiveListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); passiveListeningSocket.Bind(localEndpoint); // update localEndpoint with binded Port localEndpoint = (IPEndPoint)passiveListeningSocket.LocalEndPoint; // save data in candidate object IpAddressPort passiveIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port); IceCandidate passiveCandidate = new IceCandidate(passiveIpAddressPort, Overlay_Link.TLS_TCP_with_FH); passiveCandidate.cand_type = CandType.tcp_host; passiveCandidate.passiveListeningSocket = passiveListeningSocket; // TCP Type passiveCandidate.tcpType = TcpType.Passive; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("passive"); passiveCandidate.extension_list.Add(iceExtension); return passiveCandidate; }
// HOST METHODS private static IceCandidate GatherHostActiveCandidate(IPAddress localIPAddress) { IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0); //Socket activeConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //// here is no bind, because active candidates don't have to be physically allocated here (allocation in connectivity checks) //activeConnectingSocket.Bind(localEndpoint); // TEST /* RFC 6544 (ICE TCP), Section 3: In the case of active candidates, both IP address and port are present, but the port is meaningless (it is there only for making encoding of active candidates consistent with the other candidate types and is ignored by the peer). As a consequence, active candidates do not need to be physically allocated at the time of address gathering. Rather, the physical allocations, which occur as a consequence of a connection attempt, occur at the time of the connectivity checks. */ // save data in candidate object IpAddressPort activeIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port); IceCandidate activeCandidate = new IceCandidate(activeIpAddressPort, Overlay_Link.TLS_TCP_with_FH); activeCandidate.cand_type = CandType.tcp_host; //activeCandidate.activeConnectingSocket = activeConnectingSocket; // TEST: in PerformCheck // TCP Type activeCandidate.tcpType = TcpType.Active; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("active"); activeCandidate.extension_list.Add(iceExtension); return activeCandidate; }
public static IceCandidate CreateBootstrapCandidate(IPAddress localIPAddress, int port) { // save data in candidate object IpAddressPort bootstrapIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localIPAddress, (ushort)port); IceCandidate bootstrapCandidate = new IceCandidate(bootstrapIpAddressPort, Overlay_Link.TLS_TCP_with_FH); bootstrapCandidate.cand_type = CandType.tcp_bootstrap; // TCP Type bootstrapCandidate.tcpType = TcpType.Passive; // TCP ICE extension IceExtension iceExtension = new IceExtension(); iceExtension.name = Encoding.UTF8.GetBytes("tcptype"); iceExtension.value = Encoding.UTF8.GetBytes("passive"); bootstrapCandidate.extension_list.Add(iceExtension); // set other preference and foundation bootstrapCandidate.otherPreference = 8191; bootstrapCandidate.foundation = ComputeFoundation(bootstrapCandidate); return bootstrapCandidate; }
public IceCandidate(IpAddressPort addr_port, Overlay_Link ol) { this.addr_port = addr_port; this.priority = IceCandidate.NoICE_PRIORITY; this.cand_type = CandType.tcp_host; this.overlay_link = ol; this.extension_list = new List<IceExtension>(); }