UDPServer.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Net;
  31. using System.Net.Sockets;
  32. using libsecondlife.Packets;
  33. using OpenSim.Framework;
  34. using OpenSim.Framework.Communications.Cache;
  35. using OpenSim.Framework.Console;
  36. namespace OpenSim.Region.ClientStack
  37. {
  38. public class UDPServer : ClientStackNetworkHandler
  39. {
  40. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  41. protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
  42. public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
  43. protected Dictionary<uint, EndPoint> proxyCircuits = new Dictionary<uint, EndPoint>();
  44. public Socket Server;
  45. protected IPEndPoint ServerIncoming;
  46. protected byte[] RecvBuffer = new byte[4096];
  47. protected byte[] ZeroBuffer = new byte[8192];
  48. protected IPEndPoint ipeSender;
  49. protected EndPoint epSender;
  50. protected EndPoint epProxy;
  51. protected int proxyPortOffset;
  52. protected AsyncCallback ReceivedData;
  53. protected PacketServer m_packetServer;
  54. protected ulong m_regionHandle;
  55. protected uint listenPort;
  56. protected bool Allow_Alternate_Port;
  57. protected IPAddress listenIP = IPAddress.Parse("0.0.0.0");
  58. protected IScene m_localScene;
  59. protected AssetCache m_assetCache;
  60. protected AgentCircuitManager m_authenticateSessionsClass;
  61. public PacketServer PacketServer
  62. {
  63. get { return m_packetServer; }
  64. set { m_packetServer = value; }
  65. }
  66. public IScene LocalScene
  67. {
  68. set
  69. {
  70. m_localScene = value;
  71. m_packetServer.LocalScene = m_localScene;
  72. m_regionHandle = m_localScene.RegionInfo.RegionHandle;
  73. }
  74. }
  75. public ulong RegionHandle
  76. {
  77. get { return m_regionHandle; }
  78. }
  79. public UDPServer()
  80. {
  81. }
  82. public UDPServer(IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass)
  83. {
  84. this.proxyPortOffset = proxyPortOffset;
  85. listenPort = (uint) (port + proxyPortOffset);
  86. listenIP = _listenIP;
  87. Allow_Alternate_Port = allow_alternate_port;
  88. m_assetCache = assetCache;
  89. m_authenticateSessionsClass = authenticateClass;
  90. CreatePacketServer();
  91. // Return new port
  92. // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered.
  93. // So the option allow_alternate_ports="true" was added to default.xml
  94. port = (uint)(listenPort - proxyPortOffset);
  95. }
  96. protected virtual void CreatePacketServer()
  97. {
  98. PacketServer packetServer = new PacketServer(this);
  99. }
  100. protected virtual void OnReceivedData(IAsyncResult result)
  101. {
  102. ipeSender = new IPEndPoint(listenIP, 0);
  103. epSender = (EndPoint) ipeSender;
  104. Packet packet = null;
  105. int numBytes = 1;
  106. try
  107. {
  108. numBytes = Server.EndReceiveFrom(result, ref epSender);
  109. }
  110. catch (SocketException e)
  111. {
  112. // TODO : Actually only handle those states that we have control over, re-throw everything else,
  113. // TODO: implement cases as we encounter them.
  114. //m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString());
  115. switch (e.SocketErrorCode)
  116. {
  117. case SocketError.AlreadyInProgress:
  118. case SocketError.NetworkReset:
  119. case SocketError.ConnectionReset:
  120. try
  121. {
  122. CloseEndPoint(epSender);
  123. }
  124. catch (Exception a)
  125. {
  126. m_log.Info("[UDPSERVER]: " + a.ToString());
  127. }
  128. try
  129. {
  130. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  131. ReceivedData, null);
  132. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  133. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  134. // This will happen over and over until we've gone through all packets
  135. // sent to and from this particular user.
  136. // Stupid I know..
  137. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  138. }
  139. catch (SocketException)
  140. {
  141. }
  142. break;
  143. default:
  144. try
  145. {
  146. CloseEndPoint(epSender);
  147. }
  148. catch (Exception)
  149. {
  150. //m_log.Info("[UDPSERVER]" + a.ToString());
  151. }
  152. try
  153. {
  154. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  155. ReceivedData, null);
  156. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  157. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  158. // This will happen over and over until we've gone through all packets
  159. // sent to and from this particular user.
  160. // Stupid I know..
  161. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  162. }
  163. catch (SocketException e2)
  164. {
  165. m_log.Error("[UDPSERVER]: " + e2.ToString());
  166. }
  167. // Here's some reference code! :D
  168. // Shutdown and restart the UDP listener! hehe
  169. // Shiny
  170. //Server.Shutdown(SocketShutdown.Both);
  171. //CloseEndPoint(epSender);
  172. //ServerListener();
  173. break;
  174. }
  175. //return;
  176. }
  177. catch (ObjectDisposedException e)
  178. {
  179. m_log.Debug("[UDPSERVER]: " + e.ToString());
  180. try
  181. {
  182. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  183. ReceivedData, null);
  184. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  185. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  186. // This will happen over and over until we've gone through all packets
  187. // sent to and from this particular user.
  188. // Stupid I know..
  189. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  190. }
  191. catch (SocketException e2)
  192. {
  193. m_log.Error("[UDPSERVER]: " + e2.ToString());
  194. }
  195. //return;
  196. }
  197. //System.Console.WriteLine("UDPServer : recieved message from {0}", epSender.ToString());
  198. epProxy = epSender;
  199. if (proxyPortOffset != 0)
  200. {
  201. epSender = PacketPool.DecodeProxyMessage(RecvBuffer, ref numBytes);
  202. }
  203. int packetEnd = numBytes - 1;
  204. try
  205. {
  206. packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
  207. }
  208. catch (Exception e)
  209. {
  210. m_log.Debug("[UDPSERVER]: " + e.ToString());
  211. }
  212. try
  213. {
  214. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
  215. }
  216. catch (SocketException)
  217. {
  218. try
  219. {
  220. CloseEndPoint(epSender);
  221. }
  222. catch (Exception a)
  223. {
  224. m_log.Info("[UDPSERVER]: " + a.ToString());
  225. }
  226. try
  227. {
  228. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  229. ReceivedData, null);
  230. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  231. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  232. // This will happen over and over until we've gone through all packets
  233. // sent to and from this particular user.
  234. // Stupid I know..
  235. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  236. }
  237. catch (SocketException e5)
  238. {
  239. m_log.Error("[UDPSERVER]: " + e5.ToString());
  240. }
  241. }
  242. if (packet != null)
  243. {
  244. try
  245. {
  246. // do we already have a circuit for this endpoint
  247. uint circuit;
  248. bool ret = false;
  249. lock (clientCircuits)
  250. {
  251. ret = clientCircuits.TryGetValue(epSender, out circuit);
  252. }
  253. if (ret)
  254. {
  255. //if so then send packet to the packetserver
  256. //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!");
  257. m_packetServer.InPacket(circuit, packet);
  258. }
  259. else if (packet.Type == PacketType.UseCircuitCode)
  260. {
  261. // new client
  262. m_log.Debug("[UDPSERVER]: Adding New Client");
  263. AddNewClient(packet);
  264. }
  265. else
  266. {
  267. // invalid client
  268. //CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now
  269. //m_log.Warn("[UDPSERVER]: Got a packet from an invalid client - " + packet.ToString());
  270. }
  271. }
  272. catch (Exception)
  273. {
  274. m_log.Error("[UDPSERVER]: Exception in processing packet.");
  275. m_log.Debug("[UDPSERVER]: Adding New Client");
  276. try
  277. {
  278. AddNewClient(packet);
  279. }
  280. catch (Exception e3)
  281. {
  282. m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString());
  283. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  284. ReceivedData, null);
  285. }
  286. }
  287. }
  288. }
  289. private void CloseEndPoint(EndPoint sender)
  290. {
  291. uint circuit;
  292. lock (clientCircuits)
  293. {
  294. if (clientCircuits.TryGetValue(sender, out circuit))
  295. {
  296. m_packetServer.CloseCircuit(circuit);
  297. }
  298. }
  299. }
  300. protected virtual void AddNewClient(Packet packet)
  301. {
  302. //Slave regions don't accept new clients
  303. if(m_localScene.Region_Status != RegionStatus.SlaveScene)
  304. {
  305. UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet;
  306. lock (clientCircuits)
  307. {
  308. if (!clientCircuits.ContainsKey(epSender))
  309. clientCircuits.Add(epSender, useCircuit.CircuitCode.Code);
  310. else
  311. m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  312. }
  313. lock (clientCircuits_reverse)
  314. {
  315. if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
  316. clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender);
  317. else
  318. m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  319. }
  320. lock (proxyCircuits)
  321. {
  322. if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
  323. proxyCircuits.Add(useCircuit.CircuitCode.Code, epProxy);
  324. else
  325. m_log.Error("[UDPSERVER]: proxyCircuits already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  326. }
  327. PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass, epProxy);
  328. }
  329. PacketPool.Instance.ReturnPacket(packet);
  330. }
  331. public void ServerListener()
  332. {
  333. uint newPort = listenPort;
  334. m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + ".");
  335. ServerIncoming = new IPEndPoint(listenIP, (int)newPort);
  336. Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  337. Server.Bind(ServerIncoming);
  338. listenPort = newPort;
  339. m_log.Info("[SERVER]: UDP socket bound, getting ready to listen");
  340. ipeSender = new IPEndPoint(listenIP, 0);
  341. epSender = (EndPoint)ipeSender;
  342. ReceivedData = new AsyncCallback(OnReceivedData);
  343. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
  344. m_log.Info("[SERVER]: Listening on port " + newPort);
  345. }
  346. public virtual void RegisterPacketServer(PacketServer server)
  347. {
  348. m_packetServer = server;
  349. }
  350. public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
  351. //EndPoint packetSender)
  352. {
  353. // find the endpoint for this circuit
  354. EndPoint sendto = null;
  355. lock (clientCircuits_reverse)
  356. {
  357. if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
  358. {
  359. //we found the endpoint so send the packet to it
  360. if (proxyPortOffset != 0)
  361. {
  362. //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString());
  363. PacketPool.EncodeProxyMessage(buffer, ref size, sendto);
  364. Server.SendTo(buffer, size, flags, proxyCircuits[circuitcode]);
  365. }
  366. else
  367. {
  368. //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString());
  369. Server.SendTo(buffer, size, flags, sendto);
  370. }
  371. }
  372. }
  373. }
  374. public virtual void RemoveClientCircuit(uint circuitcode)
  375. {
  376. EndPoint sendto = null;
  377. lock (clientCircuits_reverse)
  378. {
  379. if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
  380. {
  381. clientCircuits.Remove(sendto);
  382. clientCircuits_reverse.Remove(circuitcode);
  383. proxyCircuits.Remove(circuitcode);
  384. }
  385. }
  386. }
  387. public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP)
  388. {
  389. //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient");
  390. UseCircuitCodePacket useCircuit = new UseCircuitCodePacket();
  391. useCircuit.CircuitCode.Code = circuit.circuitcode;
  392. useCircuit.CircuitCode.ID = circuit.AgentID;
  393. useCircuit.CircuitCode.SessionID = circuit.SessionID;
  394. lock (clientCircuits)
  395. {
  396. if (!clientCircuits.ContainsKey(userEP))
  397. clientCircuits.Add(userEP, useCircuit.CircuitCode.Code);
  398. else
  399. m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  400. }
  401. lock (clientCircuits_reverse)
  402. {
  403. if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
  404. clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP);
  405. else
  406. m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  407. }
  408. lock (proxyCircuits)
  409. {
  410. if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
  411. {
  412. proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
  413. }
  414. else
  415. {
  416. // re-set proxy endpoint
  417. proxyCircuits.Remove(useCircuit.CircuitCode.Code);
  418. proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
  419. }
  420. }
  421. PacketServer.AddNewClient(userEP, useCircuit, m_assetCache, m_authenticateSessionsClass, proxyEP);
  422. }
  423. }
  424. }