Skip to content

Instantly share code, notes, and snippets.

@abdullin
Created October 24, 2011 11:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abdullin/1308830 to your computer and use it in GitHub Desktop.
Save abdullin/1308830 to your computer and use it in GitHub Desktop.
SimpleMessage
/// <summary>
/// Source: https://gist.github.com/1308830
/// This simple envelope includes only:
/// <code>
/// Header - int32
/// TotalLength - int32
/// IdLength - int32
/// UTF8-encoded message ID - byte[IdLength]
/// ContractLength - int32
/// UTF-encoded contract name 0 byte[ContractLength]
/// BodyLength - int32
/// SHA1Hash - byte[20]
/// </code>
/// </summary>
public static class SimpleMessage
{
public static int MessageHeader = 20111024;
public static byte[] Write(string messageId, string contractName, byte[] body)
{
using (var m = new MemoryStream())
{
m.Write(BitConverter.GetBytes(MessageHeader), 0, 4);
var contractBytes = Encoding.UTF8.GetBytes(contractName);
var idBytes = Encoding.UTF8.GetBytes(messageId);
var innerLength = 4 + 4 + 4 + contractBytes.Length + 4 + idBytes.Length + 4 + body.Length + 20;
m.Write(BitConverter.GetBytes(innerLength), 0, 4);
m.Write(BitConverter.GetBytes(idBytes.Length), 0, 4);
m.Write(idBytes, 0, idBytes.Length);
m.Write(BitConverter.GetBytes(contractBytes.Length), 0, 4);
m.Write(contractBytes, 0, contractBytes.Length);
m.Write(BitConverter.GetBytes(body.Length), 0, 4);
m.Write(body, 0, body.Length);
using (var cryptoProvider = new SHA1CryptoServiceProvider())
{
var hash = cryptoProvider.ComputeHash(m.ToArray());
m.Write(hash, 0, 20);
}
m.Seek(0, SeekOrigin.Begin);
return m.ToArray();
}
}
public static MessageResult Read(Stream source)
{
var buffer = new byte[8];
var read = source.Read(buffer, 0, 8);
if (read < 8)
throw new InvalidOperationException("Stream too short");
if (BitConverter.ToInt32(buffer, 0) != MessageHeader)
throw new InvalidOperationException("Unexpected header");
var length = BitConverter.ToInt32(buffer, 4);
var body = new byte[length];
source.Read(body, 8, length - 8);
using (var mem = new MemoryStream(body))
using (var reader = new BinaryReader(mem,Encoding.UTF8))
{
mem.Write(buffer, 0, buffer.Length);
var idLength = reader.ReadInt32();
var id = Encoding.UTF8.GetString(reader.ReadBytes(idLength));
var contractLength = reader.ReadInt32();
var contract = Encoding.UTF8.GetString(reader.ReadBytes(contractLength));
var bodyLength = reader.ReadInt32();
var content = reader.ReadBytes(bodyLength);
var actual = reader.ReadBytes(20);
using (var crypto = new SHA1CryptoServiceProvider())
{
var expected = crypto.ComputeHash(mem.ToArray(), 0, length - 20);
if (BitConverter.ToString(actual) != BitConverter.ToString(expected))
throw new InvalidOperationException("SHA1 hashes do not match");
}
return new MessageResult(id, contract, content);
}
}
public sealed class MessageResult
{
public readonly string MessageId;
public readonly string Contract;
public readonly byte[] Body;
public MessageResult(string messageId, string contract, byte[] body)
{
MessageId = messageId;
Contract = contract;
Body = body;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment