Esempio n. 1
0
        /// <summary>
        ///     Callback for when data is available for reading from the underlying stream.
        /// </summary>
        /// <param name="asyncResult">The async result from the read.</param>
        private void ReadComplete(IAsyncResult asyncResult)
        {
            int bytesRead;
            var dataStream = (NetworkStream)asyncResult.AsyncState;

            try {
                if (tcpClient.Connected && dataStream.CanRead && dataStream.DataAvailable)
                {
                    bytesRead = dataStream.EndRead(asyncResult);

                    if (bytesRead == 1)
                    {
                        var messageBytes = new Collection <byte>();
                        messageBytes.Add(headerByte[0]);

                        Collection <byte> lengthBytes = MqttHeader.ReadLengthBytes(dataStream);
                        int length = MqttHeader.CalculateLength(lengthBytes);
                        messageBytes.AddRange(lengthBytes);

                        // we've got the bytes that make up the header, inc the size, read the .
                        var remainingMessage = new byte[length];
                        int messageBytesRead = dataStream.Read(remainingMessage, 0, length);
                        if (messageBytesRead < length)
                        {
                            // we haven't got all the message, need to figure oput what to do.
                        }
                        messageBytes.AddRange(remainingMessage);

                        FireDataAvailableEvent(messageBytes);
                    }
                }

                // initiate a read for the next byte which will be the header bytes so long as
                // we're still connected to the underlying client
                if (tcpClient.Connected && networkStream.CanRead)
                {
                    dataStream.BeginRead(headerByte, 0, 1, ReadComplete, dataStream);
                }
            } catch (IOException ex) {
                // close the underlying connection
                this.Disconnect();

                if (ConnectionDropped != null)
                {
                    ConnectionDropped(this, new ConnectionDroppedEventArgs(ex));
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        ///     Callback for when data has been read from the underlying network stream.
        /// </summary>
        /// <param name="asyncResult">The async result from the read.</param>
        private void ReadHeaderComplete(IAsyncResult asyncResult)
        {
            var readWrapper = (ReadWrapper)asyncResult.AsyncState;

            try {
                var bytesRead = readWrapper.Stream.EndRead(asyncResult);
                if (bytesRead == 0)
                {
                    // Nothing read, we will just try another read from the stream.
                    Log.Debug("Async network stream read returned 0 bytes, continuing to search for header.");
                    readWrapper.ReadState = ConnectionReadState.Header;
                }
                else if (tcpClient.Connected && readWrapper.Stream.CanRead)
                {
                    if (readWrapper.ReadState == ConnectionReadState.Header && readWrapper.Stream.DataAvailable)
                    {
                        Log.Info("Reading message arriving on the wire.");

                        readWrapper.MessageBytes.Add(readWrapper.Buffer[0]);

                        var lengthBytes     = MqttHeader.ReadLengthBytes(readWrapper.Stream);
                        var remainingLength = MqttHeader.CalculateLength(lengthBytes);

                        // update the read wrapper with the header bytes, and a resized read buffer
                        // to capture the remaining length.
                        readWrapper.MessageBytes.AddRange(lengthBytes);

                        // no content, so yield the message early, else transition to reading the content.
                        if (remainingLength == 0)
                        {
                            Log.Debug("Message receipt complete. Has empty content length so handing off now.");
                            FireDataAvailableEvent(readWrapper.MessageBytes);
                        }
                        else
                        {
                            // total bytes of content is the remaining length plus the header.
                            readWrapper.TotalBytes = remainingLength + readWrapper.MessageBytes.Count;
                            readWrapper.RecalculateNextReadSize();
                            readWrapper.ReadState = ConnectionReadState.Content;
                        }
                    }
                    else if (readWrapper.ReadState == ConnectionReadState.Content)
                    {
                        // stash what we've read.
                        readWrapper.MessageBytes.AddRange(readWrapper.Buffer.Take(bytesRead));
                        Log.Debug(m => m("Message Content read {0:n0} of {1:n0} expected remaining bytes.", bytesRead, readWrapper.TotalBytes));

                        // if we haven't yet read all of the message repeat the read otherwise if
                        // we're finished process the message and switch back to waiting for the next header.
                        if (readWrapper.IsReadComplete)
                        {
                            // reset the read buffer to accommodate the remaining length (last - what was read)
                            readWrapper.RecalculateNextReadSize();
                        }
                        else
                        {
                            Log.Debug(m => m("Message receipt complete ({0:n0} total bytes including all headers), handing off to handlers.", readWrapper.MessageBytes.Count));
                            readWrapper.ReadState = ConnectionReadState.Header;
                            FireDataAvailableEvent(readWrapper.MessageBytes);
                        }
                    }

                    // if we've switched to reading a header then recreate the read dwrapper for the next message
                    if (readWrapper.ReadState == ConnectionReadState.Header)
                    {
                        readWrapper = new ReadWrapper(readWrapper.Stream);
                    }
                    // we can still read etc
                    // initiate a read for the next set of bytes which will be the header bytes so long as
                    // we're still connected to the underlying client
                    readWrapper.Stream.BeginRead(readWrapper.Buffer, 0, readWrapper.NextReadSize, ReadHeaderComplete, readWrapper);
                }
            } catch (IOException ex) {
                Log.Debug("Error occurred during async read from broker network stream. Initiating broker disconnect", ex);

                // close the underlying connection
                this.Disconnect();

                if (ConnectionDropped != null)
                {
                    ConnectionDropped(this, new ConnectionDroppedEventArgs(ex));
                }
            }
        }