1 // 2 // Copyright (c) ZeroC, Inc. All rights reserved. 3 // 4 5 namespace IceInternal 6 { 7 using System.Collections.Generic; 8 using System.Diagnostics; 9 using System.Net; 10 using System.Threading; 11 12 public class EndpointHostResolver 13 { EndpointHostResolver(Instance instance)14 internal EndpointHostResolver(Instance instance) 15 { 16 _instance = instance; 17 _protocol = instance.protocolSupport(); 18 _preferIPv6 = instance.preferIPv6(); 19 _thread = new HelperThread(this); 20 updateObserver(); 21 _thread.Start(Util.stringToThreadPriority( 22 instance.initializationData().properties.getProperty("Ice.ThreadPriority"))); 23 } 24 resolve(string host, int port, Ice.EndpointSelectionType selType, IPEndpointI endpoint, EndpointI_connectors callback)25 public void resolve(string host, int port, Ice.EndpointSelectionType selType, IPEndpointI endpoint, 26 EndpointI_connectors callback) 27 { 28 // 29 // Try to get the addresses without DNS lookup. If this doesn't work, we queue a resolve 30 // entry and the thread will take care of getting the endpoint addresses. 31 // 32 NetworkProxy networkProxy = _instance.networkProxy(); 33 if(networkProxy == null) 34 { 35 try 36 { 37 List<EndPoint> addrs = Network.getAddresses(host, port, _protocol, selType, _preferIPv6, false); 38 if(addrs.Count > 0) 39 { 40 callback.connectors(endpoint.connectors(addrs, null)); 41 return; 42 } 43 } 44 catch(Ice.LocalException ex) 45 { 46 callback.exception(ex); 47 return; 48 } 49 } 50 51 lock(this) 52 { 53 Debug.Assert(!_destroyed); 54 55 ResolveEntry entry = new ResolveEntry(); 56 entry.host = host; 57 entry.port = port; 58 entry.selType = selType; 59 entry.endpoint = endpoint; 60 entry.callback = callback; 61 62 Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer; 63 if(obsv != null) 64 { 65 entry.observer = obsv.getEndpointLookupObserver(endpoint); 66 if(entry.observer != null) 67 { 68 entry.observer.attach(); 69 } 70 } 71 72 _queue.AddLast(entry); 73 Monitor.Pulse(this); 74 } 75 } 76 destroy()77 public void destroy() 78 { 79 lock(this) 80 { 81 Debug.Assert(!_destroyed); 82 _destroyed = true; 83 Monitor.Pulse(this); 84 } 85 } 86 joinWithThread()87 public void joinWithThread() 88 { 89 if(_thread != null) 90 { 91 _thread.Join(); 92 } 93 } 94 run()95 public void run() 96 { 97 while(true) 98 { 99 ResolveEntry r; 100 Ice.Instrumentation.ThreadObserver threadObserver; 101 102 lock(this) 103 { 104 while(!_destroyed && _queue.Count == 0) 105 { 106 Monitor.Wait(this); 107 } 108 109 if(_destroyed) 110 { 111 break; 112 } 113 114 r = _queue.First.Value; 115 _queue.RemoveFirst(); 116 threadObserver = _observer; 117 } 118 119 if(threadObserver != null) 120 { 121 threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateIdle, 122 Ice.Instrumentation.ThreadState.ThreadStateInUseForOther); 123 } 124 125 try 126 { 127 128 NetworkProxy networkProxy = _instance.networkProxy(); 129 int protocol = _protocol; 130 if(networkProxy != null) 131 { 132 networkProxy = networkProxy.resolveHost(protocol); 133 if(networkProxy != null) 134 { 135 protocol = networkProxy.getProtocolSupport(); 136 } 137 } 138 139 List<EndPoint> addrs = Network.getAddresses(r.host, r.port, protocol, r.selType, _preferIPv6, true); 140 if(r.observer != null) 141 { 142 r.observer.detach(); 143 r.observer = null; 144 } 145 146 r.callback.connectors(r.endpoint.connectors(addrs, networkProxy)); 147 } 148 catch(Ice.LocalException ex) 149 { 150 if(r.observer != null) 151 { 152 r.observer.failed(ex.ice_id()); 153 r.observer.detach(); 154 } 155 r.callback.exception(ex); 156 } 157 finally 158 { 159 if(threadObserver != null) 160 { 161 threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateInUseForOther, 162 Ice.Instrumentation.ThreadState.ThreadStateIdle); 163 } 164 } 165 } 166 167 foreach(ResolveEntry entry in _queue) 168 { 169 Ice.CommunicatorDestroyedException ex = new Ice.CommunicatorDestroyedException(); 170 if(entry.observer != null) 171 { 172 entry.observer.failed(ex.ice_id()); 173 entry.observer.detach(); 174 } 175 entry.callback.exception(ex); 176 } 177 _queue.Clear(); 178 179 if(_observer != null) 180 { 181 _observer.detach(); 182 } 183 } 184 185 public void updateObserver()186 updateObserver() 187 { 188 lock(this) 189 { 190 Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer; 191 if(obsv != null) 192 { 193 _observer = obsv.getThreadObserver("Communicator", 194 _thread.getName(), 195 Ice.Instrumentation.ThreadState.ThreadStateIdle, 196 _observer); 197 if(_observer != null) 198 { 199 _observer.attach(); 200 } 201 } 202 } 203 } 204 205 private class ResolveEntry 206 { 207 internal string host; 208 internal int port; 209 internal Ice.EndpointSelectionType selType; 210 internal IPEndpointI endpoint; 211 internal EndpointI_connectors callback; 212 internal Ice.Instrumentation.Observer observer; 213 } 214 215 private readonly Instance _instance; 216 private readonly int _protocol; 217 private readonly bool _preferIPv6; 218 private bool _destroyed; 219 private LinkedList<ResolveEntry> _queue = new LinkedList<ResolveEntry>(); 220 private Ice.Instrumentation.ThreadObserver _observer; 221 222 private sealed class HelperThread 223 { HelperThread(EndpointHostResolver resolver)224 internal HelperThread(EndpointHostResolver resolver) 225 { 226 _resolver = resolver; 227 _name = _resolver._instance.initializationData().properties.getProperty("Ice.ProgramName"); 228 if(_name.Length > 0) 229 { 230 _name += "-"; 231 } 232 _name += "Ice.HostResolver"; 233 } 234 Join()235 public void Join() 236 { 237 _thread.Join(); 238 } 239 Start(ThreadPriority priority)240 public void Start(ThreadPriority priority) 241 { 242 _thread = new Thread(new ThreadStart(Run)); 243 _thread.IsBackground = true; 244 _thread.Name = _name; 245 _thread.Priority = priority; 246 _thread.Start(); 247 } 248 Run()249 public void Run() 250 { 251 try 252 { 253 _resolver.run(); 254 } 255 catch(System.Exception ex) 256 { 257 string s = "exception in endpoint host resolver thread " + _name + ":\n" + ex; 258 _resolver._instance.initializationData().logger.error(s); 259 } 260 } 261 getName()262 public string getName() 263 { 264 return _name; 265 } 266 267 private EndpointHostResolver _resolver; 268 private string _name; 269 private Thread _thread; 270 } 271 272 private HelperThread _thread; 273 } 274 } 275