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; }