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