/// <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();
            }
        }
Пример #2
0
        /// <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();
            }
        }