2 // Microsoft.Web.Services.Messaging.SoapTcpTransport.cs
4 // Author: Todd Berman <tberman@gentoo.org>
6 // (C) 2003 Todd Berman
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;
36 SoapTcpChannel newChan = new SoapTcpChannel (uri, Formatter);
37 Channels.Add (uri.AbsoluteUri, newChan);
39 newChan.BeginReceive(new AsyncCallback (OnReceive), newChan);
47 public IAsyncResult BeginSend (SoapEnvelope env,
49 AsyncCallback callback,
52 SoapTcpChannel chan = GetTcpChannel (dest);
54 return new SendAsyncResult (chan, env, callback, state);
57 public void EndSend (IAsyncResult result)
60 throw new ArgumentNullException ("result");
63 if(result is SendAsyncResult) {
64 AsyncResult.End (result);
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)
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() );
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];
102 //This is what Hervey says it does, not WSE2 TP tested.
104 if(to.Host == "localhost") {
105 tcp = new SoapTcpListener (IPAddress.Loopback, port);
107 tcp = new SoapTcpListener (IPAddress.Any, port);
113 tcp.BeginAcceptSocket (new AsyncCallback (OnAcceptSocket), tcp);
115 _listeners[to_with_port] = tcp;
120 Receivers[to] = rType;
124 public void Send (SoapEnvelope env, Uri to)
126 SoapTcpChannel tcp = GetTcpChannel (to);
131 public void UnregisterAll ()
133 lock (Channels.SyncRoot) {
136 foreach(SoapTcpListener tcp in _listeners.Values) {
143 public void UnregisterPort (Uri to)
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;
155 if(tcp.ReleaseReference () == 0) {
156 _listeners.Remove(newTo);
159 Receivers.Remove(to);
164 //private string Scheme {
165 // get { return "soap.tcp"; }
168 private void OnAcceptSocket (IAsyncResult result)
171 SoapTcpListener tcp = (SoapTcpListener) result.AsyncState;
174 Socket sock = tcp.EndAcceptSocket (result);
175 if(tcp.IsListening != true) {
176 tcp.BeginAcceptSocket (new AsyncCallback (OnAcceptSocket), result);
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);
191 private void OnReceive (IAsyncResult result)
193 SoapTcpChannel tcp = result.AsyncState as SoapTcpChannel;
194 SoapEnvelope env = null;
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);
207 env.Context.Channel = tcp;
209 AddressingHeaders header = env.Context.Addressing;
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; }