X509Certificate2 cert;
AsymmetricAlgorithm key;
bool secure;
+ Hashtable unregistered;
public EndPointListener (IPAddress addr, int port, bool secure)
{
sock.AcceptAsync (args);
prefixes = new Hashtable ();
plock = new ReaderWriterLock ();
+ unregistered = Hashtable.Synchronized (new Hashtable ());
}
void LoadCertificateAndKey (IPAddress addr, int port)
return;
}
HttpConnection conn = new HttpConnection (accepted, epl, epl.secure, epl.cert, epl.key);
+ epl.unregistered [conn] = conn;
conn.BeginReadRequest ();
}
+ internal void RemoveConnection (HttpConnection conn)
+ {
+ unregistered.Remove (conn);
+ }
+
public bool BindContext (HttpListenerContext context)
{
HttpListenerRequest req = context.Request;
public void Close ()
{
sock.Close ();
+ lock (unregistered) {
+ foreach (HttpConnection c in unregistered.Keys)
+ c.Close (true);
+ unregistered.Clear ();
+ }
}
public void AddPrefix (ListenerPrefix prefix, HttpListener listener)
int s_timeout = 90000; // 90k ms for first request, 15k ms from then on
Timer timer;
IPEndPoint local_ep;
+ HttpListener last_listener;
public HttpConnection (Socket sock, EndPointListener epl, bool secure, X509Certificate2 cert, AsymmetricAlgorithm key)
{
context = new HttpListenerContext (this);
}
+ public bool IsClosed {
+ get { return (sock == null); }
+ }
+
public int Reuses {
get { return reuses; }
}
void OnTimeout (object unused)
{
+ CloseSocket ();
Unbind ();
- try {
- sock.Close (); // stream disposed
- } catch {
- }
}
public void BeginReadRequest ()
timer.Change (s_timeout, Timeout.Infinite);
stream.BeginRead (buffer, 0, BufferSize, OnRead, this);
} catch {
+ timer.Change (Timeout.Infinite, Timeout.Infinite);
CloseSocket ();
}
}
SendError ("Invalid host", 400);
Close (true);
}
- context_bound = true;
+ if (last_listener == null)
+ epl.RemoveConnection (this);
+ else
+ last_listener.RemoveConnection (this);
+
+ if (context.Listener != null) {
+ context.Listener.AddConnection (this);
+ context_bound = true;
+ }
+ last_listener = context.Listener;
return;
}
stream.BeginRead (buffer, 0, BufferSize, OnRead, cnc);
} finally {
sock = null;
}
+ if (last_listener == null)
+ epl.RemoveConnection (this);
}
internal void Close (bool force_close)
s.Close ();
}
Unbind ();
+ if (last_listener == null)
+ epl.RemoveConnection (this);
return;
}
}
Hashtable registry; // Dictionary<HttpListenerContext,HttpListenerContext>
ArrayList ctx_queue; // List<HttpListenerContext> ctx_queue;
ArrayList wait_queue; // List<ListenerAsyncResult> wait_queue;
+ Hashtable connections;
public HttpListener ()
{
prefixes = new HttpListenerPrefixCollection (this);
registry = new Hashtable ();
+ connections = Hashtable.Synchronized (new Hashtable ());
ctx_queue = new ArrayList ();
wait_queue = new ArrayList ();
auth_schemes = AuthenticationSchemes.Anonymous;
return;
}
- Close (false);
+ Close (true);
disposed = true;
}
foreach (HttpListenerContext context in registry.Keys) {
context.Connection.Close ();
}
- registry.Clear (); // Just in case.
+ registry.Clear ();
}
+ lock (connections) {
+ foreach (HttpConnection cnc in connections.Keys) {
+ cnc.Close (true);
+ }
+ connections.Clear ();
+ }
lock (ctx_queue) {
foreach (HttpListenerContext context in ctx_queue)
- context.Connection.Close ();
+ context.Connection.Close (true);
ctx_queue.Clear ();
}
ctx_queue.RemoveAt (idx);
}
}
+
+ internal void AddConnection (HttpConnection cnc)
+ {
+ connections [cnc] = cnc;
+ }
+
+ internal void RemoveConnection (HttpConnection cnc)
+ {
+ connections.Remove (cnc);
+ }
}
}
#endif