//
|
// EndPointManager.cs
|
// Copied from System.Net.EndPointManager.cs
|
//
|
// Author:
|
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
//
|
// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
|
// Copyright (c) 2012 sta.blockhead (sta.blockhead@gmail.com)
|
//
|
// Permission is hereby granted, free of charge, to any person obtaining
|
// a copy of this software and associated documentation files (the
|
// "Software"), to deal in the Software without restriction, including
|
// without limitation the rights to use, copy, modify, merge, publish,
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
// permit persons to whom the Software is furnished to do so, subject to
|
// the following conditions:
|
//
|
// The above copyright notice and this permission notice shall be
|
// included in all copies or substantial portions of the Software.
|
//
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
//
|
|
using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.Net;
|
|
namespace WebSocketSharp.Net {
|
|
sealed class EndPointManager {
|
|
#region Fields
|
|
static Dictionary<IPAddress, Dictionary<int, EndPointListener>> ip_to_endpoints = new Dictionary<IPAddress, Dictionary<int, EndPointListener>> ();
|
|
#endregion
|
|
#region Constructor
|
|
private EndPointManager ()
|
{
|
}
|
|
#endregion
|
|
#region Private Methods
|
|
static void AddPrefixInternal (string p, HttpListener listener)
|
{
|
ListenerPrefix lp = new ListenerPrefix (p);
|
if (lp.Path.IndexOf ('%') != -1)
|
throw new HttpListenerException (400, "Invalid path.");
|
|
if (lp.Path.IndexOf ("//", StringComparison.Ordinal) != -1) // TODO: Code?
|
throw new HttpListenerException (400, "Invalid path.");
|
|
// Always listens on all the interfaces, no matter the host name/ip used.
|
EndPointListener epl = GetEPListener (IPAddress.Any, lp.Port, listener, lp.Secure);
|
epl.AddPrefix (lp, listener);
|
}
|
|
static EndPointListener GetEPListener (IPAddress addr, int port, HttpListener listener, bool secure)
|
{
|
Dictionary<int, EndPointListener> p = null;
|
if (ip_to_endpoints.ContainsKey (addr)) {
|
p = ip_to_endpoints [addr];
|
} else {
|
p = new Dictionary<int, EndPointListener> ();
|
ip_to_endpoints [addr] = p;
|
}
|
|
EndPointListener epl = null;
|
if (p.ContainsKey (port)) {
|
epl = p [port];
|
} else {
|
epl = new EndPointListener (addr, port, secure);
|
p [port] = epl;
|
}
|
|
return epl;
|
}
|
|
static void RemovePrefixInternal (string prefix, HttpListener listener)
|
{
|
ListenerPrefix lp = new ListenerPrefix (prefix);
|
if (lp.Path.IndexOf ('%') != -1)
|
return;
|
|
if (lp.Path.IndexOf ("//", StringComparison.Ordinal) != -1)
|
return;
|
|
EndPointListener epl = GetEPListener (IPAddress.Any, lp.Port, listener, lp.Secure);
|
epl.RemovePrefix (lp, listener);
|
}
|
|
#endregion
|
|
#region Public Methods
|
|
public static void AddListener (HttpListener listener)
|
{
|
List<string> added = new List<string> ();
|
try {
|
lock (((ICollection)ip_to_endpoints).SyncRoot) {
|
foreach (string prefix in listener.Prefixes) {
|
AddPrefixInternal (prefix, listener);
|
added.Add (prefix);
|
}
|
}
|
} catch {
|
foreach (string prefix in added) {
|
RemovePrefix (prefix, listener);
|
}
|
throw;
|
}
|
}
|
|
public static void AddPrefix (string prefix, HttpListener listener)
|
{
|
lock (((ICollection)ip_to_endpoints).SyncRoot) {
|
AddPrefixInternal (prefix, listener);
|
}
|
}
|
|
public static void RemoveEndPoint (EndPointListener epl, IPEndPoint ep)
|
{
|
lock (((ICollection)ip_to_endpoints).SyncRoot) {
|
Dictionary<int, EndPointListener> p = null;
|
p = ip_to_endpoints [ep.Address];
|
p.Remove (ep.Port);
|
if (p.Count == 0) {
|
ip_to_endpoints.Remove (ep.Address);
|
}
|
epl.Close ();
|
}
|
}
|
|
public static void RemoveListener (HttpListener listener)
|
{
|
lock (((ICollection)ip_to_endpoints).SyncRoot) {
|
foreach (string prefix in listener.Prefixes) {
|
RemovePrefixInternal (prefix, listener);
|
}
|
}
|
}
|
|
public static void RemovePrefix (string prefix, HttpListener listener)
|
{
|
lock (((ICollection)ip_to_endpoints).SyncRoot) {
|
RemovePrefixInternal (prefix, listener);
|
}
|
}
|
|
#endregion
|
}
|
}
|