**** Merged from MCS ****
[mono-project.git] / mcs / class / Microsoft.Web.Services / Microsoft.Web.Services.Messaging / SoapTcpTransport.cs
blob543411359028bfa69d77b3f518e24a3f2e3d39d3
1 //
2 // Microsoft.Web.Services.Messaging.SoapTcpTransport.cs
3 //
4 // Author: Todd Berman <tberman@gentoo.org>
5 //
6 // (C) 2003 Todd Berman
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;
15 namespace Microsoft.Web.Services.Messaging
17 public class SoapTcpTransport : SoapTransport, ISoapTransport
20 public static string Scheme = "soap.tcp";
22 private Hashtable _listeners = new Hashtable ();
23 private Hashtable _receivers = new Hashtable ();
25 public SoapTcpChannel GetTcpChannel (Uri to)
27 SoapTcpChannel chan = null;
28 lock (Channels.SyncRoot) {
29 int port = (to.Port == -1) ? 8081 : to.Port;
31 Uri uri = new Uri (String.Format("{0}://{1}:{2}", Scheme, to.Host, port));
33 chan = Channels[uri.AbsoluteUri] as SoapTcpChannel;
35 if(chan == null) {
36 SoapTcpChannel newChan = new SoapTcpChannel (uri, Formatter);
37 Channels.Add (uri.AbsoluteUri, newChan);
39 newChan.BeginReceive(new AsyncCallback (OnReceive), newChan);
40 chan = newChan;
44 return chan;
47 public IAsyncResult BeginSend (SoapEnvelope env,
48 Uri dest,
49 AsyncCallback callback,
50 object state)
52 SoapTcpChannel chan = GetTcpChannel (dest);
54 return new SendAsyncResult (chan, env, callback, state);
57 public void EndSend (IAsyncResult result)
59 if(result == null) {
60 throw new ArgumentNullException ("result");
63 if(result is SendAsyncResult) {
64 AsyncResult.End (result);
65 } else {
66 throw new InvalidOperationException ("Invalid IAsyncResult Type");
70 public void RegisterPort (Uri to, Type rType)
72 GenericRegister (to, rType);
75 public void RegisterPort (Uri to, SoapReceiver rec)
77 GenericRegister (to, rec);
80 private void GenericRegister (Uri to, object rType)
82 if(to == null) {
83 throw new ArgumentNullException ("to");
85 if(Scheme != to.Scheme) {
86 throw new ArgumentException ("invalid Scheme");
88 //if(to.Host != "localhost") {
89 // throw new ArgumentException ("Host name " + to.Host + " does not equal " + Dns.GetHostName() );
90 //}
92 lock(Channels.SyncRoot) {
93 if(Receivers.Contains (to) == true) {
94 throw new ArgumentException ("URI has already been registered");
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];
100 if(tcp == null) {
102 //This is what Hervey says it does, not WSE2 TP tested.
104 if(to.Host == "localhost") {
105 tcp = new SoapTcpListener (IPAddress.Loopback, port);
106 } else {
107 tcp = new SoapTcpListener (IPAddress.Any, port);
110 tcp.Start ();
111 tcp.AddReference ();
113 tcp.BeginAcceptSocket (new AsyncCallback (OnAcceptSocket), tcp);
115 _listeners[to_with_port] = tcp;
116 } else {
117 tcp.AddReference ();
120 Receivers[to] = rType;
124 public void Send (SoapEnvelope env, Uri to)
126 SoapTcpChannel tcp = GetTcpChannel (to);
128 tcp.Send (env);
131 public void UnregisterAll ()
133 lock (Channels.SyncRoot) {
135 Receivers.Clear ();
136 foreach(SoapTcpListener tcp in _listeners.Values) {
137 tcp.Stop ();
139 _listeners.Clear ();
143 public void UnregisterPort (Uri to)
145 if(to == null) {
146 throw new ArgumentNullException ("to");
148 lock(Channels.SyncRoot) {
149 int port = to.Port < 0 ? 8081 : to.Port;
151 Uri newTo = new Uri (Scheme + "://" + to.Host + ":" + port);
152 SoapTcpListener tcp = _listeners[newTo] as SoapTcpListener;
154 if(tcp != null) {
155 if(tcp.ReleaseReference () == 0) {
156 _listeners.Remove(newTo);
157 tcp.Stop();
159 Receivers.Remove(to);
164 //private string Scheme {
165 // get { return "soap.tcp"; }
168 private void OnAcceptSocket (IAsyncResult result)
170 try {
171 SoapTcpListener tcp = (SoapTcpListener) result.AsyncState;
173 if(tcp != null) {
174 Socket sock = tcp.EndAcceptSocket (result);
175 if(tcp.IsListening != true) {
176 tcp.BeginAcceptSocket (new AsyncCallback (OnAcceptSocket), result);
178 if(sock != null) {
179 SoapTcpChannel chan = new SoapTcpChannel (sock, Formatter);
180 lock (Channels.SyncRoot) {
181 Channels.Add (chan.Destination.AbsoluteUri, chan);
183 chan.BeginReceive (new AsyncCallback (OnReceive), chan);
186 } catch (Exception)
191 private void OnReceive (IAsyncResult result)
193 SoapTcpChannel tcp = result.AsyncState as SoapTcpChannel;
194 SoapEnvelope env = null;
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 ();
206 if(env != null) {
207 env.Context.Channel = tcp;
209 AddressingHeaders header = env.Context.Addressing;
211 header.Load (env);
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"));
219 SoapReceiver.DispatchMessage (env);
223 protected IDictionary Receivers {
224 get { return _receivers; }