2 // HttpChannelListener.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections.Generic;
30 using System.Collections.ObjectModel;
32 using System.Net.Security;
33 using System.ServiceModel;
34 using System.ServiceModel.Description;
35 using System.ServiceModel.Security;
38 namespace System.ServiceModel.Channels
40 internal class HttpSimpleChannelListener<TChannel> : HttpChannelListenerBase<TChannel>
41 where TChannel : class, IChannel
43 HttpListenerManager<TChannel> httpChannelManager;
45 public HttpSimpleChannelListener (HttpTransportBindingElement source,
46 BindingContext context)
47 : base (source, context)
51 public HttpListener Http {
52 get { return httpChannelManager.HttpListener; }
55 object creator_lock = new object ();
57 protected override TChannel CreateChannel (TimeSpan timeout)
60 return CreateChannelCore (timeout);
64 TChannel CreateChannelCore (TimeSpan timeout)
66 if (typeof (TChannel) == typeof (IReplyChannel))
67 return (TChannel) (object) new HttpSimpleReplyChannel ((HttpSimpleChannelListener<IReplyChannel>) (object) this);
68 // FIXME: session channel support
69 if (typeof (TChannel) == typeof (IReplySessionChannel))
70 throw new NotImplementedException ();
72 throw new NotSupportedException (String.Format ("Channel type {0} is not supported", typeof (TChannel)));
75 protected override void OnOpen (TimeSpan timeout)
77 base.OnOpen (timeout);
78 StartListening (timeout);
81 protected override void OnAbort ()
83 httpChannelManager.Stop (true);
86 protected override void OnClose (TimeSpan timeout)
88 if (State == CommunicationState.Closed)
90 base.OnClose (timeout);
91 // FIXME: it is said that channels are not closed
92 // when the channel listener is closed.
93 // http://blogs.msdn.com/drnick/archive/2006/03/22/557642.aspx
94 httpChannelManager.Stop (false);
97 void StartListening (TimeSpan timeout)
99 httpChannelManager = new HttpListenerManager<TChannel> (this);
100 httpChannelManager.Open (timeout);
104 internal class AspNetChannelListener<TChannel> : HttpChannelListenerBase<TChannel>
105 where TChannel : class, IChannel
107 public AspNetChannelListener (HttpTransportBindingElement source,
108 BindingContext context)
109 : base (source, context)
113 protected override TChannel CreateChannel (TimeSpan timeout)
115 if (typeof (TChannel) == typeof (IReplyChannel))
116 return (TChannel) (object) new AspNetReplyChannel ((AspNetChannelListener<IReplyChannel>) (object) this);
117 // FIXME: session channel support
118 if (typeof (TChannel) == typeof (IReplySessionChannel))
119 throw new NotImplementedException ();
121 throw new NotSupportedException (String.Format ("Channel type {0} is not supported", typeof (TChannel)));
125 internal abstract class HttpChannelListenerBase<TChannel> : InternalChannelListenerBase<TChannel>
126 where TChannel : class, IChannel
128 HttpTransportBindingElement source;
129 BindingContext context;
131 List<TChannel> channels = new List<TChannel> ();
132 MessageEncoder encoder;
134 public HttpChannelListenerBase (HttpTransportBindingElement source,
135 BindingContext context)
136 : base (context.Binding)
139 // FIXME: consider ListenUriMode
140 // FIXME: there should be some way to post-provide Uri in case of null listenerUri in context.
141 listen_uri = context.ListenUriBaseAddress != null ?
142 new Uri (context.ListenUriBaseAddress, context.ListenUriRelativeAddress) : null;
143 foreach (BindingElement be in context.RemainingBindingElements) {
144 MessageEncodingBindingElement mbe = be as MessageEncodingBindingElement;
146 encoder = CreateEncoder<TChannel> (mbe);
151 encoder = new TextMessageEncoder (MessageVersion.Default, Encoding.UTF8);
154 public MessageEncoder MessageEncoder {
155 get { return encoder; }
158 public override Uri Uri {
159 get { return listen_uri; }
162 protected IList<TChannel> Channels {
163 get { return channels; }
166 protected override TChannel OnAcceptChannel (TimeSpan timeout)
168 TChannel ch = CreateChannel (timeout);
173 protected abstract TChannel CreateChannel (TimeSpan timeout);
175 protected override bool OnWaitForChannel (TimeSpan timeout)
177 throw new NotImplementedException ();
180 protected override void OnAbort ()
182 OnClose (TimeSpan.Zero);
185 protected override void OnOpen (TimeSpan timeout)
189 protected override void OnClose (TimeSpan timeout)
191 DateTime start = DateTime.Now;
192 foreach (TChannel ch in Channels)
193 ch.Close (timeout - (DateTime.Now - start));
194 base.OnClose (timeout - (DateTime.Now - start));