1 // 2 // System.Net.EndPointManager 3 // 4 // Author: 5 // Gonzalo Paniagua Javier (gonzalo@ximian.com) 6 // 7 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com) 8 // 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: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 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. 27 // 28 29 using System.Collections; 30 using System.Collections.Generic; 31 namespace System.Net { 32 sealed class EndPointManager 33 { 34 // Dictionary<IPAddress, Dictionary<int, EndPointListener>> 35 static Hashtable ip_to_endpoints = new Hashtable (); 36 EndPointManager()37 private EndPointManager () 38 { 39 } 40 AddListener(HttpListener listener)41 public static void AddListener (HttpListener listener) 42 { 43 ArrayList added = new ArrayList (); 44 try { 45 lock (ip_to_endpoints) { 46 foreach (string prefix in listener.Prefixes) { 47 AddPrefixInternal (prefix, listener); 48 added.Add (prefix); 49 } 50 } 51 } catch { 52 foreach (string prefix in added) { 53 RemovePrefix (prefix, listener); 54 } 55 throw; 56 } 57 } 58 AddPrefix(string prefix, HttpListener listener)59 public static void AddPrefix (string prefix, HttpListener listener) 60 { 61 lock (ip_to_endpoints) { 62 AddPrefixInternal (prefix, listener); 63 } 64 } 65 AddPrefixInternal(string p, HttpListener listener)66 static void AddPrefixInternal (string p, HttpListener listener) 67 { 68 ListenerPrefix lp = new ListenerPrefix (p); 69 if (lp.Path.IndexOf ('%') != -1) 70 throw new HttpListenerException (400, "Invalid path."); 71 72 if (lp.Path.IndexOf ("//", StringComparison.Ordinal) != -1) // TODO: Code? 73 throw new HttpListenerException (400, "Invalid path."); 74 75 // listens on all the interfaces if host name cannot be parsed by IPAddress. 76 EndPointListener epl = GetEPListener (lp.Host, lp.Port, listener, lp.Secure); 77 epl.AddPrefix (lp, listener); 78 } 79 GetEPListener(string host, int port, HttpListener listener, bool secure)80 static EndPointListener GetEPListener (string host, int port, HttpListener listener, bool secure) 81 { 82 IPAddress addr; 83 if (host == "*") 84 addr = IPAddress.Any; 85 else if (IPAddress.TryParse(host, out addr) == false){ 86 try { 87 #pragma warning disable 618 88 IPHostEntry iphost = Dns.GetHostByName(host); 89 #pragma warning restore 618 90 if (iphost != null) 91 addr = iphost.AddressList[0]; 92 else 93 addr = IPAddress.Any; 94 } catch { 95 addr = IPAddress.Any; 96 } 97 } 98 Hashtable p = null; // Dictionary<int, EndPointListener> 99 if (ip_to_endpoints.ContainsKey (addr)) { 100 p = (Hashtable) ip_to_endpoints [addr]; 101 } else { 102 p = new Hashtable (); 103 ip_to_endpoints [addr] = p; 104 } 105 106 EndPointListener epl = null; 107 if (p.ContainsKey (port)) { 108 epl = (EndPointListener) p [port]; 109 } else { 110 epl = new EndPointListener (listener, addr, port, secure); 111 p [port] = epl; 112 } 113 114 return epl; 115 } 116 RemoveEndPoint(EndPointListener epl, IPEndPoint ep)117 public static void RemoveEndPoint (EndPointListener epl, IPEndPoint ep) 118 { 119 lock (ip_to_endpoints) { 120 // Dictionary<int, EndPointListener> p 121 Hashtable p = null; 122 p = (Hashtable) ip_to_endpoints [ep.Address]; 123 p.Remove (ep.Port); 124 if (p.Count == 0) { 125 ip_to_endpoints.Remove (ep.Address); 126 } 127 epl.Close (); 128 } 129 } 130 RemoveListener(HttpListener listener)131 public static void RemoveListener (HttpListener listener) 132 { 133 lock (ip_to_endpoints) { 134 foreach (string prefix in listener.Prefixes) { 135 RemovePrefixInternal (prefix, listener); 136 } 137 } 138 } 139 RemovePrefix(string prefix, HttpListener listener)140 public static void RemovePrefix (string prefix, HttpListener listener) 141 { 142 lock (ip_to_endpoints) { 143 RemovePrefixInternal (prefix, listener); 144 } 145 } 146 RemovePrefixInternal(string prefix, HttpListener listener)147 static void RemovePrefixInternal (string prefix, HttpListener listener) 148 { 149 ListenerPrefix lp = new ListenerPrefix (prefix); 150 if (lp.Path.IndexOf ('%') != -1) 151 return; 152 153 if (lp.Path.IndexOf ("//", StringComparison.Ordinal) != -1) 154 return; 155 156 EndPointListener epl = GetEPListener (lp.Host, lp.Port, listener, lp.Secure); 157 epl.RemovePrefix (lp, listener); 158 } 159 } 160 } 161 162