namespace IvyBus { using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Collections; using System.Collections.Specialized; using System.IO; using IvyBus.Properties; /// /// Description résumée de IvyStream. /// internal class IvyTCPStreamV4 : NetworkStream, IvyProtocol { BinaryReader input; BinaryWriter output; IvyProtocol receiver; /* the protocol magic numbers */ internal enum MessageType : ushort { Bye = 0, /* end of the peer */ AddRegexp = 1, /* the peer adds a regexp */ Msg = 2, /* the peer sends a message */ Error = 3, /* error message */ DelBinding = 4, /* the peer removes one of his regex */ // OLD DelRegexp rename to DelBinding EndRegexp = 5, /* no more regexp in the handshake */ StartRegexp = 6, /* avoid race condition in concurrent connexions */ DirectMsg = 7, /* the peer sends a direct message */ Die = 8, /* the peer wants us to quit */ Ping = 9, /* checks the presence of the other */ Pong = 10, /* checks the presence of the other */ AddBinding = 11, /* other methods for binding message based on hash table */ }; internal IvyTCPStreamV4(Socket socket, IvyProtocol _receiver) : base( socket ) { this.input = new BinaryReader(this, Ivy.ivyEncoding); this.output = new BinaryWriter(this, Ivy.ivyEncoding); this.receiver = _receiver; } void IvyProtocol.Close() { this.output.Close(); this.input.Close(); this.Socket.Shutdown(SocketShutdown.Both); base.Close(); } /* * message Syntax: * this is a binary formated message use of network representation * * message Format: MessageType, id , length, string */ private void Serialize(int arg) { output.Write((short)IPAddress.HostToNetworkOrder(arg)); } private void Serialize(string arg) { short length = arg != null ? (short)arg.Length : (short)0; Serialize(length); if (length != 0) output.Write(arg.ToCharArray()); } private void Serialize(string[] arg) { /* serialize count */ Serialize(arg.Length); for (int i = 0; i < arg.Length; i++) { Serialize(arg[i]); } } private void sendMsg(MessageType type, int id, params string[] arg) { lock (this.output) { Serialize((int)type); Serialize(id); Serialize(arg); output.Flush(); } } void IvyProtocol.TokenStartRegexp(int port, string appName) { sendMsg(MessageType.StartRegexp, port, appName); } void IvyProtocol.TokenEndRegexp() { sendMsg(MessageType.EndRegexp, 0, string.Empty); } void IvyProtocol.TokenAddBinding(BindingType type, int id, string expression) { switch (type) { case BindingType.RegularExpression: sendMsg(MessageType.AddRegexp, id, expression); /* perhaps we should perform some checking here */ break; case BindingType.Simple: sendMsg(MessageType.AddBinding, id, expression); /* perhaps we should perform some checking here */ break; } } void IvyProtocol.TokenDelBinding(int id) { sendMsg(MessageType.DelBinding, id, null ); } void IvyProtocol.TokenDirectMsg(int id, string message) { sendMsg(MessageType.DirectMsg, id, message); } void IvyProtocol.TokenPong(int id, string s) { sendMsg(MessageType.Pong, id, s); } void IvyProtocol.TokenPing(int id, string s) { sendMsg(MessageType.Ping, id, s); } void IvyProtocol.TokenBye(int id, string message) { sendMsg(MessageType.Bye, id, message); } void IvyProtocol.TokenDie(int id, string message) { sendMsg(MessageType.Die, id, message); } void IvyProtocol.TokenMsg(int key, string[] args) { sendMsg(MessageType.Msg, key, args ); } void IvyProtocol.TokenError(int key, string arg) { sendMsg(MessageType.Error, key, arg); } private int DeserializeInt() { return IPAddress.NetworkToHostOrder((short)input.ReadInt16()); } private string DeserializeString() { string arg; int val_len; char[] data; val_len = DeserializeInt(); if (val_len != 0) { data = input.ReadChars(val_len); arg = new String(data); } else arg = string.Empty; return arg; } private string[] DeserializeArgument() { int nb_children; string[] arg; /* Deserialize childrens */ nb_children = DeserializeInt(); /* deserialize Value */ arg = new string[nb_children]; for (int i = 0; i < nb_children; i++) { arg[i] = DeserializeString(); } return arg; } bool IvyProtocol.ReceiveMsg() { MessageType msgType = MessageType.Die; int msgId = 0; string[] msgData = null; try { msgType = (MessageType)DeserializeInt(); msgId = DeserializeInt(); msgData = DeserializeArgument(); switch (msgType) { case MessageType.Die: receiver.TokenDie(msgId, msgData[0]); break; case MessageType.Bye: receiver.TokenBye(msgId, msgData[0]); break; case MessageType.AddRegexp: receiver.TokenAddBinding(BindingType.RegularExpression, msgId, msgData[0]); break; case MessageType.AddBinding: receiver.TokenAddBinding(BindingType.Simple, msgId, msgData[0]); break; case MessageType.DelBinding: receiver.TokenDelBinding(msgId); break; case MessageType.EndRegexp: receiver.TokenEndRegexp(); break; case MessageType.Msg: receiver.TokenMsg( msgId, msgData ); break; case MessageType.Pong: receiver.TokenPong( msgId, msgData[0]); break; case MessageType.Ping: receiver.TokenPing( msgId, msgData[0]); break; case MessageType.Error: receiver.TokenError(msgId, msgData[0]); break; case MessageType.StartRegexp: receiver.TokenStartRegexp(msgId, msgData[0]); break; case MessageType.DirectMsg: receiver.TokenDirectMsg(msgId, msgData[0]); break; default: throw new IvyException(Resources.UnknownMessage + msgType); } } catch (EndOfStreamException) { return false; } catch (FormatException) { throw new IvyException(Resources.ProtocolError); } return true; } } }