summaryrefslogtreecommitdiff
path: root/Ivy/IvyTCPStreamV3.cs
diff options
context:
space:
mode:
authorfcolin2007-02-01 12:04:16 +0000
committerfcolin2007-02-01 12:04:16 +0000
commit92757a8d629812303ff3665343bd098917cca611 (patch)
treecd995c9863aa6fc4c32ec5ce247e4c3119eb44a3 /Ivy/IvyTCPStreamV3.cs
parent98ab5d0164040427f7c554febae125686284e2a7 (diff)
downloadivy-csharp-92757a8d629812303ff3665343bd098917cca611.zip
ivy-csharp-92757a8d629812303ff3665343bd098917cca611.tar.gz
ivy-csharp-92757a8d629812303ff3665343bd098917cca611.tar.bz2
ivy-csharp-92757a8d629812303ff3665343bd098917cca611.tar.xz
modification structure svn
Diffstat (limited to 'Ivy/IvyTCPStreamV3.cs')
-rw-r--r--Ivy/IvyTCPStreamV3.cs254
1 files changed, 254 insertions, 0 deletions
diff --git a/Ivy/IvyTCPStreamV3.cs b/Ivy/IvyTCPStreamV3.cs
new file mode 100644
index 0000000..4eef12c
--- /dev/null
+++ b/Ivy/IvyTCPStreamV3.cs
@@ -0,0 +1,254 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Collections;
+using System.Collections.Specialized;
+using System.IO;
+
+namespace IvyBus
+{
+ /// <summary>
+ /// Description résumée de IvyStream.
+ /// </summary>
+ internal class IvyTCPStreamV3 : NetworkStream, IvyProtocol
+ {
+ StreamReader input;
+ StreamWriter output;
+ IvyProtocol receiver;
+
+ /// the protocol separator
+ internal const char ARG_START = '\x02';
+ internal const char ARG_END = '\x03';
+ internal const char MSG_END = '\n';
+
+ internal IvyTCPStreamV3(Socket socket, IvyProtocol _receiver) : base ( socket )
+ {
+ output = new StreamWriter(this, Encoding.ASCII);
+ output.NewLine = MSG_END.ToString();
+ input = new StreamReader(this, Encoding.ASCII);
+ receiver = _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 */
+ };
+
+ /*
+ * message Syntax:
+ * this is text formated message 'type id STX ARG0 {[ETX] ARG1 [ETX] ARGn}\n'
+ *
+ * message Format:
+ MessageType, id , length, string
+ */
+
+ private void sendMsg(MessageType msgType, ushort msgId, string msgData)
+ {
+ // IOException Should be traited upstairs
+ output.Write((ushort)msgType);
+ output.Write(' ');
+ output.Write(msgId);
+ output.Write(ARG_START);
+ output.Write(msgData);
+ output.Write(MSG_END);
+ output.Flush();
+
+ }
+ void IvyProtocol.TokenStartRegexp(ushort port, string appName)
+ {
+ sendMsg(MessageType.StartRegexp, port, appName);
+ }
+ void IvyProtocol.TokenEndRegexp()
+ {
+ sendMsg(MessageType.EndRegexp, 0, "");
+ }
+ void IvyProtocol.TokenApplicationId(ushort priority, string appId)
+ {
+ // NOt implemented in this protocol version
+ }
+
+ void IvyProtocol.TokenAddBinding(BindingType type, ushort id, string expression)
+ {
+ switch (type)
+ {
+ case BindingType.Regexp:
+ sendMsg(MessageType.AddRegexp, id, expression); /* perhaps we should perform some checking here */
+ break;
+ case BindingType.Simple:
+ // NO Simple Binding in this protocol
+ break;
+ }
+ }
+
+ void IvyProtocol.TokenDelBinding(ushort id)
+ {
+ sendMsg(MessageType.DelBinding, id, "");
+ }
+
+ void IvyProtocol.TokenDirectMsg(ushort id, string message)
+ {
+ sendMsg(MessageType.DirectMsg, id, message);
+ }
+ void IvyProtocol.TokenPong(string s)
+ {
+ sendMsg(MessageType.Pong, 0, s);
+ }
+ void IvyProtocol.TokenPing(string s)
+ {
+ sendMsg(MessageType.Ping, 0, s);
+ }
+
+ void IvyProtocol.TokenBye(ushort id, string message)
+ {
+ sendMsg(MessageType.Bye, id, message);
+ }
+
+ void IvyProtocol.TokenDie(ushort id, string message)
+ {
+ sendMsg(MessageType.Die, id, message);
+ }
+
+ void IvyProtocol.TokenMsg(ushort key, string[] args)
+ {
+ string delimiter = "" + ARG_END;
+ string data = string.Join(delimiter, args);
+ // a bad protocol implementation in C add a delimiter to the end of each arg
+ // we must add a delimiter to the end
+ data += delimiter;
+ sendMsg(MessageType.Msg, key, data);
+ }
+
+ void IvyProtocol.TokenError(ushort key, string arg)
+ {
+ sendMsg(MessageType.Msg, key, arg);
+ }
+
+ private ushort DeserializeShort()
+ {
+ int read;
+ ushort ret = 0;
+ char digit;
+ // this will eat next non digit char ie space
+ do
+ {
+ read = input.Read();
+ if (read < 0)
+ throw new EndOfStreamException();
+ digit = (char)read;
+ if (Char.IsDigit(digit))
+ ret = (ushort)(ret * 10 + (digit - 0x30));
+ } while (Char.IsDigit(digit));
+ return ret;
+ }
+ private string DeserializeString(char sep)
+ {
+ int read;
+ char car;
+ StringBuilder str = new StringBuilder();
+ // this will eat next non separator char
+ do
+ {
+ read = input.Read();
+ if (read < 0)
+ throw new EndOfStreamException();
+ car = (char)read;
+ if (car != sep ) str.Append(car);
+ } while (car != sep);
+ return str.ToString();
+ }
+
+ bool IvyProtocol.receiveMsg()
+ {
+ MessageType msgType = MessageType.Die;
+ ushort msgId = 0;
+ string msgData = null;
+
+ try
+ {
+ msgType = (MessageType)DeserializeShort();
+ msgId = DeserializeShort();
+ msgData = DeserializeString(MSG_END);
+
+ switch (msgType)
+ {
+ case MessageType.Die:
+ receiver.TokenDie(msgId, msgData);
+ break;
+
+ case MessageType.Bye:
+ receiver.TokenBye(msgId, msgData);
+ break;
+
+ case MessageType.AddRegexp:
+ receiver.TokenAddBinding(BindingType.Regexp, msgId, msgData);
+ break;
+
+ case MessageType.DelBinding:
+ receiver.TokenDelBinding(msgId);
+ break;
+
+ case MessageType.EndRegexp:
+ receiver.TokenEndRegexp();
+ break;
+
+ case MessageType.Msg:
+ // a bad protocol implementation in C add a delimiter to the end of each arg
+ // we must remove a delimiter to the end
+ if ( msgData.Length > 0 )
+ msgData = msgData.Remove(msgData.Length - 1,1);
+ receiver.TokenMsg(msgId, msgData.Split( ARG_END ));
+ break;
+
+ case MessageType.Pong:
+ receiver.TokenPong(msgData);
+ break;
+
+ case MessageType.Ping:
+ receiver.TokenPing(msgData);
+ break;
+
+ case MessageType.Error:
+ receiver.TokenError(msgId, msgData);
+ break;
+
+ case MessageType.StartRegexp:
+ receiver.TokenStartRegexp(msgId, msgData);
+ break;
+
+ case MessageType.DirectMsg:
+ receiver.TokenDirectMsg(msgId, msgData);
+ break;
+ default:
+ throw new IvyException("protocol error, unknown message type " + msgType);
+
+ }
+
+
+
+ }
+ catch (EndOfStreamException)
+ {
+ return false;
+ }
+ catch (FormatException)
+ {
+ throw new IvyException("protocol error on msgType");
+ }
+
+
+ return true;
+ }
+
+ }
+}