2 // TcpChannelListener.cs
5 // Marcos Cobena (marcoscobena@gmail.com)
7 // Copyright 2007 Marcos Cobena (http://www.youcannoteatbits.org/)
11 using System.Collections.Generic;
14 using System.Net.Sockets;
15 using System.ServiceModel.Description;
17 using System.Threading;
20 namespace System.ServiceModel.Channels
22 internal class TcpChannelListener<TChannel> : InternalChannelListenerBase<TChannel>
23 where TChannel : class, IChannel
25 BindingContext context;
27 IDuplexSession session;
29 TcpListener tcp_listener;
31 public TcpChannelListener (TcpTransportBindingElement source,
32 BindingContext context) : base (context.Binding)
34 MessageEncoder encoder = null;
35 XmlDictionaryReaderQuotas quotas = null;
37 if (context.ListenUriMode == ListenUriMode.Explicit)
39 context.ListenUriRelativeAddress != null ?
40 new Uri (context.ListenUriBaseAddress, context.ListenUriRelativeAddress) :
41 context.ListenUriBaseAddress;
43 throw new NotImplementedException ();
45 foreach (BindingElement be in context.RemainingBindingElements) {
46 MessageEncodingBindingElement mbe = be as MessageEncodingBindingElement;
48 encoder = CreateEncoder<TChannel> (mbe);
49 quotas = mbe.GetProperty<XmlDictionaryReaderQuotas> (context);
55 encoder = new BinaryMessageEncoder ();
57 info = new TcpChannelInfo (source, encoder, quotas);
60 public override Uri Uri {
61 get { return listen_uri; }
64 List<ManualResetEvent> accept_handles = new List<ManualResetEvent> ();
66 protected override TChannel OnAcceptChannel (TimeSpan timeout)
68 TcpClient client = null;
69 if (tcp_listener.Pending ()) {
70 client = tcp_listener.AcceptTcpClient ();
72 var wait = new ManualResetEvent (false);
73 tcp_listener.BeginAcceptTcpClient (delegate (IAsyncResult result) {
74 client = tcp_listener.EndAcceptTcpClient (result);
76 accept_handles.Remove (wait);
78 if (State == CommunicationState.Closing)
80 accept_handles.Add (wait);
81 wait.WaitOne (timeout);
84 return null; // onclose
86 if (typeof (TChannel) == typeof (IDuplexSessionChannel))
87 return (TChannel) (object) new TcpDuplexSessionChannel (this, info, client);
89 // FIXME: To implement more.
90 throw new NotImplementedException ();
94 protected override bool OnWaitForChannel (TimeSpan timeout)
96 throw new NotImplementedException ();
99 // CommunicationObject
101 protected override void OnAbort ()
103 if (State == CommunicationState.Closed)
108 protected override void OnClose (TimeSpan timeout)
110 if (State == CommunicationState.Closed)
117 if (tcp_listener == null)
118 throw new InvalidOperationException ("Current state is " + State);
119 lock (accept_handles) {
120 foreach (var wait in accept_handles)
123 tcp_listener.Stop ();
127 protected override void OnOpen (TimeSpan timeout)
129 IPHostEntry entry = Dns.GetHostEntry (listen_uri.Host);
131 if (entry.AddressList.Length ==0)
132 throw new ArgumentException (String.Format ("Invalid listen URI: {0}", listen_uri));
134 int explicitPort = listen_uri.Port;
135 tcp_listener = new TcpListener (entry.AddressList [0], explicitPort <= 0 ? TcpTransportBindingElement.DefaultPort : explicitPort);
136 tcp_listener.Start ();