internal void CloseInputChannel( SoapUdpInputChannel channel ) { lock ( InputChannels.SyncRoot ) { // // remove the channel // if ( InputChannels.Contains( channel ) ) InputChannels.Remove( channel ); // // Decrement reference count on the socket for active channels // lock ( _sockets ) { IPEndPoint localEP = GetLocalIPEndPoint( channel.LocalEndpoint.TransportAddress ); SoapUdpSocket socket = _sockets[ localEP ] as SoapUdpSocket; if ( socket != null ) { if ( socket.ReleaseReference( ) == 0 ) { socket.Close( ); _sockets.Remove( localEP ); } } } } }
/// <summary> /// Build an ISoapInputChannel for the specified endpoint. /// </summary> /// <param name="endpoint"></param> /// <param name="capabilities"></param> /// <returns></returns> ISoapInputChannel ISoapTransport.GetInputChannel( EndpointReference endpoint, SoapChannelCapabilities capabilities ) { if ( endpoint == null ) throw new ArgumentNullException( "endpoint" ); if ( capabilities == SoapChannelCapabilities.ActivelyListening && endpoint.TransportAddress.Scheme != UriScheme ) throw new ArgumentException( "Invalid Transport Scheme specified" ); if ( capabilities != SoapChannelCapabilities.None && capabilities != SoapChannelCapabilities.ActivelyListening ) throw new NotSupportedException( "Unsupported SoapChannelCapabilities Flags" ); Debug( "GetInputChannel TransportAddress: " + endpoint.TransportAddress.ToString( ) ); // // NOTE: Transport level receiving requires that we map the transport address to // one of the local interfaces for the machine. // IPEndPoint localEP = GetLocalIPEndPoint( endpoint.TransportAddress ); if ( localEP == null ) throw new ArgumentException( "Transport address " + endpoint.TransportAddress.ToString( ) + " could not be mapped to a local network interface." ); // // Lock the InputChannels collection while we register the new channel. // lock ( InputChannels.SyncRoot ) { // // Determine whether the request channel already exists. // SoapUdpInputChannel channel = InputChannels[ endpoint ] as SoapUdpInputChannel; SoapUdpSocket socket; if ( channel != null ) return channel; // // Lock the sockets collection while checking for an existing socket // or creating a new one. // lock ( _sockets ) { socket = _sockets[ localEP ] as SoapUdpSocket; if ( socket == null ) { // // There is no suitable socket available. Create a new one, // increment it's reference count and start receiving packets. // socket = new SoapUdpSocket( localEP, _options ); _sockets[ localEP ] = socket; socket.AddReference( ); socket.BeginReceiveFrom( new AsyncCallback( OnReceiveComplete ), socket ); } else { // // Increment the reference count on the listener for unregister behaviour // socket.AddReference( ); } } // // Create the channel, then modify the via so that it matches // the local endpoint address. // // TODO: Fix the race condition here where a packet might be // received before the channel is established for // dispatching. // channel = new SoapUdpInputChannel( endpoint, socket, this ); // // TODO: Do not do Via for the Any address // channel.LocalEndpoint.Via = new Via( ConvertToUri( localEP ) ); // // Record the channel // InputChannels.Add( channel ); return channel; } }