internal static void ReleaseSharedSocket(IPEndPoint endPoint, LstSocks.Socket sock) { object sockObj = socks[endPoint]; if (sockObj == null) { throw new InvalidOperationException("Sock does not exist as a shared socket."); } lock (socks) { if (--sock.refCount <= 0) { // Leave the multicast group if (Utility.IsMulticast(endPoint.Address)) { try { if (endPoint.AddressFamily == AddressFamily.InterNetworkV6) { IPv6MulticastOption mo = new IPv6MulticastOption(endPoint.Address); sock.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.DropMembership, mo); } else { MulticastOption mo = new MulticastOption(endPoint.Address); sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DropMembership, mo); } } catch {} // The user of the socket *may* not have joined the multicast group (?) } // Remove ourselves from the shared pool socks.Remove(endPoint); // Close the socket try { sock.Close(); } catch (ObjectDisposedException) {} } } }
// Apparently binding to the same ports on UDPSender and UDPListener causes problems in unicast. // Sharing the socket though, allows us to tunnel through firewalls as data is sent and received // on the same endpoint. // This region of code enables sharing sockets between the two classes. internal static SockInterfacePair GetSharedSocket(IPEndPoint endPoint) { lock(socks) { object sockObj = socks[endPoint]; if( sockObj != null ) { SockInterfacePair sip = (SockInterfacePair)sockObj; ++sip.sock.refCount; return sip; } else { // Create the socket LstSocks.Socket sock = new LstSocks.Socket(endPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); // Get the External Interface, save it for future use IPAddress externalInterface = Utility.GetLocalRoutingInterface(endPoint.Address); if (externalInterface == null) { // Pri3: Do something more helpful here throw new Exception("Unable to find a local routing interface, is no network present?"); } if( Utility.IsMulticast(endPoint.Address) ) { // Allow multiple binds to this socket, as it will still function properly // (this is only the case if it is a multicast socket. Unicast sockets fail to // receive all data on all sockets) sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, -1); // We don't join the multicast group here, because we may not want to listen // to our own data (halfing our throughput). jasonv - 10/28/2004 } // Add the socket to the hashtable SockInterfacePair sip = new SockInterfacePair(); sip.sock = sock; sip.extInterface = externalInterface; socks.Add(endPoint, sip); // Increase the socket's reference count ++sock.refCount; return sip; } } }
// Apparently binding to the same ports on UDPSender and UDPListener causes problems in unicast. // Sharing the socket though, allows us to tunnel through firewalls as data is sent and received // on the same endpoint. // This region of code enables sharing sockets between the two classes. internal static SockInterfacePair GetSharedSocket(IPEndPoint endPoint) { lock (socks) { object sockObj = socks[endPoint]; if (sockObj != null) { SockInterfacePair sip = (SockInterfacePair)sockObj; ++sip.sock.refCount; return(sip); } else { // Create the socket LstSocks.Socket sock = new LstSocks.Socket(endPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); // Get the External Interface, save it for future use IPAddress externalInterface = Utility.GetLocalRoutingInterface(endPoint.Address); if (externalInterface == null) { // Pri3: Do something more helpful here throw new Exception("Unable to find a local routing interface, is no network present?"); } if (Utility.IsMulticast(endPoint.Address)) { // Allow multiple binds to this socket, as it will still function properly // (this is only the case if it is a multicast socket. Unicast sockets fail to // receive all data on all sockets) sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, -1); // We don't join the multicast group here, because we may not want to listen // to our own data (halfing our throughput). jasonv - 10/28/2004 } // Add the socket to the hashtable SockInterfacePair sip = new SockInterfacePair(); sip.sock = sock; sip.extInterface = externalInterface; socks.Add(endPoint, sip); // Increase the socket's reference count ++sock.refCount; return(sip); } } }