removed unused variables
[mono.git] / mcs / class / Microsoft.Web.Services / Microsoft.Web.Services.Messaging / SoapTcpTransport.cs
1 //
2 // Microsoft.Web.Services.Messaging.SoapTcpTransport.cs
3 //
4 // Author: Todd Berman <tberman@gentoo.org>
5 //
6 // (C) 2003 Todd Berman
7
8 using System;
9 using System.Net;
10 using System.Net.Sockets;
11 using System.Collections;
12 using Microsoft.Web.Services;
13 using Microsoft.Web.Services.Addressing;
14
15 namespace Microsoft.Web.Services.Messaging
16 {
17         public class SoapTcpTransport : SoapTransport, ISoapTransport
18         {
19                 
20                 public static string Scheme = "soap.tcp";
21                 
22                 private Hashtable _listeners = new Hashtable ();
23                 private Hashtable _receivers = new Hashtable ();
24
25                 public SoapTcpChannel GetTcpChannel (Uri to)
26                 {
27                         SoapTcpChannel chan = null;
28                         lock (Channels.SyncRoot) {
29                                 int port = (to.Port == -1) ? 8081 : to.Port;
30
31                                 Uri uri = new Uri (String.Format("{0}://{1}:{2}", Scheme, to.Host, port));
32
33                                 chan = Channels[uri.AbsoluteUri] as SoapTcpChannel;
34
35                                 if(chan == null) {
36                                         SoapTcpChannel newChan = new SoapTcpChannel (uri, Formatter);
37                                         Channels.Add (uri.AbsoluteUri, newChan);
38                                 
39                                         newChan.BeginReceive(new AsyncCallback (OnReceive), newChan);
40                                         chan = newChan;
41                                 
42                                 }
43                         }
44                         return chan;
45                 }
46
47                 public IAsyncResult BeginSend (SoapEnvelope env,
48                                                 Uri dest,
49                                                 AsyncCallback callback,
50                                                 object state)
51                 {
52                         SoapTcpChannel chan = GetTcpChannel (dest);
53
54                         return new SendAsyncResult (chan, env, callback, state);
55                 }
56
57                 public void EndSend (IAsyncResult result)
58                 {
59                         if(result == null) {
60                                 throw new ArgumentNullException ("result");
61                         }
62
63                         if(result is SendAsyncResult) {
64                                 AsyncResult.End (result);
65                         } else {
66                                 throw new InvalidOperationException ("Invalid IAsyncResult Type");
67                         }
68                 }
69
70                 public void RegisterPort (Uri to, Type rType)
71                 {
72                         GenericRegister (to, rType);
73                 }
74
75                 public void RegisterPort (Uri to, SoapReceiver rec)
76                 {
77                         GenericRegister (to, rec);
78                 }
79
80                 private void GenericRegister (Uri to, object rType)
81                 {
82                         if(to == null) {
83                                 throw new ArgumentNullException ("to");
84                         }
85                         if(Scheme != to.Scheme) {
86                                 throw new ArgumentException ("invalid Scheme");
87                         }
88                         //if(to.Host != "localhost") {
89                         //      throw new ArgumentException ("Host name " + to.Host + " does not equal " + Dns.GetHostName() );
90                         //}
91
92                         lock(Channels.SyncRoot) {
93                                 if(Receivers.Contains (to) == true) {
94                                         throw new ArgumentException ("URI has already been registered");
95                                 }
96                                 int port = to.Port <= -1 ? 8081 : to.Port;
97                                 Uri to_with_port = new Uri (Scheme + "://" + to.Host + ":" + port);
98                                 SoapTcpListener tcp = (SoapTcpListener) _listeners[to_with_port];
99
100                                 if(tcp == null) {
101                                         
102                                         //This is what Hervey says it does, not WSE2 TP tested.
103                                         
104                                         if(to.Host == "localhost") {
105                                                 tcp = new SoapTcpListener (IPAddress.Loopback, port);
106                                         } else {
107                                                 tcp = new SoapTcpListener (IPAddress.Any, port);
108                                         }
109
110                                         tcp.Start ();
111                                         tcp.AddReference ();
112
113                                         tcp.BeginAcceptSocket (new AsyncCallback (OnAcceptSocket), tcp);
114
115                                         _listeners[to_with_port] = tcp;
116                                 } else {
117                                         tcp.AddReference ();
118                                 }
119
120                                 Receivers[to] = rType;
121                         }
122                 }
123
124                 public void Send (SoapEnvelope env, Uri to)
125                 {
126                         SoapTcpChannel tcp = GetTcpChannel (to);
127
128                         tcp.Send (env);
129                 }
130
131                 public void UnregisterAll ()
132                 {
133                         lock (Channels.SyncRoot) {
134
135                                 Receivers.Clear ();
136                                 foreach(SoapTcpListener tcp in _listeners.Values) {
137                                         tcp.Stop ();
138                                 }
139                                 _listeners.Clear ();
140                         }
141                 }
142
143                 public void UnregisterPort (Uri to)
144                 {
145                         if(to == null) {
146                                 throw new ArgumentNullException ("to");
147                         }
148                         lock(Channels.SyncRoot) {
149                                 int port = to.Port < 0 ? 8081 : to.Port;
150
151                                 Uri newTo = new Uri (Scheme + "://" + to.Host + ":" + port);
152                                 SoapTcpListener tcp = _listeners[newTo] as SoapTcpListener;
153
154                                 if(tcp != null) {
155                                         if(tcp.ReleaseReference () == 0) {
156                                                 _listeners.Remove(newTo);
157                                                 tcp.Stop();
158                                         }
159                                         Receivers.Remove(to);
160                                 }
161                         }
162                 }
163
164                 //private string Scheme {
165                 //      get { return "soap.tcp"; }
166                 //}
167
168                 private void OnAcceptSocket (IAsyncResult result)
169                 {
170                         try {
171                                 SoapTcpListener tcp = (SoapTcpListener) result.AsyncState;
172
173                                 if(tcp != null) {
174                                         Socket sock = tcp.EndAcceptSocket (result);
175                                         if(tcp.IsListening != true) {
176                                                 tcp.BeginAcceptSocket (new AsyncCallback (OnAcceptSocket), result);
177                                         }
178                                         if(sock != null) {
179                                                 SoapTcpChannel chan = new SoapTcpChannel (sock, Formatter);
180                                                 lock (Channels.SyncRoot) {
181                                                         Channels.Add (chan.Destination.AbsoluteUri, chan);
182                                                 }
183                                                 chan.BeginReceive (new AsyncCallback (OnReceive), chan);
184                                         }
185                                 }
186                         } catch (Exception)
187                         {
188                         }
189                 }
190
191                 private void OnReceive (IAsyncResult result)
192                 {
193                         SoapTcpChannel tcp = result.AsyncState as SoapTcpChannel;
194                         SoapEnvelope env = null;
195
196                         try {
197                                 env = tcp.EndReceive (result);
198                                 tcp.BeginReceive (new AsyncCallback (OnReceive), tcp);
199                         } catch (Exception) {
200                                 lock (Channels.SyncRoot) {
201                                         Channels.Remove (tcp.Destination.AbsoluteUri);
202                                         tcp.Close ();
203                                 }
204                         }
205                         
206                         if(env != null) {
207                                 env.Context.Channel = tcp;
208
209                                 AddressingHeaders header = env.Context.Addressing;
210
211                                 header.Load (env);
212
213                                 //FIXME: There is a lot more checking to do here for a valid message.
214                                 if(header.To != null) {
215                                         if(header.To.Value.Scheme != "soap.tcp") {
216                                                 SoapReceiver.DispatchMessageFault (env, new ArgumentException ("soap error"));
217                                         }
218                                 }
219                                 SoapReceiver.DispatchMessage (env);
220                         }
221                 }
222                 
223                 protected IDictionary Receivers {
224                         get { return _receivers; }
225                 }
226                 
227         }
228
229 }