channel example implementation
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.Channels.Tcp / TcpServerChannel.cs
1 //
2 // System.Runtime.Remoting.Channels.Tcp.TcpServerChannel.cs
3 //
4 // Author: Rodrigo Moya (rodrigo@ximian.com)
5 //
6 // 2002 (C) Copyright, Ximian, Inc.
7 //
8
9 using System.Collections;
10 using System.Runtime.Remoting.Messaging;
11 using System.Text.RegularExpressions;
12 using System.Net.Sockets;
13 using System.Net;
14 using System.Threading;
15 using System.IO;
16
17 namespace System.Runtime.Remoting.Channels.Tcp
18 {
19         public class TcpServerTransportSink : IServerChannelSink, IChannelSinkBase
20         {
21                 IServerChannelSink next_sink;
22                 
23                 public TcpServerTransportSink (IServerChannelSink next)
24                 {
25                         next_sink = next;
26                 }
27                 
28                 public IServerChannelSink NextChannelSink {
29                         get {
30                                 return next_sink;
31                         }
32                 }
33
34                 [MonoTODO]
35                 public IDictionary Properties {
36                         get {
37                                 throw new NotImplementedException ();
38                         }
39                 }
40
41                 [MonoTODO]
42                 public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
43                                                   IMessage msg, ITransportHeaders headers, Stream stream)
44                 {
45                         throw new NotImplementedException ();
46                 }
47
48                 [MonoTODO]
49                 public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
50                                                 IMessage msg, ITransportHeaders headers)
51                 {
52                         throw new NotImplementedException ();
53                 }
54                 
55                 public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
56                                                         IMessage requestMsg,
57                                                         ITransportHeaders requestHeaders,
58                                                         Stream requestStream,
59                                                         out IMessage responseMsg,
60                                                         out ITransportHeaders responseHeaders,
61                                                         out Stream responseStream)
62                 {
63                         // this is the first sink, and TcpServerChannel does not call it.
64                         throw new NotSupportedException ();
65                 }
66
67                 internal void InternalProcessMessage (Stream requestStream)
68                 {
69                         Console.WriteLine ("ProcessMessageInternal");
70                 }
71         }
72
73         public class TcpServerChannel : IChannelReceiver, IChannel
74         {
75                 int port = 0;
76                 string name = "tcp";
77                 string host;
78                 int priority = 1;
79                 Thread server_thread = null;
80                 TcpListener listener;
81                 TcpServerTransportSink sink;
82                 ChannelDataStore channel_data;
83                 
84                 void Init (IServerChannelSinkProvider provider) {
85                         if (provider == null) {
86                                 provider = new BinaryServerFormatterSinkProvider ();
87                         }
88                         IServerChannelSink next_sink = provider.CreateSink (this);
89
90                         host = Dns.GetHostByName(Dns.GetHostName()).HostName;
91                         
92                         string [] uris = null;
93                         
94                         if (port != 0) {
95                                 uris = new String [1];
96                                 uris [0] = GetChannelUri ();
97                         }
98                         
99                         channel_data = new ChannelDataStore (uris);;
100
101                         sink = new TcpServerTransportSink (next_sink);
102                         
103                         listener = new TcpListener (port);
104                         StartListening (null);
105                 }
106                 
107                 public TcpServerChannel (int port)
108                 {
109                         this.port = port;
110                         Init (null);
111                 }
112
113                 public TcpServerChannel (IDictionary properties,
114                                          IServerChannelSinkProvider serverSinkProvider)
115                 {
116                         port = (int)properties ["port"];
117                         Init (serverSinkProvider);
118                 }
119
120                 public TcpServerChannel (string name, int port,
121                                          IServerChannelSinkProvider serverSinkProvider)
122                 {
123                         name = name;
124                         this.port = port;
125                         Init (serverSinkProvider);
126                 }
127                 
128                 public TcpServerChannel (string name, int port)
129                 {
130                         name = name;
131                         this.port = port;
132                         Init (null);
133                 }
134                 
135                 public object ChannelData
136                 {
137                         get {
138                                 return channel_data;
139                         }
140                 }
141
142                 public string ChannelName
143                 {
144                         get {
145                                 return name;
146                         }
147                 }
148
149                 public int ChannelPriority
150                 {
151                         get {
152                                 return priority;
153                         }
154                 }
155
156                 public string GetChannelUri ()
157                 {
158                         return "tcp://" + host + ":" + port;
159                 }
160                 
161                 public string[] GetUrlsForUri (string uri)
162                 {
163                         string [] result = new String [1];
164
165                         if (uri.IndexOf ('/') != 0)
166                                 result [0] = GetChannelUri () + "/" + uri;
167                         else
168                                 result [0] = GetChannelUri () + uri;
169
170                         return result;
171                 }
172
173                 public string Parse (string url, out string objectURI)
174                 {
175                         int port;
176                         
177                         string host = TcpChannel.ParseTcpURL (url, out objectURI, out port);
178
179                         return "tcp://" + host + ":" + port;
180                 }
181
182                 void WaitForConnections ()
183                 {
184                         while (true) {
185                                 TcpClient client = listener.AcceptTcpClient ();
186
187                                 sink.InternalProcessMessage (client.GetStream ());
188                                 
189                                 client.Close ();
190                         }
191                 }
192                 
193                 public void StartListening (object data)
194                 {
195                         if (server_thread == null) {
196                                 listener.Start ();
197                                 if (port == 0) {
198                                         port = ((IPEndPoint)listener.LocalEndpoint).Port;
199                                         channel_data.ChannelUris = new String [1];
200                                         channel_data.ChannelUris [0] = GetChannelUri ();
201                                 }
202
203                                 server_thread = new Thread (new ThreadStart (WaitForConnections));
204                                 server_thread.Start ();
205                         }
206                 }
207
208                 public void StopListening (object data)
209                 {
210                         if (server_thread != null) {
211                                 server_thread.Abort ();
212                                 server_thread = null;
213                                 listener.Stop ();
214                         }
215                 }
216         }
217 }