Entries = new List<HttpChannelListenerEntry> ();
}
- public List<HttpChannelListenerEntry> Entries { get; private set; }
+ protected List<HttpChannelListenerEntry> Entries { get; private set; }
+ object entries_lock = new object ();
- public abstract void RegisterListener (ChannelDispatcher channel, TimeSpan timeout);
+ public abstract void RegisterListener (ChannelDispatcher channel, HttpTransportBindingElement element, TimeSpan timeout);
public abstract void UnregisterListener (ChannelDispatcher channel, TimeSpan timeout);
protected void RegisterListenerCommon (ChannelDispatcher channel, TimeSpan timeout)
{
- Entries.Add (new HttpChannelListenerEntry (channel, new AutoResetEvent (false)));
+ lock (entries_lock) {
+ Entries.Add (new HttpChannelListenerEntry (channel, new AutoResetEvent (false)));
- Entries.Sort (HttpChannelListenerEntry.CompareEntries);
+ Entries.Sort (HttpChannelListenerEntry.CompareEntries);
+ }
}
protected void UnregisterListenerCommon (ChannelDispatcher channel, TimeSpan timeout)
{
- var entry = Entries.First (e => e.ChannelDispatcher == channel);
- Entries.Remove (entry);
+ lock (entries_lock) {
+ var entry = Entries.First (e => e.ChannelDispatcher == channel);
+ Entries.Remove (entry);
- entry.WaitHandle.Set (); // make sure to finish pending requests.
+ entry.WaitHandle.Set (); // make sure to finish pending requests.
+ }
}
public void ProcessNewContext (HttpContextInfo ctxi)
HttpChannelListenerEntry SelectChannel (HttpContextInfo ctx)
{
- foreach (var e in Entries)
- if (e.FilterHttpContext (ctx))
- return e;
+ lock (entries_lock) {
+ foreach (var e in Entries)
+ if (e.FilterHttpContext (ctx))
+ return e;
+ }
return null;
}
DateTime start = DateTime.Now;
context = null;
- var ce = Entries.First (e => e.ChannelDispatcher == channel);
+ HttpChannelListenerEntry ce = null;
+ lock (entries_lock) {
+ ce = Entries.FirstOrDefault (e => e.ChannelDispatcher == channel);
+ }
+ if (ce == null)
+ return false;
lock (ce.RetrieverLock) {
var q = ce.ContextQueue;
if (q.Count == 0) {
- bool ret = ce.WaitHandle.WaitOne (timeout);
- return ret && TryDequeueRequest (channel, timeout - (DateTime.Now - start), out context); // recurse, am lazy :/
+ if (timeout.TotalMilliseconds < 0) return false;
+ TimeSpan waitTimeout = timeout;
+ if (timeout == TimeSpan.MaxValue)
+ waitTimeout = TimeSpan.FromMilliseconds (int.MaxValue);
+ bool ret = ce.WaitHandle.WaitOne (waitTimeout);
+ return ret && TryDequeueRequest (channel, waitTimeout - (DateTime.Now - start), out context); // recurse, am lazy :/
}
context = q.Dequeue ();
return true;
internal class HttpStandaloneListenerManager : HttpListenerManager
{
- public HttpStandaloneListenerManager (Uri uri)
+ public HttpStandaloneListenerManager (Uri uri, HttpTransportBindingElement element)
{
var l = new HttpListener ();
- string uriString = uri.ToString ();
+ string uriString = element.HostNameComparisonMode == HostNameComparisonMode.Exact ? uri.ToString () : uri.Scheme + "://*" + uri.GetComponents (UriComponents.Port | UriComponents.Path, UriFormat.SafeUnescaped);
if (!uriString.EndsWith ("/", StringComparison.Ordinal))
uriString += "/"; // HttpListener requires this mess.
Thread loop;
// FIXME: use timeout
- public override void RegisterListener (ChannelDispatcher channel, TimeSpan timeout)
+ public override void RegisterListener (ChannelDispatcher channel, HttpTransportBindingElement element, TimeSpan timeout)
{
RegisterListenerCommon (channel, timeout);
if (Entries.Count != 1)
return;
+ if (element != null) {
+ var l = listener;
+ l.AuthenticationSchemeSelectorDelegate = delegate (HttpListenerRequest req) {
+ return element.AuthenticationScheme;
+ };
+ l.Realm = element.Realm;
+ l.UnsafeConnectionNtlmAuthentication = element.UnsafeConnectionNtlmAuthentication;
+ }
+
// Start here. It is shared between channel listeners
// that share the same listen Uri. So there is no other appropriate place.
-#if true
+#if USE_SEPARATE_LOOP // this cannot be enabled because it causes infinite loop when ChannelDispatcher is not involved.
loop = new Thread (new ThreadStart (delegate {
listener.Start ();
try {
}));
loop.Start ();
#else
+ listener.Start ();
listener.BeginGetContext (GetContextCompleted, null);
#endif
}
if (Entries.Count > 0)
return;
-#if true
+#if USE_SEPARATE_LOOP
loop.Abort ();
#else
this.listener.Stop ();
{
}
- public override void RegisterListener (ChannelDispatcher channel, TimeSpan timeout)
+ public override void RegisterListener (ChannelDispatcher channel, HttpTransportBindingElement element, TimeSpan timeout)
{
RegisterListenerCommon (channel, timeout);
}