예제 #1
0
        /// <summary>
        /// Writes this Header to buffer starting at offset
        /// Keep in mind, this API assumes buffer is large enough
        /// for the operation.
        /// </summary>
        /// <param name="buffer">buffer to serialize this Header to</param>
        /// <param name="offset">offset to begin writing at.</param>
        /// <returns>
        /// the new offset.
        /// </returns>
        public int WriteToBuffer(byte[] buffer, int offset)
        {
            var newOffset = offset;

            buffer[newOffset++] = (byte)Name.Length;
            var nameBytes = Encoding.UTF8.GetBytes(Name);

            Buffer.BlockCopy(nameBytes, 0, buffer, newOffset, Name.Length);
            newOffset += Name.Length;

            buffer[newOffset++] = (byte)HeaderType;
            byte[] serializedBytes = null;
            int    valueLength     = 0;

            switch (HeaderType)
            {
            case EventStreamHeaderType.BoolTrue:
            case EventStreamHeaderType.BoolFalse:
                break;

            case EventStreamHeaderType.Byte:
                buffer[newOffset++] = (byte)HeaderValue;
                break;

            case EventStreamHeaderType.Int16:
                serializedBytes = BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder((Int16)HeaderValue));
                Buffer.BlockCopy(serializedBytes, 0, buffer, newOffset, 2);
                newOffset += _sizeOfInt16;
                break;

            case EventStreamHeaderType.Int32:
                serializedBytes = BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder((Int32)HeaderValue));
                Buffer.BlockCopy(serializedBytes, 0, buffer, newOffset, 4);
                newOffset += _sizeOfInt32;
                break;

            case EventStreamHeaderType.Int64:
                serializedBytes = BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder((Int64)HeaderValue));
                Buffer.BlockCopy(serializedBytes, 0, buffer, newOffset, 8);
                newOffset += _sizeOfInt64;
                break;

            case EventStreamHeaderType.ByteBuf:
                serializedBytes = HeaderValue as byte[];
                valueLength     = serializedBytes.Length;
                Buffer.BlockCopy(BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder((Int16)valueLength)), 0,
                                 buffer, newOffset, 2);
                newOffset += _sizeOfInt16;
                Buffer.BlockCopy(serializedBytes, 0, buffer, newOffset, valueLength);
                newOffset += valueLength;
                break;

            case EventStreamHeaderType.String:
                serializedBytes = Encoding.UTF8.GetBytes(HeaderValue as string);
                valueLength     = serializedBytes.Length;
                Buffer.BlockCopy(BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder((Int16)valueLength)), 0,
                                 buffer, newOffset, 2);
                newOffset += _sizeOfInt16;
                Buffer.BlockCopy(serializedBytes, 0, buffer, newOffset, valueLength);
                newOffset += valueLength;
                break;

            case EventStreamHeaderType.Timestamp:
                var tempValue = (Int64)((DateTime)HeaderValue).Subtract(_unixEpoch).TotalMilliseconds;
                serializedBytes = BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder(tempValue));
                Buffer.BlockCopy(serializedBytes, 0, buffer, newOffset, 8);
                newOffset += _sizeOfInt64;
                break;

            case EventStreamHeaderType.UUID:
                serializedBytes = ((Guid)HeaderValue).ToByteArray();
                Buffer.BlockCopy(serializedBytes, 0, buffer, newOffset, serializedBytes.Length);
                newOffset += serializedBytes.Length;
                break;

            default:
                throw new EventStreamParseException(string.Format(CultureInfo.InvariantCulture, "Header Type: {0} is an unknown type.", HeaderType));
            }

            return(newOffset);
        }
예제 #2
0
        /// <summary>
        /// Converts a message into a byte buffer (usually for network transmission).
        /// </summary>
        public byte[] ToByteArray()
        {
            int headersWireLength = 0;

            //first we need to figure out how much space the headers will take up.
            if (Headers != null)
            {
                foreach (var header in Headers)
                {
                    headersWireLength += header.Value.GetWireSize();
                }
            }

            var payloadLength = Payload?.Length ?? 0;
            //total message length is the framing size + the payload size + the headers wire size.
            var totalLength = headersWireLength + payloadLength + FramingSize;

            var messageBuffer = new byte[totalLength];

            //now write the total length and the headers length to the message. make sure to handle endianness conversions
            var offset = 0;

            Buffer.BlockCopy(BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder(totalLength)), 0,
                             messageBuffer, offset, SizeOfInt32);
            offset += SizeOfInt32;
            Buffer.BlockCopy(BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder(headersWireLength)), 0,
                             messageBuffer, offset, SizeOfInt32);
            offset += SizeOfInt32;

            using (var nullStream = new NullStream())
                using (var runningChecksum = new CrcCalculatorStream(nullStream))
                {
                    //write the total length and headers length to the checksum stream.
                    runningChecksum.Write(messageBuffer, 0, offset);
                    //take the current checksum and write it to the message.
                    Buffer.BlockCopy(BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder(runningChecksum.Crc32)), 0,
                                     messageBuffer, offset, SizeOfInt32);
                    //now take the current checksum and write it to the checksum stream.
                    runningChecksum.Write(messageBuffer, offset, SizeOfInt32);
                    offset += SizeOfInt32;

                    //loop over the headers and write them out to the message.
                    if (Headers != null)
                    {
                        foreach (var header in Headers)
                        {
                            offset = header.Value.WriteToBuffer(messageBuffer, offset);
                        }
                        //make sure to add the header bytes to the checksum stream.
                        runningChecksum.Write(messageBuffer, PreludeLen, offset - PreludeLen);
                    }

                    //write the payload to the message.
                    if (Payload != null)
                    {
                        Buffer.BlockCopy(Payload, 0, messageBuffer, offset, Payload.Length);
                        //update the checksum
                        runningChecksum.Write(messageBuffer, offset, Payload.Length);
                        offset += Payload.Length;
                    }

                    //take the final checksum and add it to the end of the message.
                    Buffer.BlockCopy(BitConverter.GetBytes(EndianConversionUtility.HostToNetworkOrder(runningChecksum.Crc32)), 0,
                                     messageBuffer, offset, SizeOfInt32);
                }

            return(messageBuffer);
        }