| using System; | 
| using System.Collections.Generic; | 
| using System.IO; | 
| using System.Text; | 
|   | 
| namespace Taobao.Top.Link.Endpoints | 
| { | 
|     //simple protocol impl, match protocolVersion=2 | 
|     public class MessageIO | 
|     { | 
|         public static Message ReadMessage(Stream input) | 
|         { | 
|             var buffer = new BinaryReader(input); | 
|             Message msg = new Message(); | 
|             msg.ProtocolVersion = buffer.ReadByte(); | 
|             msg.MessageType = buffer.ReadByte(); | 
|             // read kv | 
|             IDictionary<string, object> dict = new Dictionary<string, object>(); | 
|             short headerType = buffer.ReadInt16(); | 
|             while (headerType != MessageType.HeaderType.EndOfHeaders) | 
|             { | 
|                 if (headerType == MessageType.HeaderType.Custom) | 
|                     dict.Add(ReadCountedString(buffer), ReadCustomValue(buffer)); | 
|                 else if (headerType == MessageType.HeaderType.StatusCode) | 
|                     msg.StatusCode = buffer.ReadInt32(); | 
|                 else if (headerType == MessageType.HeaderType.StatusPhrase) | 
|                     msg.StatusPhase = ReadCountedString(buffer); | 
|                 else if (headerType == MessageType.HeaderType.Flag) | 
|                     msg.Flag = buffer.ReadInt32(); | 
|                 else if (headerType == MessageType.HeaderType.Token) | 
|                     msg.Token = ReadCountedString(buffer); | 
|                 headerType = buffer.ReadInt16(); | 
|             } | 
|             msg.Content = dict; | 
|             return msg; | 
|         } | 
|         public static void WriteMessage(Stream input, Message message) | 
|         { | 
|             var buffer = new BinaryWriter(input); | 
|             buffer.Write((byte)message.ProtocolVersion); | 
|             buffer.Write((byte)message.MessageType); | 
|   | 
|             if (message.StatusCode > 0) | 
|             { | 
|                 buffer.Write(MessageType.HeaderType.StatusCode); | 
|                 buffer.Write(message.StatusCode); | 
|             } | 
|             if (message.StatusPhase != null && message.StatusPhase != "") | 
|             { | 
|                 buffer.Write(MessageType.HeaderType.StatusPhrase); | 
|                 WriteCountedString(buffer, message.StatusPhase); | 
|             } | 
|             if (message.Flag > 0) | 
|             { | 
|                 buffer.Write(MessageType.HeaderType.Flag); | 
|                 buffer.Write(message.Flag); | 
|             } | 
|             if (message.Token != null && message.Token != "") | 
|             { | 
|                 buffer.Write(MessageType.HeaderType.Token); | 
|                 WriteCountedString(buffer, message.Token); | 
|             } | 
|             if (message.Content != null) | 
|             { | 
|                 foreach (var i in message.Content) | 
|                     WriteCustomHeader(buffer, i.Key, i.Value); | 
|             } | 
|             buffer.Write(MessageType.HeaderType.EndOfHeaders); | 
|         } | 
|         // UTF-8 only | 
|         private static string ReadCountedString(BinaryReader buffer) | 
|         { | 
|             int size = buffer.ReadInt32(); | 
|             return size > 0 ? Encoding.UTF8.GetString(buffer.ReadBytes(size)) : null; | 
|         } | 
|         private static void WriteCountedString(BinaryWriter buffer, string value) | 
|         { | 
|             int strLength = 0; | 
|             if (value != null) | 
|                 strLength = value.Length; | 
|   | 
|             if (strLength > 0) | 
|             { | 
|                 byte[] strBytes = Encoding.UTF8.GetBytes(value); | 
|                 buffer.Write(strBytes.Length); | 
|                 buffer.Write(strBytes); | 
|             } | 
|             else | 
|                 buffer.Write(0); | 
|         } | 
|         private static void WriteCustomHeader(BinaryWriter buffer, string name, object value) | 
|         { | 
|             buffer.Write(MessageType.HeaderType.Custom); | 
|             WriteCountedString(buffer, name); | 
|             WriteCustomValue(buffer, value); | 
|         } | 
|         private static object ReadCustomValue(BinaryReader buffer) | 
|         { | 
|             byte format = buffer.ReadByte(); | 
|             switch (format) | 
|             { | 
|                 case MessageType.ValueFormat.Void: | 
|                     return null; | 
|                 case MessageType.ValueFormat.Byte: | 
|                     return buffer.ReadByte(); | 
|                 case MessageType.ValueFormat.Int16: | 
|                     return buffer.ReadInt16(); | 
|                 case MessageType.ValueFormat.Int32: | 
|                     return buffer.ReadInt32(); | 
|                 case MessageType.ValueFormat.Int64: | 
|                     return buffer.ReadInt64(); | 
|                 case MessageType.ValueFormat.Date: | 
|                     return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1).AddMilliseconds(buffer.ReadInt64())); | 
|                 case MessageType.ValueFormat.ByteArray: | 
|                     return buffer.ReadBytes(buffer.ReadInt32()); | 
|                 default: | 
|                     return ReadCountedString(buffer); | 
|             } | 
|         } | 
|         private static void WriteCustomValue(BinaryWriter buffer, object value) | 
|         { | 
|             if (value == null) | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.Void); | 
|                 return; | 
|             } | 
|             Type type = value.GetType(); | 
|             if (typeof(byte).Equals(type) || typeof(Byte).Equals(type)) | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.Byte); | 
|                 buffer.Write((byte)value); | 
|             } | 
|             else if (typeof(short).Equals(type)) | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.Int16); | 
|                 buffer.Write((short)value); | 
|             } | 
|             else if (typeof(int).Equals(type) || typeof(Int32).Equals(type)) | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.Int32); | 
|                 buffer.Write((int)value); | 
|             } | 
|             else if (typeof(long).Equals(type) || typeof(Int64).Equals(type)) | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.Int64); | 
|                 buffer.Write((long)value); | 
|             } | 
|             else if (typeof(DateTime).Equals(type)) | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.Date); | 
|                 buffer.Write(((DateTime)value).Ticks); | 
|             } | 
|             else if (typeof(byte[]).Equals(type)) | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.ByteArray); | 
|                 var data = value as byte[]; | 
|                 buffer.Write(data.Length); | 
|                 buffer.Write(data); | 
|             } | 
|             else | 
|             { | 
|                 buffer.Write(MessageType.ValueFormat.CountedString); | 
|                 WriteCountedString(buffer, (string)value); | 
|             } | 
|         } | 
|     } | 
| } |