UDPServer.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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. */
  28. using System;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. using System.Net;
  32. using System.Net.Sockets;
  33. using libsecondlife.Packets;
  34. using OpenSim.Framework;
  35. using OpenSim.Framework.Communications.Cache;
  36. using OpenSim.Framework.Console;
  37. namespace OpenSim.Region.ClientStack
  38. {
  39. public class UDPServer : ClientStackNetworkHandler
  40. {
  41. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  42. protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
  43. public Dictionary<uint, EndPoint> clientCircuits_reverse = 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 AsyncCallback ReceivedData;
  51. protected PacketServer m_packetServer;
  52. protected ulong m_regionHandle;
  53. protected uint listenPort;
  54. protected bool Allow_Alternate_Port;
  55. protected IPAddress listenIP = IPAddress.Parse("0.0.0.0");
  56. protected IScene m_localScene;
  57. protected AssetCache m_assetCache;
  58. protected AgentCircuitManager m_authenticateSessionsClass;
  59. public PacketServer PacketServer
  60. {
  61. get { return m_packetServer; }
  62. set { m_packetServer = value; }
  63. }
  64. public IScene LocalScene
  65. {
  66. set
  67. {
  68. m_localScene = value;
  69. m_packetServer.LocalScene = m_localScene;
  70. m_regionHandle = m_localScene.RegionInfo.RegionHandle;
  71. }
  72. }
  73. public ulong RegionHandle
  74. {
  75. get { return m_regionHandle; }
  76. }
  77. public UDPServer()
  78. {
  79. }
  80. public UDPServer(IPAddress _listenIP, ref uint port, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass)
  81. {
  82. listenIP = _listenIP;
  83. listenPort = port;
  84. Allow_Alternate_Port = allow_alternate_port;
  85. m_assetCache = assetCache;
  86. m_authenticateSessionsClass = authenticateClass;
  87. CreatePacketServer();
  88. // Return new port
  89. // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered.
  90. // So the option allow_alternate_ports="true" was added to default.xml
  91. port = listenPort;
  92. }
  93. protected virtual void CreatePacketServer()
  94. {
  95. PacketServer packetServer = new PacketServer(this);
  96. }
  97. protected virtual void OnReceivedData(IAsyncResult result)
  98. {
  99. ipeSender = new IPEndPoint(listenIP, 0);
  100. epSender = (EndPoint) ipeSender;
  101. Packet packet = null;
  102. int numBytes = 1;
  103. try
  104. {
  105. numBytes = Server.EndReceiveFrom(result, ref epSender);
  106. }
  107. catch (SocketException e)
  108. {
  109. // TODO : Actually only handle those states that we have control over, re-throw everything else,
  110. // TODO: implement cases as we encounter them.
  111. //m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString());
  112. switch (e.SocketErrorCode)
  113. {
  114. case SocketError.AlreadyInProgress:
  115. case SocketError.NetworkReset:
  116. case SocketError.ConnectionReset:
  117. try
  118. {
  119. CloseEndPoint(epSender);
  120. }
  121. catch (Exception a)
  122. {
  123. m_log.Info("[UDPSERVER]: " + a.ToString());
  124. }
  125. try
  126. {
  127. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  128. ReceivedData, null);
  129. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  130. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  131. // This will happen over and over until we've gone through all packets
  132. // sent to and from this particular user.
  133. // Stupid I know..
  134. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  135. }
  136. catch (SocketException)
  137. {
  138. }
  139. break;
  140. default:
  141. try
  142. {
  143. CloseEndPoint(epSender);
  144. }
  145. catch (Exception)
  146. {
  147. //m_log.Info("[UDPSERVER]" + a.ToString());
  148. }
  149. try
  150. {
  151. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  152. ReceivedData, null);
  153. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  154. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  155. // This will happen over and over until we've gone through all packets
  156. // sent to and from this particular user.
  157. // Stupid I know..
  158. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  159. }
  160. catch (SocketException e2)
  161. {
  162. m_log.Error("[UDPSERVER]: " + e2.ToString());
  163. }
  164. // Here's some reference code! :D
  165. // Shutdown and restart the UDP listener! hehe
  166. // Shiny
  167. //Server.Shutdown(SocketShutdown.Both);
  168. //CloseEndPoint(epSender);
  169. //ServerListener();
  170. break;
  171. }
  172. //return;
  173. }
  174. catch (ObjectDisposedException e)
  175. {
  176. m_log.Debug("[UDPSERVER]: " + e.ToString());
  177. try
  178. {
  179. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  180. ReceivedData, null);
  181. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  182. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  183. // This will happen over and over until we've gone through all packets
  184. // sent to and from this particular user.
  185. // Stupid I know..
  186. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  187. }
  188. catch (SocketException e2)
  189. {
  190. m_log.Error("[UDPSERVER]: " + e2.ToString());
  191. }
  192. //return;
  193. }
  194. int packetEnd = numBytes - 1;
  195. try
  196. {
  197. packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
  198. }
  199. catch (Exception e)
  200. {
  201. m_log.Debug("[UDPSERVER]: " + e.ToString());
  202. }
  203. try
  204. {
  205. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
  206. }
  207. catch (SocketException e4)
  208. {
  209. try
  210. {
  211. CloseEndPoint(epSender);
  212. }
  213. catch (Exception a)
  214. {
  215. m_log.Info("[UDPSERVER]: " + a.ToString());
  216. }
  217. try
  218. {
  219. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  220. ReceivedData, null);
  221. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  222. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  223. // This will happen over and over until we've gone through all packets
  224. // sent to and from this particular user.
  225. // Stupid I know..
  226. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  227. }
  228. catch (SocketException e5)
  229. {
  230. m_log.Error("[UDPSERVER]: " + e5.ToString());
  231. }
  232. }
  233. if (packet != null)
  234. {
  235. try
  236. {
  237. // do we already have a circuit for this endpoint
  238. uint circuit;
  239. bool ret = false;
  240. lock (clientCircuits)
  241. {
  242. ret = clientCircuits.TryGetValue(epSender, out circuit);
  243. }
  244. if (ret)
  245. {
  246. //if so then send packet to the packetserver
  247. //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!");
  248. m_packetServer.InPacket(circuit, packet);
  249. }
  250. else if (packet.Type == PacketType.UseCircuitCode)
  251. {
  252. // new client
  253. m_log.Debug("[UDPSERVER]: Adding New Client");
  254. AddNewClient(packet);
  255. }
  256. else
  257. {
  258. // invalid client
  259. //CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now
  260. //m_log.Warn("[UDPSERVER]: Got a packet from an invalid client - " + packet.ToString());
  261. }
  262. }
  263. catch (Exception ex)
  264. {
  265. m_log.Error("[UDPSERVER]: Exception in processing packet.");
  266. m_log.Debug("[UDPSERVER]: Adding New Client");
  267. try
  268. {
  269. AddNewClient(packet);
  270. }
  271. catch (Exception e3)
  272. {
  273. m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString());
  274. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  275. ReceivedData, null);
  276. }
  277. }
  278. }
  279. }
  280. private void CloseEndPoint(EndPoint sender)
  281. {
  282. uint circuit;
  283. if (clientCircuits.TryGetValue(sender, out circuit))
  284. {
  285. m_packetServer.CloseCircuit(circuit);
  286. }
  287. }
  288. protected virtual void AddNewClient(Packet packet)
  289. {
  290. UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet;
  291. lock (clientCircuits)
  292. {
  293. clientCircuits.Add(epSender, useCircuit.CircuitCode.Code);
  294. }
  295. lock (clientCircuits_reverse)
  296. {
  297. if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
  298. clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender);
  299. }
  300. PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass);
  301. }
  302. public void ServerListener()
  303. {
  304. uint newPort = listenPort;
  305. for (uint i = 0; i < 20; i++)
  306. {
  307. newPort = listenPort + i;
  308. m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + ".");// Allow alternate ports: " + Allow_Alternate_Port.ToString());
  309. try
  310. {
  311. ServerIncoming = new IPEndPoint(listenIP, (int) newPort);
  312. Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  313. Server.Bind(ServerIncoming);
  314. listenPort = newPort;
  315. break;
  316. }
  317. catch (Exception ex)
  318. {
  319. // We are not looking for alternate ports?
  320. //if (!Allow_Alternate_Port)
  321. throw (ex);
  322. // We are looking for alternate ports!
  323. m_log.Info("[SERVER]: UDP socket on " + listenIP.ToString() + " " + listenPort.ToString() + " is not available, trying next.");
  324. }
  325. System.Threading.Thread.Sleep(100); // Wait before we retry socket
  326. }
  327. m_log.Info("[SERVER]: UDP socket bound, getting ready to listen");
  328. ipeSender = new IPEndPoint(listenIP, 0);
  329. epSender = (EndPoint) ipeSender;
  330. ReceivedData = new AsyncCallback(OnReceivedData);
  331. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
  332. m_log.Info("[SERVER]: Listening on port " + newPort);
  333. }
  334. public virtual void RegisterPacketServer(PacketServer server)
  335. {
  336. m_packetServer = server;
  337. }
  338. public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
  339. //EndPoint packetSender)
  340. {
  341. // find the endpoint for this circuit
  342. EndPoint sendto = null;
  343. if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
  344. {
  345. //we found the endpoint so send the packet to it
  346. Server.SendTo(buffer, size, flags, sendto);
  347. }
  348. }
  349. public virtual void RemoveClientCircuit(uint circuitcode)
  350. {
  351. EndPoint sendto = null;
  352. if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
  353. {
  354. clientCircuits.Remove(sendto);
  355. clientCircuits_reverse.Remove(circuitcode);
  356. }
  357. }
  358. }
  359. }