// 
 | 
// 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 
 | 
    } 
 | 
} 
 |