/// <summary> /// Synchronously reads the next network packet if it is available. /// </summary> /// <param name="deriveHeader">Indicates whether it is necessary to take header from the provided connection.</param> private void ReadNextPortion(bool deriveHeader) { int bytesRead = 0; int lengthToRead = 0; if (!deriveHeader) { // try to read the remaining part of the packet if (this._currentPacketBytesRead < this._currentPacketSize) { // read the next part of the packet lengthToRead = Math.Min(this._currentPacketSize - this._currentPacketBytesRead, this._readBuffer.Length); this._validLength = this.ReadFromSocket(this._readBuffer, 0, lengthToRead); if (this._validLength == 0) { throw GenuineExceptions.Get_Receive_Portion(); } // Fixed in 2.5.9.7 //this._tcpSocketInfo.ITransportContext.ConnectionManager.IncreaseBytesReceived(this._validLength); this._currentPacketBytesRead += this._validLength; this._currentPosition = 0; if (this._currentPacketBytesRead == this._currentPacketSize && this._messageRead) { this.ReadingCompleted(); } return; } // the underlying stream ends if (this._messageRead) { return; } // prepare for reading a header this._currentPosition = 0; } lengthToRead = TcpConnectionManager.HEADER_SIZE; if (deriveHeader) { if (this._tcpSocketInfo.ReceivingBufferCurrentPosition > 0) { Buffer.BlockCopy(this._tcpSocketInfo.ReceivingHeaderBuffer, 0, this._readBuffer, 0, this._tcpSocketInfo.ReceivingBufferCurrentPosition); } this._currentPosition = this._tcpSocketInfo.ReceivingBufferCurrentPosition; } // read the header while (this._currentPosition < lengthToRead) { bytesRead = this.ReadFromSocket(this._readBuffer, this._currentPosition, lengthToRead - this._currentPosition); if (bytesRead == 0) { throw GenuineExceptions.Get_Receive_Portion(); } // Fixed in 2.5.9.7 //this._tcpSocketInfo.ITransportContext.ConnectionManager.IncreaseBytesReceived(bytesRead); this._currentPosition += bytesRead; } // parse the header if (this._readBuffer[0] != MessageCoder.COMMAND_MAGIC_CODE) { throw GenuineExceptions.Get_Receive_IncorrectData(); } this._currentPacketSize = MessageCoder.ReadInt32(this._readBuffer, 1); this._messageRead = this._readBuffer[5] != 0; this._currentPacketBytesRead = 0; // and read the part of the packet if (this._currentPacketBytesRead < this._currentPacketSize) { // read the next part of the packet lengthToRead = Math.Min(this._currentPacketSize - this._currentPacketBytesRead, this._readBuffer.Length); this._validLength = this.ReadFromSocket(this._readBuffer, 0, lengthToRead); if (this._validLength == 0) { throw GenuineExceptions.Get_Receive_Portion(); } // Fixed in 2.5.9.7 //this._tcpSocketInfo.ITransportContext.ConnectionManager.IncreaseBytesReceived(this._validLength); this._currentPacketBytesRead += this._validLength; this._currentPosition = 0; } if (this._currentPacketBytesRead == this._currentPacketSize && this._messageRead) { this.ReadingCompleted(); } }
/// <summary> /// Receives the content synchronously. /// </summary> private void ReceiveSynchronously() { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; byte[] receiveBuffer = null; this._receivingThreadClosed.Reset(); try { int mtu = (int)this.ITransportContext.IParameterProvider[GenuineParameter.UdpMtu]; for ( ; ;) { if (this._closing) { return; } if (BufferPool.GENERAL_BUFFER_SIZE >= mtu) { receiveBuffer = BufferPool.ObtainBuffer(); } else { receiveBuffer = new byte[mtu]; } try { IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0); EndPoint endPointReference = ipEndPoint; int bytesReceived = this._socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref endPointReference); ipEndPoint = (IPEndPoint)endPointReference; // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0) { binaryLogWriter.WriteTransportContentEvent(LogCategory.Transport, "UdpConnectionManager.ReceiveSynchronously", LogMessageType.ReceivingFinished, null, null, null, binaryLogWriter[LogCategory.Transport] > 1 ? new MemoryStream(GenuineUtility.CutOutBuffer(receiveBuffer, 0, bytesReceived)) : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this.DbgConnectionId, bytesReceived, ipEndPoint.ToString(), null, null, "Content is received from {0}.", ipEndPoint.ToString()); } // parse the header if (bytesReceived < HEADER_SIZE) { throw GenuineExceptions.Get_Receive_IncorrectData(); } if (receiveBuffer[0] != MessageCoder.COMMAND_MAGIC_CODE) { throw GenuineExceptions.Get_Receive_IncorrectData(); } // get the packet identifier byte[] guidBuffer = new byte[16]; Buffer.BlockCopy(receiveBuffer, 1, guidBuffer, 0, 16); Guid packetGuid = new Guid(guidBuffer); // and chunk number int chunkNumber = MessageCoder.ReadInt32(receiveBuffer, 17); bool isLast = chunkNumber < 0; if (chunkNumber < 0) { chunkNumber = -chunkNumber; } chunkNumber--; // process the chunk StreamAssembled streamAssembled; lock (this._streams.SyncRoot) { streamAssembled = this._streams[packetGuid] as StreamAssembled; if (streamAssembled == null) { this._streams[packetGuid] = streamAssembled = new StreamAssembled(ipEndPoint, HEADER_SIZE); } if (streamAssembled.IsProcessed) { continue; } } string uri = "gudp://" + ipEndPoint.ToString(); HostInformation remote = this.ITransportContext.KnownHosts[uri]; remote.Renew(this._closeInvocationConnectionAfterInactivity, false); if ((int)this.ITransportContext.IParameterProvider[GenuineParameter.CompatibilityLevel] <= 0) { remote.UpdateUri(uri, 0, false); } if (streamAssembled.BufferReceived(chunkNumber, receiveBuffer, bytesReceived, isLast)) { // prepare it for processing this._streams.Remove(packetGuid); streamAssembled.IsProcessed = true; // read the remote host URI if ((int)this.ITransportContext.IParameterProvider[GenuineParameter.CompatibilityLevel] > 0) { BinaryReader binaryReader = new BinaryReader(streamAssembled); // read the URI byte[] uriBuffer = new byte[16]; GenuineUtility.ReadDataFromStream(streamAssembled, uriBuffer, 0, uriBuffer.Length); Guid remoteHostUriGuid = new Guid(uriBuffer); string receivedUri = "_gudp://" + remoteHostUriGuid.ToString("N"); // read the remote host unique identifier int remoteHostUniqueIdentifier = binaryReader.ReadInt32(); // update the host information remote.UpdateUri(receivedUri, remoteHostUniqueIdentifier, false); // and skip the skip space GenuineUtility.CopyStreamToStream(streamAssembled, Stream.Null, binaryReader.ReadInt16()); } // LOG: if (remote.PhysicalAddress == null && binaryLogWriter != null && binaryLogWriter[LogCategory.HostInformation] > 0) { binaryLogWriter.WriteHostInformationEvent("UdpConnectionManager.ReceiveSynchronously", LogMessageType.HostInformationCreated, null, remote, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, this.DbgConnectionId, "HostInformation is ready for actions."); } remote.PhysicalAddress = endPointReference; this.ITransportContext.IIncomingStreamHandler.HandleMessage(streamAssembled, remote, GenuineConnectionType.Persistent, string.Empty, -1, false, this._iMessageRegistrator, null, null); } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.Connection, "UdpConnectionManager.ReceiveSynchronously", LogMessageType.ReceivingFinished, ex, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, this.DbgConnectionId, 0, 0, 0, null, null, null, null, "UDP socket failure."); } if (this._closing) { return; } this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GUdpSocketException, ex, this.Local, null)); } } } finally { this._receivingThreadClosed.Set(); } }