internal UdpChannelListener(UdpTransportBindingElement udpTransportBindingElement, BindingContext context) : base(context.Binding) { Fx.Assert(udpTransportBindingElement != null, "udpTransportBindingElement can't be null"); Fx.Assert(context != null, "BindingContext parameter can't be null"); this.udpTransportBindingElement = udpTransportBindingElement; this.cleanedUp = 0; this.duplicateDetector = null; if (udpTransportBindingElement.DuplicateMessageHistoryLength > 0) { this.duplicateDetector = new DuplicateMessageDetector(udpTransportBindingElement.DuplicateMessageHistoryLength); } this.onChannelClosed = new EventHandler(OnChannelClosed); // We should only throw this exception if the user specified realistic MaxReceivedMessageSize less than or equal to max message size over UDP. // If the user specified something bigger like Long.MaxValue, we shouldn't stop them. if (this.udpTransportBindingElement.MaxReceivedMessageSize <= UdpConstants.MaxMessageSizeOverIPv4 && this.udpTransportBindingElement.SocketReceiveBufferSize < this.udpTransportBindingElement.MaxReceivedMessageSize) { throw FxTrace.Exception.ArgumentOutOfRange("SocketReceiveBufferSize", this.udpTransportBindingElement.SocketReceiveBufferSize, SR.Property1LessThanOrEqualToProperty2("MaxReceivedMessageSize", this.udpTransportBindingElement.MaxReceivedMessageSize, "SocketReceiveBufferSize", this.udpTransportBindingElement.SocketReceiveBufferSize)); } int maxBufferSize = (int)Math.Min(udpTransportBindingElement.MaxReceivedMessageSize, UdpConstants.MaxMessageSizeOverIPv4); this.bufferManager = BufferManager.CreateBufferManager(udpTransportBindingElement.MaxBufferPoolSize, maxBufferSize); this.messageEncoderFactory = UdpUtility.GetEncoder(context); UdpUtility.ValidateDuplicateDetectionAndRetransmittionSupport(this.messageEncoderFactory, this.udpTransportBindingElement.RetransmissionSettings.Enabled, this.udpTransportBindingElement.DuplicateMessageHistoryLength > 0); InitUri(context); //Note: because we are binding the sockets in InitSockets, we can start receiving data immediately. //If there is a delay between the Building of the listener and the call to Open, stale data could build up //inside the Winsock buffer. We have decided that making sure the port is updated correctly in the listen uri //(e.g. in the ListenUriMode.Unique case) before leaving the build step is more important than the //potential for stale data. InitSockets(context.ListenUriMode == ListenUriMode.Unique); Fx.Assert(!this.listenUri.IsDefaultPort, "Listen Uri's port should never be the default port: " + this.listenUri); }
public static Message DecodeMessage(DuplicateMessageDetector duplicateDetector, MessageEncoder encoder, BufferManager bufferManager, ArraySegment <byte> data, IPEndPoint remoteEndPoint, int interfaceIndex, bool ignoreSerializationException, out string messageHash) { Fx.Assert(data != null, "data can't be null"); Fx.Assert(remoteEndPoint != null, "remoteEndPoint can't be null"); Fx.Assert(encoder != null, "encoder can't be null"); Fx.Assert(bufferManager != null, "bufferManager can't be null"); Message message = null; messageHash = null; if (duplicateDetector == null || !duplicateDetector.IsDuplicate(data, out messageHash)) { try { message = encoder.ReadMessage(data, bufferManager); } catch (XmlException error) { // Don't throw serialization exceptions when the channel supports Multicast if (!ignoreSerializationException) { throw; } FxTrace.Exception.AsWarning(error); } if (message != null) { message.Properties.Add(RemoteEndpointMessageProperty.Name, new RemoteEndpointMessageProperty(remoteEndPoint.Address.ToString(), remoteEndPoint.Port)); NetworkInterfaceMessageProperty networkInterfaceMessageProperty = new NetworkInterfaceMessageProperty(interfaceIndex); networkInterfaceMessageProperty.AddTo(message); } } return(message); }
protected override void OnClosing() { if (this.channelInstance != null) { lock (ThisLock) { if (this.channelInstance != null) { if (this.channelInstance.TransferReceiveManagerOwnership(this.socketReceiveManager, this.duplicateDetector)) { //don't clean these objects up, they now belong to the channel instance this.socketReceiveManager = null; this.duplicateDetector = null; this.bufferManager = null; } } this.channelInstance = null; } } base.OnClosing(); }
// Since ChannelListener and channel lifetimes can be different, we need a // way to transfer the socketReceiveManager and DuplicateMessageDetection // objects to the channel if the listener gets closed. If this method succeeds, then // this also indicates that the bufferManager is no longer owned by the channel listener, // so we have to clean that up also. internal bool TransferReceiveManagerOwnership(UdpSocketReceiveManager socketReceiveManager, DuplicateMessageDetector duplicateDetector) { bool success = false; if (this.State == CommunicationState.Opened) { lock (ThisLock) { if (this.State == CommunicationState.Opened) { Fx.Assert(this.ReceiveManager == null, "ReceiveManager is already set to a non-null value"); Fx.Assert(this.DuplicateDetector == null, "DuplicateDetector is already set to a non-null value"); this.ReceiveManager = socketReceiveManager; this.OwnsBufferManager = true; this.ReceiveManager.SetReceiveHandler(this); this.DuplicateDetector = duplicateDetector; success = true; } } } return(success); }
public static Message DecodeMessage(DuplicateMessageDetector duplicateDetector, MessageEncoder encoder, BufferManager bufferManager, ArraySegment<byte> data, IPEndPoint remoteEndPoint, int interfaceIndex, bool ignoreSerializationException, out string messageHash) { Fx.Assert(data != null, "data can't be null"); Fx.Assert(remoteEndPoint != null, "remoteEndPoint can't be null"); Fx.Assert(encoder != null, "encoder can't be null"); Fx.Assert(bufferManager != null, "bufferManager can't be null"); Message message = null; messageHash = null; if (duplicateDetector == null || !duplicateDetector.IsDuplicate(data, out messageHash)) { try { message = encoder.ReadMessage(data, bufferManager); } catch (XmlException error) { // Don't throw serialization exceptions when the channel supports Multicast if (!ignoreSerializationException) { throw; } FxTrace.Exception.AsWarning(error); } if (message != null) { message.Properties.Add(RemoteEndpointMessageProperty.Name, new RemoteEndpointMessageProperty(remoteEndPoint.Address.ToString(), remoteEndPoint.Port)); NetworkInterfaceMessageProperty networkInterfaceMessageProperty = new NetworkInterfaceMessageProperty(interfaceIndex); networkInterfaceMessageProperty.AddTo(message); } } return message; }