public void SetReceiveHandler(IUdpReceiveHandler handler) { Fx.Assert(handler != null, "IUdpReceiveHandler can't be null"); Fx.Assert(handler.MaxReceivedMessageSize == this.receiveHandler.MaxReceivedMessageSize, "new receive handler's max message size doesn't match"); Fx.Assert(this.openCount > 0, "SetReceiveHandler called on a closed UdpSocketReceiveManager"); this.receiveHandler = handler; }
internal UdpSocketReceiveManager(UdpSocket[] receiveSockets, int maxPendingReceivesPerSocket, BufferManager bufferManager, IUdpReceiveHandler receiveHandler) { Fx.Assert(receiveSockets != null, "receiveSockets parameter is null"); Fx.Assert(receiveSockets.Length > 0, "receiveSockets parameter is empty"); Fx.Assert(maxPendingReceivesPerSocket > 0, "maxPendingReceivesPerSocket can't be <= 0"); Fx.Assert(receiveHandler.MaxReceivedMessageSize > 0, "maxReceivedMessageSize must be > 0"); Fx.Assert(bufferManager != null, "bufferManager argument should not be null"); Fx.Assert(receiveHandler != null, "receiveHandler should not be null"); this.receiveHandler = receiveHandler; this.thisLock = new object(); this.bufferManager = bufferManager; this.receiveSockets = receiveSockets; this.maxPendingReceivesPerSocket = maxPendingReceivesPerSocket; this.messageBufferSize = UdpUtility.ComputeMessageBufferSize(receiveHandler.MaxReceivedMessageSize); int maxPendingReceives = maxPendingReceivesPerSocket * receiveSockets.Length; this.receiveBufferPool = new ConnectionBufferPool(this.messageBufferSize, maxPendingReceives); }
//returns false if the message was dropped because the max pending message count was hit. bool IUdpReceiveHandler.HandleDataReceived(ArraySegment <byte> data, EndPoint remoteEndpoint, int interfaceIndex, Action onMessageDequeuedCallback) { BufferManager localBufferManager = this.bufferManager; bool returnBuffer = true; string messageHash = null; Message message = null; bool continueReceiving = true; try { IPEndPoint remoteIPEndPoint = (IPEndPoint)remoteEndpoint; if (localBufferManager != null) { message = UdpUtility.DecodeMessage(this.duplicateDetector, this.messageEncoderFactory.Encoder, localBufferManager, data, remoteIPEndPoint, interfaceIndex, true, out messageHash); if (message != null) { // We pass in the length of the message buffer instead of the length of the message to keep track of the amount of memory that's been allocated continueReceiving = Dispatch(message, data.Array.Length, onMessageDequeuedCallback); returnBuffer = !continueReceiving; } } else { Fx.Assert(this.State != CommunicationState.Opened, "buffer manager should only be null when closing down and the channel instance has taken control of the receive manager."); IUdpReceiveHandler receiveHandler = (IUdpReceiveHandler)this.channelInstance; if (receiveHandler != null) { returnBuffer = false; //let the channel instance take care of the buffer continueReceiving = receiveHandler.HandleDataReceived(data, remoteEndpoint, interfaceIndex, onMessageDequeuedCallback); } else { //both channel and listener are shutting down, so drop the message and stop the receive loop continueReceiving = false; } } } catch (Exception e) { if (Fx.IsFatal(e)) { returnBuffer = false; throw; } HandleReceiveException(e); } finally { if (returnBuffer) { if (message != null) { if (this.duplicateDetector != null) { Fx.Assert(messageHash != null, "message hash should always be available if duplicate detector is enabled"); this.duplicateDetector.RemoveEntry(messageHash); } message.Close(); // implicitly returns the buffer } else { // CSDMain 238600. Both channel and listener are shutting down. There's a race condition happening here // and the bufferManager is not available at this moment. The data buffer ignored here might introduce // an issue with buffer manager, but given that we are in the shutting down case here, it should not be a // big problem. if (localBufferManager != null) { localBufferManager.ReturnBuffer(data.Array); } } } } return(continueReceiving); }