llpacketring.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:8k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llpacketring.cpp
  3.  * @brief implementation of LLPacketRing class for a packet.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llpacketring.h"
  34. // linden library includes
  35. #include "llerror.h"
  36. #include "lltimer.h"
  37. #include "timing.h"
  38. #include "llrand.h"
  39. #include "u64.h"
  40. ///////////////////////////////////////////////////////////
  41. LLPacketRing::LLPacketRing () :
  42. mUseInThrottle(FALSE),
  43. mUseOutThrottle(FALSE),
  44. mInThrottle(256000.f),
  45. mOutThrottle(64000.f),
  46. mActualBitsIn(0),
  47. mActualBitsOut(0),
  48. mMaxBufferLength(64000),
  49. mInBufferLength(0),
  50. mOutBufferLength(0),
  51. mDropPercentage(0.0f),
  52. mPacketsToDrop(0x0)
  53. {
  54. }
  55. ///////////////////////////////////////////////////////////
  56. LLPacketRing::~LLPacketRing ()
  57. {
  58. cleanup();
  59. }
  60. ///////////////////////////////////////////////////////////
  61. void LLPacketRing::cleanup ()
  62. {
  63. LLPacketBuffer *packetp;
  64. while (!mReceiveQueue.empty())
  65. {
  66. packetp = mReceiveQueue.front();
  67. delete packetp;
  68. mReceiveQueue.pop();
  69. }
  70. while (!mSendQueue.empty())
  71. {
  72. packetp = mSendQueue.front();
  73. delete packetp;
  74. mSendQueue.pop();
  75. }
  76. }
  77. ///////////////////////////////////////////////////////////
  78. void LLPacketRing::dropPackets (U32 num_to_drop)
  79. {
  80. mPacketsToDrop += num_to_drop;
  81. }
  82. ///////////////////////////////////////////////////////////
  83. void LLPacketRing::setDropPercentage (F32 percent_to_drop)
  84. {
  85. mDropPercentage = percent_to_drop;
  86. }
  87. void LLPacketRing::setUseInThrottle(const BOOL use_throttle)
  88. {
  89. mUseInThrottle = use_throttle;
  90. }
  91. void LLPacketRing::setUseOutThrottle(const BOOL use_throttle)
  92. {
  93. mUseOutThrottle = use_throttle;
  94. }
  95. void LLPacketRing::setInBandwidth(const F32 bps)
  96. {
  97. mInThrottle.setRate(bps);
  98. }
  99. void LLPacketRing::setOutBandwidth(const F32 bps)
  100. {
  101. mOutThrottle.setRate(bps);
  102. }
  103. ///////////////////////////////////////////////////////////
  104. S32 LLPacketRing::receiveFromRing (S32 socket, char *datap)
  105. {
  106. if (mInThrottle.checkOverflow(0))
  107. {
  108. // We don't have enough bandwidth, don't give them a packet.
  109. return 0;
  110. }
  111. LLPacketBuffer *packetp = NULL;
  112. if (mReceiveQueue.empty())
  113. {
  114. // No packets on the queue, don't give them any.
  115. return 0;
  116. }
  117. S32 packet_size = 0;
  118. packetp = mReceiveQueue.front();
  119. mReceiveQueue.pop();
  120. packet_size = packetp->getSize();
  121. if (packetp->getData() != NULL)
  122. {
  123. memcpy(datap, packetp->getData(), packet_size); /*Flawfinder: ignore*/
  124. }
  125. // need to set sender IP/port!!
  126. mLastSender = packetp->getHost();
  127. mLastReceivingIF = packetp->getReceivingInterface();
  128. delete packetp;
  129. this->mInBufferLength -= packet_size;
  130. // Adjust the throttle
  131. mInThrottle.throttleOverflow(packet_size * 8.f);
  132. return packet_size;
  133. }
  134. ///////////////////////////////////////////////////////////
  135. S32 LLPacketRing::receivePacket (S32 socket, char *datap)
  136. {
  137. S32 packet_size = 0;
  138. // If using the throttle, simulate a limited size input buffer.
  139. if (mUseInThrottle)
  140. {
  141. BOOL done = FALSE;
  142. // push any current net packet (if any) onto delay ring
  143. while (!done)
  144. {
  145. LLPacketBuffer *packetp;
  146. packetp = new LLPacketBuffer(socket);
  147. if (packetp->getSize())
  148. {
  149. mActualBitsIn += packetp->getSize() * 8;
  150. // Fake packet loss
  151. if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
  152. {
  153. mPacketsToDrop++;
  154. }
  155. if (mPacketsToDrop)
  156. {
  157. delete packetp;
  158. packetp = NULL;
  159. packet_size = 0;
  160. mPacketsToDrop--;
  161. }
  162. }
  163. // If we faked packet loss, then we don't have a packet
  164. // to use for buffer overflow testing
  165. if (packetp)
  166. {
  167. if (mInBufferLength + packetp->getSize() > mMaxBufferLength)
  168. {
  169. // Toss it.
  170. llwarns << "Throwing away packet, overflowing buffer" << llendl;
  171. delete packetp;
  172. packetp = NULL;
  173. }
  174. else if (packetp->getSize())
  175. {
  176. mReceiveQueue.push(packetp);
  177. mInBufferLength += packetp->getSize();
  178. }
  179. else
  180. {
  181. delete packetp;
  182. packetp = NULL;
  183. done = true;
  184. }
  185. }
  186. else
  187. {
  188. // No packetp, keep going? - no packetp == faked packet loss
  189. }
  190. }
  191. // Now, grab data off of the receive queue according to our
  192. // throttled bandwidth settings.
  193. packet_size = receiveFromRing(socket, datap);
  194. }
  195. else
  196. {
  197. // no delay, pull straight from net
  198. packet_size = receive_packet(socket, datap);
  199. mLastSender = ::get_sender();
  200. mLastReceivingIF = ::get_receiving_interface();
  201. if (packet_size)  // did we actually get a packet?
  202. {
  203. if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
  204. {
  205. mPacketsToDrop++;
  206. }
  207. if (mPacketsToDrop)
  208. {
  209. packet_size = 0;
  210. mPacketsToDrop--;
  211. }
  212. }
  213. }
  214. return packet_size;
  215. }
  216. BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
  217. {
  218. BOOL status = TRUE;
  219. if (!mUseOutThrottle)
  220. {
  221. return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() );
  222. }
  223. else
  224. {
  225. mActualBitsOut += buf_size * 8;
  226. LLPacketBuffer *packetp = NULL;
  227. // See if we've got enough throttle to send a packet.
  228. while (!mOutThrottle.checkOverflow(0.f))
  229. {
  230. // While we have enough bandwidth, send a packet from the queue or the current packet
  231. S32 packet_size = 0;
  232. if (!mSendQueue.empty())
  233. {
  234. // Send a packet off of the queue
  235. LLPacketBuffer *packetp = mSendQueue.front();
  236. mSendQueue.pop();
  237. mOutBufferLength -= packetp->getSize();
  238. packet_size = packetp->getSize();
  239. status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort());
  240. delete packetp;
  241. // Update the throttle
  242. mOutThrottle.throttleOverflow(packet_size * 8.f);
  243. }
  244. else
  245. {
  246. // If the queue's empty, we can just send this packet right away.
  247. status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() );
  248. packet_size = buf_size;
  249. // Update the throttle
  250. mOutThrottle.throttleOverflow(packet_size * 8.f);
  251. // This was the packet we're sending now, there are no other packets
  252. // that we need to send
  253. return status;
  254. }
  255. }
  256. // We haven't sent the incoming packet, add it to the queue
  257. if (mOutBufferLength + buf_size > mMaxBufferLength)
  258. {
  259. // Nuke this packet, we overflowed the buffer.
  260. // Toss it.
  261. llwarns << "Throwing away outbound packet, overflowing buffer" << llendl;
  262. }
  263. else
  264. {
  265. static LLTimer queue_timer;
  266. if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
  267. {
  268. // Add it to the queue
  269. llinfos << "Outbound packet queue " << mOutBufferLength << " bytes" << llendl;
  270. queue_timer.reset();
  271. }
  272. packetp = new LLPacketBuffer(host, send_buffer, buf_size);
  273. mOutBufferLength += packetp->getSize();
  274. mSendQueue.push(packetp);
  275. }
  276. }
  277. return status;
  278. }