Created
October 24, 2011 11:37
-
-
Save abdullin/1308830 to your computer and use it in GitHub Desktop.
SimpleMessage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <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