summaryrefslogtreecommitdiff
path: root/CSharp/Ivy/IvyPPC/IvyTCPStreamV4.cs
blob: 1fead5a6da467097cea97c3f300afd500130564d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections;
using System.IO;

namespace IvyBus
{
	/// <summary>
	/// Description résumée de IvyStream.
	/// </summary>
	public class IvyTCPStreamV4 :  NetworkStream
	{
		BinaryReader input;
		BinaryWriter output;
		public IvyTCPStreamV4(Socket socket) : base( socket, true ) 
		{
			input = new BinaryReader( new BufferedStream(this),Encoding.ASCII);
			output = new BinaryWriter( new BufferedStream(this), Encoding.ASCII);
		}
		/* 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 */
			DelRegexp = 4,		/* the peer removes one of his regex */
			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 */
			DelBinding = 12,	/* other methods for binding message based on hash table */
			ApplicationId = 13,	/* on start send my ID and priority */
		};
		/*
		 * message Syntax:
		 * this is a binary formated message use of network representation
		 * 
		 * message Format:
				MessageType, id , length, string 
		 */
		private void  sendMsg(MessageType type, int id, byte[] arg)
		{
			try
			{
				output.Write( (ushort)IPAddress.HostToNetworkOrder( (short)type ) );
				output.Write( (ushort)IPAddress.HostToNetworkOrder( (short)id ) );
				output.Write( (ushort)IPAddress.HostToNetworkOrder( (short)arg.Length ) );
				output.Write( arg );
				output.Flush();
			}
			catch (IOException ie)
			{
				Console.Error.WriteLine("received an exception: " + ie.Message);
				Console.Error.WriteLine(ie.StackTrace);
			}
		}
        internal void sendStartRegexp(int port, string appName)
        {
            sendMsg(MessageType.StartRegexp, port, Encoding.ASCII.GetBytes(appName));
        }
        internal void sendEndRegexp()
        {
            sendMsg(MessageType.EndRegexp, 0, Encoding.ASCII.GetBytes(""));
        }
        internal void sendApplicationId(int priority, string appId)
        {
            sendMsg(MessageType.ApplicationId, priority, Encoding.ASCII.GetBytes(appId));
        }

        internal void sendBinding(Ivy.ApplicationBinding bind)
        {
            sendMsg(bind.type == Ivy.BindingType.BindRegexp ? IvyTCPStreamV4.MessageType.AddRegexp : IvyTCPStreamV4.MessageType.AddBinding, bind.key, Encoding.ASCII.GetBytes(bind.regexp)); /* perhaps we should perform some checking here */
        }

        internal void delBinding(Ivy.ApplicationBinding bind)
        {
            sendMsg(bind.type == Ivy.BindingType.BindRegexp ? IvyTCPStreamV4.MessageType.DelRegexp : IvyTCPStreamV4.MessageType.DelBinding, bind.key, Encoding.ASCII.GetBytes(""));
        }

        internal void sendDirectMsg(int id, string message)
        {
            sendMsg(MessageType.DirectMsg, id, Encoding.ASCII.GetBytes(message));
        }
        internal void sendPong(byte[] s)
        {
            sendMsg(MessageType.Pong, 0, s);
        }
        internal void sendPing(string s)
        {
            sendMsg(MessageType.Ping, 0, Encoding.ASCII.GetBytes(s));
        }

        internal void sendBye(string message)
        {
            sendMsg(MessageType.Bye, 0, Encoding.ASCII.GetBytes(message));
        }

        internal void sendDie(string message)
        {
            sendMsg(MessageType.Die, 0, Encoding.ASCII.GetBytes(message));
        }

        internal void sendMsg(int key, IvyArgument args)
		{
            sendMsg(MessageType.Msg, key, args.Serialize() );
        }
		internal bool  receiveMsg(out MessageType type, out int id, out byte[] data)
		{
			int length = 0;
			data = null;
			id = 0;
			type = MessageType.Die;

			try
			{
				type = (MessageType)(ushort) IPAddress.NetworkToHostOrder( (short) input.ReadUInt16() );
				id = (ushort) IPAddress.NetworkToHostOrder( (short) input.ReadUInt16());
				length = (ushort) IPAddress.NetworkToHostOrder( (short) input.ReadUInt16());
				data = input.ReadBytes( length );
			}
			catch (EndOfStreamException nfe)
			{
				return false;
			}
			catch (FormatException nfe)
			{
				throw new IvyException("protocol error on msgType");
			}
			
			
			return true;
		}
		
	}
}