PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/llpacketring.cpp

https://bitbucket.org/lindenlab/viewer-development/
C++ | 372 lines | 261 code | 51 blank | 60 comment | 29 complexity | d7104c5355757fffdfc464539c2d67d2 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. /**
  2. * @file llpacketring.cpp
  3. * @brief implementation of LLPacketRing class for a packet.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llpacketring.h"
  28. #if LL_WINDOWS
  29. #include <winsock2.h>
  30. #else
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #endif
  34. // linden library includes
  35. #include "llerror.h"
  36. #include "lltimer.h"
  37. #include "llproxy.h"
  38. #include "llrand.h"
  39. #include "message.h"
  40. #include "timing.h"
  41. #include "u64.h"
  42. ///////////////////////////////////////////////////////////
  43. LLPacketRing::LLPacketRing () :
  44. mUseInThrottle(FALSE),
  45. mUseOutThrottle(FALSE),
  46. mInThrottle(256000.f),
  47. mOutThrottle(64000.f),
  48. mActualBitsIn(0),
  49. mActualBitsOut(0),
  50. mMaxBufferLength(64000),
  51. mInBufferLength(0),
  52. mOutBufferLength(0),
  53. mDropPercentage(0.0f),
  54. mPacketsToDrop(0x0)
  55. {
  56. }
  57. ///////////////////////////////////////////////////////////
  58. LLPacketRing::~LLPacketRing ()
  59. {
  60. cleanup();
  61. }
  62. ///////////////////////////////////////////////////////////
  63. void LLPacketRing::cleanup ()
  64. {
  65. LLPacketBuffer *packetp;
  66. while (!mReceiveQueue.empty())
  67. {
  68. packetp = mReceiveQueue.front();
  69. delete packetp;
  70. mReceiveQueue.pop();
  71. }
  72. while (!mSendQueue.empty())
  73. {
  74. packetp = mSendQueue.front();
  75. delete packetp;
  76. mSendQueue.pop();
  77. }
  78. }
  79. ///////////////////////////////////////////////////////////
  80. void LLPacketRing::dropPackets (U32 num_to_drop)
  81. {
  82. mPacketsToDrop += num_to_drop;
  83. }
  84. ///////////////////////////////////////////////////////////
  85. void LLPacketRing::setDropPercentage (F32 percent_to_drop)
  86. {
  87. mDropPercentage = percent_to_drop;
  88. }
  89. void LLPacketRing::setUseInThrottle(const BOOL use_throttle)
  90. {
  91. mUseInThrottle = use_throttle;
  92. }
  93. void LLPacketRing::setUseOutThrottle(const BOOL use_throttle)
  94. {
  95. mUseOutThrottle = use_throttle;
  96. }
  97. void LLPacketRing::setInBandwidth(const F32 bps)
  98. {
  99. mInThrottle.setRate(bps);
  100. }
  101. void LLPacketRing::setOutBandwidth(const F32 bps)
  102. {
  103. mOutThrottle.setRate(bps);
  104. }
  105. ///////////////////////////////////////////////////////////
  106. S32 LLPacketRing::receiveFromRing (S32 socket, char *datap)
  107. {
  108. if (mInThrottle.checkOverflow(0))
  109. {
  110. // We don't have enough bandwidth, don't give them a packet.
  111. return 0;
  112. }
  113. LLPacketBuffer *packetp = NULL;
  114. if (mReceiveQueue.empty())
  115. {
  116. // No packets on the queue, don't give them any.
  117. return 0;
  118. }
  119. S32 packet_size = 0;
  120. packetp = mReceiveQueue.front();
  121. mReceiveQueue.pop();
  122. packet_size = packetp->getSize();
  123. if (packetp->getData() != NULL)
  124. {
  125. memcpy(datap, packetp->getData(), packet_size); /*Flawfinder: ignore*/
  126. }
  127. // need to set sender IP/port!!
  128. mLastSender = packetp->getHost();
  129. mLastReceivingIF = packetp->getReceivingInterface();
  130. delete packetp;
  131. this->mInBufferLength -= packet_size;
  132. // Adjust the throttle
  133. mInThrottle.throttleOverflow(packet_size * 8.f);
  134. return packet_size;
  135. }
  136. ///////////////////////////////////////////////////////////
  137. S32 LLPacketRing::receivePacket (S32 socket, char *datap)
  138. {
  139. S32 packet_size = 0;
  140. // If using the throttle, simulate a limited size input buffer.
  141. if (mUseInThrottle)
  142. {
  143. BOOL done = FALSE;
  144. // push any current net packet (if any) onto delay ring
  145. while (!done)
  146. {
  147. LLPacketBuffer *packetp;
  148. packetp = new LLPacketBuffer(socket);
  149. if (packetp->getSize())
  150. {
  151. mActualBitsIn += packetp->getSize() * 8;
  152. // Fake packet loss
  153. if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
  154. {
  155. mPacketsToDrop++;
  156. }
  157. if (mPacketsToDrop)
  158. {
  159. delete packetp;
  160. packetp = NULL;
  161. packet_size = 0;
  162. mPacketsToDrop--;
  163. }
  164. }
  165. // If we faked packet loss, then we don't have a packet
  166. // to use for buffer overflow testing
  167. if (packetp)
  168. {
  169. if (mInBufferLength + packetp->getSize() > mMaxBufferLength)
  170. {
  171. // Toss it.
  172. llwarns << "Throwing away packet, overflowing buffer" << llendl;
  173. delete packetp;
  174. packetp = NULL;
  175. }
  176. else if (packetp->getSize())
  177. {
  178. mReceiveQueue.push(packetp);
  179. mInBufferLength += packetp->getSize();
  180. }
  181. else
  182. {
  183. delete packetp;
  184. packetp = NULL;
  185. done = true;
  186. }
  187. }
  188. else
  189. {
  190. // No packetp, keep going? - no packetp == faked packet loss
  191. }
  192. }
  193. // Now, grab data off of the receive queue according to our
  194. // throttled bandwidth settings.
  195. packet_size = receiveFromRing(socket, datap);
  196. }
  197. else
  198. {
  199. // no delay, pull straight from net
  200. if (LLProxy::isSOCKSProxyEnabled())
  201. {
  202. U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
  203. packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer)));
  204. if (packet_size > SOCKS_HEADER_SIZE)
  205. {
  206. // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
  207. memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE);
  208. proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
  209. mLastSender.setAddress(header->addr);
  210. mLastSender.setPort(ntohs(header->port));
  211. packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
  212. }
  213. else
  214. {
  215. packet_size = 0;
  216. }
  217. }
  218. else
  219. {
  220. packet_size = receive_packet(socket, datap);
  221. mLastSender = ::get_sender();
  222. }
  223. mLastReceivingIF = ::get_receiving_interface();
  224. if (packet_size) // did we actually get a packet?
  225. {
  226. if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
  227. {
  228. mPacketsToDrop++;
  229. }
  230. if (mPacketsToDrop)
  231. {
  232. packet_size = 0;
  233. mPacketsToDrop--;
  234. }
  235. }
  236. }
  237. return packet_size;
  238. }
  239. BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
  240. {
  241. BOOL status = TRUE;
  242. if (!mUseOutThrottle)
  243. {
  244. return sendPacketImpl(h_socket, send_buffer, buf_size, host );
  245. }
  246. else
  247. {
  248. mActualBitsOut += buf_size * 8;
  249. LLPacketBuffer *packetp = NULL;
  250. // See if we've got enough throttle to send a packet.
  251. while (!mOutThrottle.checkOverflow(0.f))
  252. {
  253. // While we have enough bandwidth, send a packet from the queue or the current packet
  254. S32 packet_size = 0;
  255. if (!mSendQueue.empty())
  256. {
  257. // Send a packet off of the queue
  258. LLPacketBuffer *packetp = mSendQueue.front();
  259. mSendQueue.pop();
  260. mOutBufferLength -= packetp->getSize();
  261. packet_size = packetp->getSize();
  262. status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost());
  263. delete packetp;
  264. // Update the throttle
  265. mOutThrottle.throttleOverflow(packet_size * 8.f);
  266. }
  267. else
  268. {
  269. // If the queue's empty, we can just send this packet right away.
  270. status = sendPacketImpl(h_socket, send_buffer, buf_size, host );
  271. packet_size = buf_size;
  272. // Update the throttle
  273. mOutThrottle.throttleOverflow(packet_size * 8.f);
  274. // This was the packet we're sending now, there are no other packets
  275. // that we need to send
  276. return status;
  277. }
  278. }
  279. // We haven't sent the incoming packet, add it to the queue
  280. if (mOutBufferLength + buf_size > mMaxBufferLength)
  281. {
  282. // Nuke this packet, we overflowed the buffer.
  283. // Toss it.
  284. llwarns << "Throwing away outbound packet, overflowing buffer" << llendl;
  285. }
  286. else
  287. {
  288. static LLTimer queue_timer;
  289. if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
  290. {
  291. // Add it to the queue
  292. llinfos << "Outbound packet queue " << mOutBufferLength << " bytes" << llendl;
  293. queue_timer.reset();
  294. }
  295. packetp = new LLPacketBuffer(host, send_buffer, buf_size);
  296. mOutBufferLength += packetp->getSize();
  297. mSendQueue.push(packetp);
  298. }
  299. }
  300. return status;
  301. }
  302. BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host)
  303. {
  304. if (!LLProxy::isSOCKSProxyEnabled())
  305. {
  306. return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
  307. }
  308. char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
  309. proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer));
  310. socks_header->rsv = 0;
  311. socks_header->addr = host.getAddress();
  312. socks_header->port = htons(host.getPort());
  313. socks_header->atype = ADDRESS_IPV4;
  314. socks_header->frag = 0;
  315. memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);
  316. return send_packet( h_socket,
  317. headered_send_buffer,
  318. buf_size + SOCKS_HEADER_SIZE,
  319. LLProxy::getInstance()->getUDPProxy().getAddress(),
  320. LLProxy::getInstance()->getUDPProxy().getPort());
  321. }