UDPServer.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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.Generic;
  29. using System.Net;
  30. using System.Net.Sockets;
  31. using System.Reflection;
  32. using libsecondlife.Packets;
  33. using log4net;
  34. using OpenSim.Framework;
  35. using OpenSim.Framework.Communications.Cache;
  36. namespace OpenSim.Region.ClientStack
  37. {
  38. public class UDPServer : ClientStackNetworkHandler
  39. {
  40. private static readonly ILog m_log = LogManager.GetLogger(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. catch (ObjectDisposedException)
  196. {
  197. }
  198. //return;
  199. }
  200. //System.Console.WriteLine("UDPServer : recieved message from {0}", epSender.ToString());
  201. epProxy = epSender;
  202. if (proxyPortOffset != 0)
  203. {
  204. epSender = PacketPool.DecodeProxyMessage(RecvBuffer, ref numBytes);
  205. }
  206. int packetEnd = numBytes - 1;
  207. try
  208. {
  209. packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
  210. }
  211. catch (Exception e)
  212. {
  213. m_log.Debug("[UDPSERVER]: " + e.ToString());
  214. }
  215. try
  216. {
  217. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
  218. }
  219. catch (SocketException)
  220. {
  221. try
  222. {
  223. CloseEndPoint(epSender);
  224. }
  225. catch (Exception a)
  226. {
  227. m_log.Info("[UDPSERVER]: " + a.ToString());
  228. }
  229. try
  230. {
  231. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  232. ReceivedData, null);
  233. // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
  234. // so therefore.. we've got to tell the server to BeginReceiveFrom again.
  235. // This will happen over and over until we've gone through all packets
  236. // sent to and from this particular user.
  237. // Stupid I know..
  238. // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
  239. }
  240. catch (SocketException e5)
  241. {
  242. m_log.Error("[UDPSERVER]: " + e5.ToString());
  243. }
  244. }
  245. catch (ObjectDisposedException)
  246. {
  247. }
  248. if (packet != null)
  249. {
  250. try
  251. {
  252. // do we already have a circuit for this endpoint
  253. uint circuit;
  254. bool ret = false;
  255. lock (clientCircuits)
  256. {
  257. ret = clientCircuits.TryGetValue(epSender, out circuit);
  258. }
  259. if (ret)
  260. {
  261. //if so then send packet to the packetserver
  262. //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!");
  263. m_packetServer.InPacket(circuit, packet);
  264. }
  265. else if (packet.Type == PacketType.UseCircuitCode)
  266. {
  267. // new client
  268. m_log.Debug("[UDPSERVER]: Adding New Client");
  269. AddNewClient(packet);
  270. UseCircuitCodePacket p = (UseCircuitCodePacket)packet;
  271. // Ack the first UseCircuitCode packet
  272. PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
  273. // TODO: don't create new blocks if recycling an old packet
  274. ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
  275. ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
  276. ack_it.Packets[0].ID = packet.Header.Sequence;
  277. ack_it.Header.Reliable = false;
  278. SendPacketTo(ack_it.ToBytes(),ack_it.ToBytes().Length,SocketFlags.None,p.CircuitCode.Code);
  279. }
  280. else
  281. {
  282. // invalid client
  283. //CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now
  284. //m_log.Warn("[UDPSERVER]: Got a packet from an invalid client - " + packet.ToString());
  285. }
  286. }
  287. catch (Exception)
  288. {
  289. m_log.Error("[UDPSERVER]: Exception in processing packet.");
  290. m_log.Debug("[UDPSERVER]: Adding New Client");
  291. try
  292. {
  293. AddNewClient(packet);
  294. }
  295. catch (Exception e3)
  296. {
  297. m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString());
  298. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
  299. ReceivedData, null);
  300. }
  301. }
  302. }
  303. }
  304. private void CloseEndPoint(EndPoint sender)
  305. {
  306. uint circuit;
  307. lock (clientCircuits)
  308. {
  309. if (clientCircuits.TryGetValue(sender, out circuit))
  310. {
  311. m_packetServer.CloseCircuit(circuit);
  312. }
  313. }
  314. }
  315. protected virtual void AddNewClient(Packet packet)
  316. {
  317. //Slave regions don't accept new clients
  318. if(m_localScene.Region_Status != RegionStatus.SlaveScene)
  319. {
  320. UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet;
  321. lock (clientCircuits)
  322. {
  323. if (!clientCircuits.ContainsKey(epSender))
  324. clientCircuits.Add(epSender, useCircuit.CircuitCode.Code);
  325. else
  326. m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  327. }
  328. lock (clientCircuits_reverse)
  329. {
  330. if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
  331. clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender);
  332. else
  333. m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  334. }
  335. lock (proxyCircuits)
  336. {
  337. if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
  338. proxyCircuits.Add(useCircuit.CircuitCode.Code, epProxy);
  339. else
  340. m_log.Error("[UDPSERVER]: proxyCircuits already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  341. }
  342. PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass, epProxy);
  343. }
  344. PacketPool.Instance.ReturnPacket(packet);
  345. }
  346. public void ServerListener()
  347. {
  348. uint newPort = listenPort;
  349. m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + ".");
  350. ServerIncoming = new IPEndPoint(listenIP, (int)newPort);
  351. Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  352. Server.Bind(ServerIncoming);
  353. listenPort = newPort;
  354. m_log.Info("[SERVER]: UDP socket bound, getting ready to listen");
  355. ipeSender = new IPEndPoint(listenIP, 0);
  356. epSender = (EndPoint)ipeSender;
  357. ReceivedData = new AsyncCallback(OnReceivedData);
  358. Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
  359. m_log.Info("[SERVER]: Listening on port " + newPort);
  360. }
  361. public virtual void RegisterPacketServer(PacketServer server)
  362. {
  363. m_packetServer = server;
  364. }
  365. public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
  366. //EndPoint packetSender)
  367. {
  368. // find the endpoint for this circuit
  369. EndPoint sendto = null;
  370. lock (clientCircuits_reverse)
  371. {
  372. if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
  373. {
  374. //we found the endpoint so send the packet to it
  375. if (proxyPortOffset != 0)
  376. {
  377. //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString());
  378. PacketPool.EncodeProxyMessage(buffer, ref size, sendto);
  379. Server.SendTo(buffer, size, flags, proxyCircuits[circuitcode]);
  380. }
  381. else
  382. {
  383. //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString());
  384. Server.SendTo(buffer, size, flags, sendto);
  385. }
  386. }
  387. }
  388. }
  389. public virtual void RemoveClientCircuit(uint circuitcode)
  390. {
  391. EndPoint sendto = null;
  392. lock (clientCircuits_reverse)
  393. {
  394. if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
  395. {
  396. clientCircuits.Remove(sendto);
  397. clientCircuits_reverse.Remove(circuitcode);
  398. proxyCircuits.Remove(circuitcode);
  399. }
  400. }
  401. }
  402. public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP)
  403. {
  404. //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient");
  405. UseCircuitCodePacket useCircuit = new UseCircuitCodePacket();
  406. useCircuit.CircuitCode.Code = circuit.circuitcode;
  407. useCircuit.CircuitCode.ID = circuit.AgentID;
  408. useCircuit.CircuitCode.SessionID = circuit.SessionID;
  409. lock (clientCircuits)
  410. {
  411. if (!clientCircuits.ContainsKey(userEP))
  412. clientCircuits.Add(userEP, useCircuit.CircuitCode.Code);
  413. else
  414. m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  415. }
  416. lock (clientCircuits_reverse)
  417. {
  418. if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
  419. clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP);
  420. else
  421. m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
  422. }
  423. lock (proxyCircuits)
  424. {
  425. if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
  426. {
  427. proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
  428. }
  429. else
  430. {
  431. // re-set proxy endpoint
  432. proxyCircuits.Remove(useCircuit.CircuitCode.Code);
  433. proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
  434. }
  435. }
  436. PacketServer.AddNewClient(userEP, useCircuit, m_assetCache, m_authenticateSessionsClass, proxyEP);
  437. }
  438. }
  439. }