diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmessage/llpacketring.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 312 |
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 | /////////////////////////////////////////////////////////// | ||
40 | LLPacketRing::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 | /////////////////////////////////////////////////////////// | ||
56 | LLPacketRing::~LLPacketRing () | ||
57 | { | ||
58 | free(); | ||
59 | } | ||
60 | |||
61 | /////////////////////////////////////////////////////////// | ||
62 | void 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 | /////////////////////////////////////////////////////////// | ||
82 | void LLPacketRing::dropPackets (U32 num_to_drop) | ||
83 | { | ||
84 | mPacketsToDrop += num_to_drop; | ||
85 | } | ||
86 | |||
87 | /////////////////////////////////////////////////////////// | ||
88 | void LLPacketRing::setDropPercentage (F32 percent_to_drop) | ||
89 | { | ||
90 | mDropPercentage = percent_to_drop; | ||
91 | } | ||
92 | |||
93 | void LLPacketRing::setUseInThrottle(const BOOL use_throttle) | ||
94 | { | ||
95 | mUseInThrottle = use_throttle; | ||
96 | } | ||
97 | |||
98 | void LLPacketRing::setUseOutThrottle(const BOOL use_throttle) | ||
99 | { | ||
100 | mUseOutThrottle = use_throttle; | ||
101 | } | ||
102 | |||
103 | void LLPacketRing::setInBandwidth(const F32 bps) | ||
104 | { | ||
105 | mInThrottle.setRate(bps); | ||
106 | } | ||
107 | |||
108 | void LLPacketRing::setOutBandwidth(const F32 bps) | ||
109 | { | ||
110 | mOutThrottle.setRate(bps); | ||
111 | } | ||
112 | /////////////////////////////////////////////////////////// | ||
113 | S32 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 | /////////////////////////////////////////////////////////// | ||
149 | S32 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 | |||
240 | BOOL 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 | } | ||