Exemple #1
0
        /// <summary>
        /// Creates a byte array useful for transmission, without packaging the data.
        /// </summary>
        /// <returns>Byte array.</returns>
        internal byte[] ToHeaderBytes(long contentLength)
        {
            SetHeaderFieldBitmap();

            byte[] headerFieldsBytes = new byte[8];
            headerFieldsBytes = BitArrayToBytes(HeaderFields);
            headerFieldsBytes = ReverseByteArray(headerFieldsBytes);

            byte[] ret = new byte[headerFieldsBytes.Length];
            Buffer.BlockCopy(headerFieldsBytes, 0, ret, 0, headerFieldsBytes.Length);

            #region Header-Fields

            for (int i = 0; i < HeaderFields.Length; i++)
            {
                if (HeaderFields[i])
                {
                    if (_Debug)
                    {
                        Console.WriteLine("Header field " + i + " is set");
                    }
                    MessageField field = GetMessageField(i);
                    switch (i)
                    {
                    case 0:     // preshared key
                        if (_Debug)
                        {
                            Console.WriteLine("PresharedKey: " + Encoding.UTF8.GetString(PresharedKey));
                        }
                        ret = AppendBytes(ret, PresharedKey);
                        break;

                    case 1:     // status
                        if (_Debug)
                        {
                            Console.WriteLine("Status: " + Status.ToString() + " " + (int)Status);
                        }
                        ret = AppendBytes(ret, IntegerToBytes((int)Status));
                        break;

                    default:
                        throw new ArgumentException("Unknown bit number.");
                    }
                }
            }

            #endregion

            #region Prepend-Message-Length

            long finalLen = ret.Length + contentLength;
            if (_Debug)
            {
                Console.WriteLine("Content length: " + finalLen + " (" + ret.Length + " + " + contentLength + ")");
            }

            byte[] lengthHeader = Encoding.UTF8.GetBytes(finalLen.ToString() + ":");
            byte[] final        = new byte[(lengthHeader.Length + ret.Length)];
            Buffer.BlockCopy(lengthHeader, 0, final, 0, lengthHeader.Length);
            Buffer.BlockCopy(ret, 0, final, lengthHeader.Length, ret.Length);

            #endregion

            if (_Debug)
            {
                Console.WriteLine("ToHeaderBytes returning: " + Encoding.UTF8.GetString(final));
            }
            return(final);
        }
Exemple #2
0
        /// <summary>
        /// Awaitable async method to build the Message object from data that awaits in a NetworkStream or SslStream, returning the stream itself.
        /// </summary>
        /// <returns>Always returns true (void cannot be a return parameter).</returns>
        internal async Task <bool> BuildStream()
        {
            try
            {
                #region Read-Message-Length

                using (MemoryStream msgLengthMs = new MemoryStream())
                {
                    while (true)
                    {
                        byte[] data = await ReadFromNetwork(1, "MessageLength");

                        await msgLengthMs.WriteAsync(data, 0, 1);

                        if (data[0] == 58)
                        {
                            break;
                        }
                    }

                    byte[] msgLengthBytes = msgLengthMs.ToArray();
                    if (msgLengthBytes == null || msgLengthBytes.Length < 1)
                    {
                        return(false);
                    }
                    string msgLengthString = Encoding.UTF8.GetString(msgLengthBytes).Replace(":", "");

                    long length;
                    Int64.TryParse(msgLengthString, out length);
                    Length = length;

                    Log("Message payload length: " + Length + " bytes");
                }

                #endregion Read-Message-Length

                #region Process-Header-Fields

                byte[] headerFields = await ReadFromNetwork(8, "HeaderFields");

                headerFields = ReverseByteArray(headerFields);
                HeaderFields = new BitArray(headerFields);

                long payloadLength = Length - 8;

                for (int i = 0; i < HeaderFields.Length; i++)
                {
                    if (HeaderFields[i])
                    {
                        MessageField field = GetMessageField(i);
                        Log("Reading header field " + i + " " + field.Name + " " + field.Type.ToString() + " " + field.Length + " bytes");
                        object val = await ReadField(field.Type, field.Length, field.Name);

                        SetMessageValue(field, val);
                        payloadLength -= field.Length;
                    }
                }

                if (MetadataLength > 0)
                {
                    MetadataBytes = await ReadFromNetwork(MetadataLength, "MetadataBytes");

                    // payloadLength -= MetadataLength;
                    Metadata = SerializationHelper.DeserializeJson <Dictionary <object, object> >(Encoding.UTF8.GetString(MetadataBytes));
                }

                ContentLength = payloadLength;
                Data          = null;

                #endregion Process-Header-Fields

                return(true);
            }
            catch (Exception e)
            {
                Log(Environment.NewLine +
                    "Message build from stream exception:" +
                    Environment.NewLine +
                    e.ToString() +
                    Environment.NewLine);

                return(false);
            }
        }
Exemple #3
0
        /// <summary>
        /// Awaitable async method to build the Message object from data that awaits in a NetworkStream or SslStream, returning the stream itself.
        /// </summary>
        /// <returns>Always returns true (void cannot be a return parameter).</returns>
        internal async Task <bool> BuildStream()
        {
            try
            {
                #region Read-Message-Length

                using (MemoryStream msgLengthMs = new MemoryStream())
                {
                    while (true)
                    {
                        byte[] data = await ReadFromNetwork(1, "MessageLength");

                        await msgLengthMs.WriteAsync(data, 0, 1);

                        if (data[0] == 58)
                        {
                            break;
                        }
                    }

                    byte[] msgLengthBytes = msgLengthMs.ToArray();
                    if (msgLengthBytes == null || msgLengthBytes.Length < 1)
                    {
                        return(false);
                    }
                    string msgLengthString = Encoding.UTF8.GetString(msgLengthBytes).Replace(":", "");

                    long length;
                    Int64.TryParse(msgLengthString, out length);
                    Length = length;

                    if (_Debug)
                    {
                        Console.WriteLine("Message payload length: " + Length + " bytes");
                    }
                }

                #endregion

                #region Process-Header-Fields

                byte[] headerFields = await ReadFromNetwork(8, "HeaderFields");

                headerFields = ReverseByteArray(headerFields);
                HeaderFields = new BitArray(headerFields);

                long payloadLength = Length - 8;

                for (int i = 0; i < HeaderFields.Length; i++)
                {
                    if (HeaderFields[i])
                    {
                        MessageField field = GetMessageField(i);
                        if (_Debug)
                        {
                            Console.WriteLine("Reading header field " + i + " " + field.Name + " " + field.Type.ToString() + " " + field.Length + " bytes");
                        }
                        object val = await ReadField(field.Type, field.Length, field.Name);

                        SetMessageValue(field, val);
                        payloadLength -= field.Length;
                    }
                }

                ContentLength = payloadLength;
                Data          = null;

                if (_NetworkStream != null)
                {
                    DataStream = _NetworkStream;
                }
                else if (_SslStream != null)
                {
                    DataStream = _SslStream;
                }
                else
                {
                    throw new IOException("No suitable input stream found.");
                }

                #endregion

                return(true);
            }
            catch (Exception e)
            {
                if (_Debug)
                {
                    Console.WriteLine(Common.SerializeJson(e));
                }
                throw e;
            }
            finally
            {
                if (_Debug)
                {
                    Console.WriteLine("Message build completed:");
                    Console.WriteLine(this.ToString());
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Awaitable async method to build the Message object from data that awaits in a NetworkStream or SslStream.
        /// </summary>
        /// <returns>Always returns true (void cannot be a return parameter).</returns>
        public async Task <bool> Build()
        {
            try
            {
                int read           = 0;
                int totalBytesRead = 0;

                #region Read-Message-Length

                using (MemoryStream msgLengthMs = new MemoryStream())
                {
                    byte[] msgLengthBuffer = new byte[1];

                    if (_NetworkStream != null)
                    {
                        while ((read = await _NetworkStream.ReadAsync(msgLengthBuffer, 0, msgLengthBuffer.Length)) > 0)
                        {
                            await msgLengthMs.WriteAsync(msgLengthBuffer, 0, read);

                            // check if end of headers reached
                            if (msgLengthBuffer[0] == 58)
                            {
                                break;
                            }
                        }
                    }
                    else if (_SslStream != null)
                    {
                        while ((read = await _SslStream.ReadAsync(msgLengthBuffer, 0, msgLengthBuffer.Length)) > 0)
                        {
                            await msgLengthMs.WriteAsync(msgLengthBuffer, 0, read);

                            totalBytesRead += read;

                            // check if end of headers reached
                            if (msgLengthBuffer[0] == 58)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Unknown stream type.");
                    }

                    byte[] msgLengthBytes = msgLengthMs.ToArray();
                    if (msgLengthBytes == null || msgLengthBytes.Length < 1)
                    {
                        return(false);
                    }
                    string msgLengthString = Encoding.UTF8.GetString(msgLengthBytes).Replace(":", "");

                    long length;
                    Int64.TryParse(msgLengthString, out length);
                    Length = length;

                    if (_Debug)
                    {
                        Console.WriteLine("Message payload length: " + Length + " bytes");
                    }
                }

                #endregion

                #region Process-Header-Fields

                byte[] headerFields = await ReadFromNetwork(8, "HeaderFields");

                headerFields = ReverseByteArray(headerFields);
                HeaderFields = new BitArray(headerFields);

                long payloadBytes = Length - 8;

                for (int i = 0; i < HeaderFields.Length; i++)
                {
                    if (HeaderFields[i])
                    {
                        MessageField field = GetMessageField(i);
                        if (_Debug)
                        {
                            Console.WriteLine("Reading header field " + i + " " + field.Name + " " + field.Type.ToString() + " " + field.Length + " bytes");
                        }
                        object val = await ReadField(field.Type, field.Length, field.Name);

                        SetMessageValue(field, val);
                        payloadBytes -= field.Length;
                    }
                }

                Data = await ReadFromNetwork(payloadBytes, "Payload");

                #endregion

                return(true);
            }
            catch (Exception e)
            {
                if (_Debug)
                {
                    Console.WriteLine("Message build exception: " + e.Message);
                }
                throw;
            }
            finally
            {
                if (_Debug)
                {
                    Console.WriteLine("Message build completed");
                }
            }
        }