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