Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: webrtc/test/channel_transport/udp_socket2_win.cc

Issue 2319583005: Moved webrtc/test/channel_transport/ into webrtc/voice_engine/test/ (Closed)
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/test/channel_transport/udp_socket2_win.h"
12
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <winsock2.h>
16
17 #include "webrtc/base/format_macros.h"
18 #include "webrtc/system_wrappers/include/sleep.h"
19 #include "webrtc/test/channel_transport/traffic_control_win.h"
20 #include "webrtc/test/channel_transport/udp_socket2_manager_win.h"
21
22 #pragma warning(disable : 4311)
23
24 namespace webrtc {
25 namespace test {
26
27 typedef struct _QOS_DESTADDR
28 {
29 QOS_OBJECT_HDR ObjectHdr;
30 const struct sockaddr* SocketAddress;
31 ULONG SocketAddressLength;
32 } QOS_DESTADDR, *LPQOS_DESTADDR;
33
34 typedef const QOS_DESTADDR* LPCQOS_DESTADDR;
35
36 // TODO (patrikw): seems to be defined in ws2ipdef.h as 3. How come it's
37 // redefined here (as a different value)?
38 #define IP_TOS 8
39
40 #define QOS_GENERAL_ID_BASE 2000
41 #define QOS_OBJECT_DESTADDR (0x00000004 + QOS_GENERAL_ID_BASE)
42
43 UdpSocket2Windows::UdpSocket2Windows(const int32_t id,
44 UdpSocketManager* mgr, bool ipV6Enable,
45 bool disableGQOS)
46 : _id(id),
47 _qos(true),
48 _iProtocol(0),
49 _outstandingCalls(0),
50 _outstandingCallComplete(0),
51 _terminate(false),
52 _addedToMgr(false),
53 delete_event_(true, false),
54 _outstandingCallsDisabled(false),
55 _clientHandle(NULL),
56 _flowHandle(NULL),
57 _filterHandle(NULL),
58 _flow(NULL),
59 _gtc(NULL),
60 _pcp(-2),
61 _receiveBuffers(0)
62 {
63 WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id,
64 "UdpSocket2Windows::UdpSocket2Windows()");
65
66 _wantsIncoming = false;
67 _mgr = static_cast<UdpSocket2ManagerWindows *>(mgr);
68
69 _obj = NULL;
70 _incomingCb = NULL;
71 _socket = INVALID_SOCKET;
72 _ptrCbRWLock = RWLockWrapper::CreateRWLock();
73 _ptrDestRWLock = RWLockWrapper::CreateRWLock();
74 _ptrSocketRWLock = RWLockWrapper::CreateRWLock();
75
76 // Check if QoS is supported.
77 BOOL bProtocolFound = FALSE;
78 WSAPROTOCOL_INFO *lpProtocolBuf = NULL;
79 WSAPROTOCOL_INFO pProtocolInfo;
80
81 if(!disableGQOS)
82 {
83 DWORD dwBufLen = 0;
84 // Set dwBufLen to the size needed to retreive all the requested
85 // information from WSAEnumProtocols.
86 int32_t nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
87 lpProtocolBuf = (WSAPROTOCOL_INFO*)malloc(dwBufLen);
88 nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
89
90 if (ipV6Enable)
91 {
92 _iProtocol=AF_INET6;
93 } else {
94 _iProtocol=AF_INET;
95 }
96
97 for (int32_t i=0; i<nRet; i++)
98 {
99 if (_iProtocol == lpProtocolBuf[i].iAddressFamily &&
100 IPPROTO_UDP == lpProtocolBuf[i].iProtocol)
101 {
102 if ((XP1_QOS_SUPPORTED ==
103 (XP1_QOS_SUPPORTED & lpProtocolBuf[i].dwServiceFlags1)))
104 {
105 pProtocolInfo = lpProtocolBuf[i];
106 bProtocolFound = TRUE;
107 break;
108 }
109 }
110 }
111 }
112
113 if(!bProtocolFound)
114 {
115 free(lpProtocolBuf);
116 _qos=false;
117 WEBRTC_TRACE(
118 kTraceError,
119 kTraceTransport,
120 _id,
121 "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR_NO_QOS,\
122 !bProtocolFound");
123 } else {
124
125 _socket = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
126 FROM_PROTOCOL_INFO,&pProtocolInfo, 0,
127 WSA_FLAG_OVERLAPPED);
128 free(lpProtocolBuf);
129
130 if (_socket != INVALID_SOCKET)
131 {
132 return;
133 } else {
134 _qos = false;
135 WEBRTC_TRACE(
136 kTraceError,
137 kTraceTransport,
138 _id,
139 "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR_NO_QOS");
140 }
141 }
142 // QoS not supported.
143 if(ipV6Enable)
144 {
145 _socket = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, 0 , 0,
146 WSA_FLAG_OVERLAPPED);
147 }else
148 {
149 _socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0 , 0,
150 WSA_FLAG_OVERLAPPED);
151 }
152 if (_socket == INVALID_SOCKET)
153 {
154 WEBRTC_TRACE(
155 kTraceError,
156 kTraceTransport,
157 _id,
158 "UdpSocket2Windows::UdpSocket2Windows(), INVALID_SOCKET,\
159 WSAerror: %d",
160 WSAGetLastError());
161 }
162
163 // Disable send buffering on the socket to improve CPU usage.
164 // This is done by setting SO_SNDBUF to 0.
165 int32_t nZero = 0;
166 int32_t nRet = setsockopt(_socket, SOL_SOCKET, SO_SNDBUF,
167 (char*)&nZero, sizeof(nZero));
168 if( nRet == SOCKET_ERROR )
169 {
170 WEBRTC_TRACE(
171 kTraceError,
172 kTraceTransport,
173 _id,
174 "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR,\
175 WSAerror: %d",
176 WSAGetLastError());
177 }
178 }
179
180 UdpSocket2Windows::~UdpSocket2Windows()
181 {
182 WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id,
183 "UdpSocket2Windows::~UdpSocket2Windows()");
184
185 delete_event_.Wait(rtc::Event::kForever);
186
187
188 delete _ptrCbRWLock;
189 delete _ptrDestRWLock;
190 delete _ptrSocketRWLock;
191
192 if (_flow)
193 {
194 free(_flow);
195 _flow = NULL;
196 }
197
198 if (_gtc)
199 {
200 if(_filterHandle)
201 {
202 _gtc->TcDeleteFilter(_filterHandle);
203 }
204 if(_flowHandle)
205 {
206 _gtc->TcDeleteFlow(_flowHandle);
207 }
208 TrafficControlWindows::Release( _gtc);
209 }
210 }
211
212 bool UdpSocket2Windows::ValidHandle()
213 {
214 return GetFd() != INVALID_SOCKET;
215 }
216
217 bool UdpSocket2Windows::SetCallback(CallbackObj obj, IncomingSocketCallback cb)
218 {
219 _ptrCbRWLock->AcquireLockExclusive();
220 _obj = obj;
221 _incomingCb = cb;
222 _ptrCbRWLock->ReleaseLockExclusive();
223
224 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
225 "UdpSocket2Windows(%d)::SetCallback ",(int32_t)this);
226 if(_addedToMgr)
227 {
228 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
229 "UdpSocket2Windows(%d)::SetCallback alreadey added",
230 (int32_t) this);
231 return false;
232
233 }
234 if (_mgr->AddSocket(this))
235 {
236 WEBRTC_TRACE(
237 kTraceDebug, kTraceTransport, _id,
238 "UdpSocket2Windows(%d)::SetCallback socket added to manager",
239 (int32_t)this);
240 _addedToMgr = true;
241 return true;
242 }
243
244 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
245 "UdpSocket2Windows(%d)::SetCallback error adding me to mgr",
246 (int32_t) this);
247 return false;
248 }
249
250 bool UdpSocket2Windows::SetSockopt(int32_t level, int32_t optname,
251 const int8_t* optval, int32_t optlen)
252 {
253 bool returnValue = true;
254 if(!AquireSocket())
255 {
256 return false;
257 }
258 if(0 != setsockopt(_socket, level, optname,
259 reinterpret_cast<const char*>(optval), optlen ))
260 {
261 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
262 "UdpSocket2Windows::SetSockopt(), WSAerror:%d",
263 WSAGetLastError());
264 returnValue = false;
265 }
266 ReleaseSocket();
267 return returnValue;
268 }
269
270 bool UdpSocket2Windows::StartReceiving(uint32_t receiveBuffers)
271 {
272 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
273 "UdpSocket2Windows(%d)::StartReceiving(%d)", (int32_t)this,
274 receiveBuffers);
275
276 _wantsIncoming = true;
277
278 int32_t numberOfReceiveBuffersToCreate =
279 receiveBuffers - _receiveBuffers.Value();
280 numberOfReceiveBuffersToCreate = (numberOfReceiveBuffersToCreate < 0) ?
281 0 : numberOfReceiveBuffersToCreate;
282
283 int32_t error = 0;
284 for(int32_t i = 0;
285 i < numberOfReceiveBuffersToCreate;
286 i++)
287 {
288 if(PostRecv())
289 {
290 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
291 "UdpSocket2Windows::StartReceiving() i=%d", i);
292 error = -1;
293 break;
294 }
295 ++_receiveBuffers;
296 }
297 if(error == -1)
298 {
299 return false;
300 }
301
302 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
303 "Socket receiving using:%d number of buffers",
304 _receiveBuffers.Value());
305 return true;
306 }
307
308 bool UdpSocket2Windows::StopReceiving()
309 {
310 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
311 "UdpSocket2Windows::StopReceiving()");
312 _wantsIncoming = false;
313 return true;
314 }
315
316 bool UdpSocket2Windows::Bind(const SocketAddress& name)
317 {
318 const struct sockaddr* addr =
319 reinterpret_cast<const struct sockaddr*>(&name);
320 bool returnValue = true;
321 if(!AquireSocket())
322 {
323 return false;
324 }
325 if (0 != bind(_socket, addr, sizeof(SocketAddress)))
326 {
327 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
328 "UdpSocket2Windows::Bind() WSAerror: %d",
329 WSAGetLastError());
330 returnValue = false;
331 }
332 ReleaseSocket();
333 return returnValue;
334 }
335
336 int32_t UdpSocket2Windows::SendTo(const int8_t* buf, size_t len,
337 const SocketAddress& to)
338 {
339 int32_t retVal = 0;
340 int32_t error = 0;
341 PerIoContext* pIoContext = _mgr->PopIoContext();
342 if(pIoContext == 0)
343 {
344 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
345 "UdpSocket2Windows(%d)::SendTo(), pIoContext==0",
346 (int32_t) this);
347 return -1;
348 }
349 // sizeof(pIoContext->buffer) is smaller than the highest number that
350 // can be represented by a size_t.
351 if(len >= sizeof(pIoContext->buffer))
352 {
353 WEBRTC_TRACE(
354 kTraceError,
355 kTraceTransport,
356 _id,
357 "UdpSocket2Windows(%d)::SendTo(), len= %" PRIuS
358 " > buffer_size = %d",
359 (int32_t) this,
360 len,sizeof(pIoContext->buffer));
361 len = sizeof(pIoContext->buffer);
362 }
363
364 memcpy(pIoContext->buffer,buf,len);
365 pIoContext->wsabuf.buf = pIoContext->buffer;
366 pIoContext->wsabuf.len = static_cast<ULONG>(len);
367 pIoContext->fromLen=sizeof(SocketAddress);
368 pIoContext->ioOperation = OP_WRITE;
369 pIoContext->nTotalBytes = len;
370 pIoContext->nSentBytes=0;
371
372 DWORD numOfbytesSent = 0;
373 const struct sockaddr* addr = reinterpret_cast<const struct sockaddr*>(&to);
374
375 if(!AquireSocket())
376 {
377 _mgr->PushIoContext(pIoContext);
378 return -1;
379 }
380 // Assume that the WSASendTo call will be successfull to make sure that
381 // _outstandingCalls is positive. Roll back if WSASendTo failed.
382 if(!NewOutstandingCall())
383 {
384 _mgr->PushIoContext(pIoContext);
385 ReleaseSocket();
386 return -1;
387 }
388 retVal = WSASendTo(_socket, &pIoContext->wsabuf, 1, &numOfbytesSent,
389 0, addr, sizeof(SocketAddress),
390 &(pIoContext->overlapped), 0);
391 ReleaseSocket();
392
393 if( retVal == SOCKET_ERROR )
394 {
395 error = WSAGetLastError();
396 if(error != ERROR_IO_PENDING)
397 {
398 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
399 "UdpSocket2Windows::SendTo() WSAerror: %d",error);
400 }
401 }
402 if(retVal == 0 || (retVal == SOCKET_ERROR && error == ERROR_IO_PENDING))
403 {
404 return static_cast<int32_t>(len);
405 }
406 error = _mgr->PushIoContext(pIoContext);
407 if(error)
408 {
409 WEBRTC_TRACE(
410 kTraceError,
411 kTraceTransport,
412 _id,
413 "UdpSocket2Windows(%d)::SendTo(), error:%d pushing ioContext",
414 (int32_t)this, error);
415 }
416
417 // Roll back.
418 OutstandingCallCompleted();
419 return -1;
420 }
421
422 void UdpSocket2Windows::IOCompleted(PerIoContext* pIOContext,
423 uint32_t ioSize, uint32_t error)
424 {
425 if(pIOContext == NULL || error == ERROR_OPERATION_ABORTED)
426 {
427 if ((pIOContext != NULL) &&
428 !pIOContext->ioInitiatedByPlatformThread &&
429 (error == ERROR_OPERATION_ABORTED) &&
430 (pIOContext->ioOperation == OP_READ) &&
431 _outstandingCallsDisabled)
432 {
433 // !pIOContext->initiatedIOByPlatformThread indicate that the I/O
434 // was not initiated by a PlatformThread thread.
435 // This may happen if the thread that initiated receiving (e.g.
436 // by calling StartListen())) is deleted before any packets have
437 // been received.
438 // In this case there is no packet in the PerIoContext. Re-use it
439 // to post a new PostRecv(..).
440 // Note 1: the PerIoContext will henceforth be posted by a thread
441 // that is controlled by the socket implementation.
442 // Note 2: This is more likely to happen to RTCP packets as
443 // they are less frequent than RTP packets.
444 // Note 3: _outstandingCallsDisabled being false indicates
445 // that the socket isn't being shut down.
446 // Note 4: This should only happen buffers set to receive packets
447 // (OP_READ).
448 } else {
449 if(pIOContext == NULL)
450 {
451 WEBRTC_TRACE(
452 kTraceError,
453 kTraceTransport,
454 _id,
455 "UdpSocket2Windows::IOCompleted(%d,%d,%d), %d",
456 (int32_t)pIOContext,
457 ioSize,
458 error,
459 pIOContext ? (int32_t)pIOContext->ioOperation : -1);
460 } else {
461 WEBRTC_TRACE(
462 kTraceDebug,
463 kTraceTransport,
464 _id,
465 "UdpSocket2Windows::IOCompleted() Operation aborted");
466 }
467 if(pIOContext)
468 {
469 int32_t remainingReceiveBuffers = --_receiveBuffers;
470 if(remainingReceiveBuffers < 0)
471 {
472 assert(false);
473 }
474 int32_t err = _mgr->PushIoContext(pIOContext);
475 if(err)
476 {
477 WEBRTC_TRACE(
478 kTraceError,
479 kTraceTransport,
480 _id,
481 "UdpSocket2Windows::IOCompleted(), err = %d, when\
482 pushing ioContext after error",
483 err);
484 }
485 }
486 OutstandingCallCompleted();
487 return;
488 }
489 } // if (pIOContext == NULL || error == ERROR_OPERATION_ABORTED)
490
491 if(pIOContext->ioOperation == OP_WRITE)
492 {
493 _mgr->PushIoContext(pIOContext);
494 }
495 else if(pIOContext->ioOperation == OP_READ)
496 {
497 if(!error && ioSize != 0)
498 {
499 _ptrCbRWLock->AcquireLockShared();
500 if(_wantsIncoming && _incomingCb)
501 {
502 _incomingCb(_obj,
503 reinterpret_cast<const int8_t*>(
504 pIOContext->wsabuf.buf),
505 ioSize,
506 &pIOContext->from);
507 }
508 _ptrCbRWLock->ReleaseLockShared();
509 }
510 int32_t err = PostRecv(pIOContext);
511 if(err == 0)
512 {
513 // The PerIoContext was posted by a thread controlled by the socket
514 // implementation.
515 pIOContext->ioInitiatedByPlatformThread = true;
516 }
517 OutstandingCallCompleted();
518 return;
519 } else {
520 // Unknown operation. Should not happen. Return pIOContext to avoid
521 // memory leak.
522 assert(false);
523 _mgr->PushIoContext(pIOContext);
524 }
525 OutstandingCallCompleted();
526 // Don't touch any members after OutstandingCallCompleted() since the socket
527 // may be deleted at this point.
528 }
529
530 int32_t UdpSocket2Windows::PostRecv()
531 {
532 PerIoContext* pIoContext=_mgr->PopIoContext();
533 if(pIoContext == 0)
534 {
535 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
536 "UdpSocket2Windows(%d)::PostRecv(), pIoContext == 0",
537 (int32_t)this);
538 return -1;
539 }
540 // This function may have been called by thread not controlled by the socket
541 // implementation.
542 pIoContext->ioInitiatedByPlatformThread = false;
543 return PostRecv(pIoContext);
544 }
545
546 int32_t UdpSocket2Windows::PostRecv(PerIoContext* pIoContext)
547 {
548 if(pIoContext==0)
549 {
550 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
551 "UdpSocket2Windows(%d)::PostRecv(?), pIoContext==0",
552 (int32_t)this);
553 return -1;
554 }
555
556 DWORD numOfRecivedBytes = 0;
557 DWORD flags = 0;
558 pIoContext->wsabuf.buf = pIoContext->buffer;
559 pIoContext->wsabuf.len = sizeof(pIoContext->buffer);
560 pIoContext->fromLen = sizeof(SocketAddress);
561 pIoContext->ioOperation = OP_READ;
562 int32_t rxError = 0;
563 int32_t nRet = 0;
564 int32_t postingSucessfull = false;
565
566 if(!AquireSocket())
567 {
568 _mgr->PushIoContext(pIoContext);
569 return -1;
570 }
571
572 // Assume that the WSARecvFrom() call will be successfull to make sure that
573 // _outstandingCalls is positive. Roll back if WSARecvFrom() failed.
574 if(!NewOutstandingCall())
575 {
576 _mgr->PushIoContext(pIoContext);
577 ReleaseSocket();
578 return -1;
579 }
580 for(int32_t tries = 0; tries < 10; tries++)
581 {
582 nRet = WSARecvFrom(
583 _socket,
584 &(pIoContext->wsabuf),
585 1,
586 &numOfRecivedBytes,
587 &flags,
588 reinterpret_cast<struct sockaddr*>(&(pIoContext->from)),
589 &(pIoContext->fromLen),
590 &(pIoContext->overlapped),
591 0);
592
593 if( nRet == SOCKET_ERROR)
594 {
595 rxError = WSAGetLastError();
596 if(rxError != ERROR_IO_PENDING)
597 {
598 WEBRTC_TRACE(
599 kTraceError,
600 kTraceTransport,
601 _id,
602 "UdpSocket2Windows(%d)::PostRecv(?), WSAerror:%d when\
603 posting new recieve,trie:%d",
604 (int32_t)this,
605 rxError,
606 tries);
607 // Tell the OS that this is a good place to context switch if
608 // it wants to.
609 SleepMs(0);
610 }
611 }
612 if((rxError == ERROR_IO_PENDING) || (nRet == 0))
613 {
614 postingSucessfull = true;
615 break;
616 }
617 }
618 ReleaseSocket();
619
620 if(postingSucessfull)
621 {
622 return 0;
623 }
624 int32_t remainingReceiveBuffers = --_receiveBuffers;
625 if(remainingReceiveBuffers < 0)
626 {
627 assert(false);
628 }
629 int32_t error = _mgr->PushIoContext(pIoContext);
630 if(error)
631 {
632 WEBRTC_TRACE(
633 kTraceError,
634 kTraceTransport,
635 _id,
636 "UdpSocket2Windows(%d)::PostRecv(?), error:%d when PushIoContext",
637 (int32_t)this,
638 error);
639 }
640 // Roll back.
641 OutstandingCallCompleted();
642 return -1;
643 }
644
645 void UdpSocket2Windows::CloseBlocking()
646 {
647 LINGER lingerStruct;
648
649 lingerStruct.l_onoff = 1;
650 lingerStruct.l_linger = 0;
651 if(AquireSocket())
652 {
653 setsockopt(_socket, SOL_SOCKET, SO_LINGER,
654 reinterpret_cast<const char*>(&lingerStruct),
655 sizeof(lingerStruct));
656 ReleaseSocket();
657 }
658
659 _wantsIncoming = false;
660 // Reclaims the socket and prevents it from being used again.
661 InvalidateSocket();
662 DisableNewOutstandingCalls();
663 delete this;
664 }
665
666 bool UdpSocket2Windows::SetQos(int32_t serviceType,
667 int32_t tokenRate,
668 int32_t bucketSize,
669 int32_t peekBandwith,
670 int32_t minPolicedSize,
671 int32_t maxSduSize,
672 const SocketAddress &stRemName,
673 int32_t overrideDSCP)
674 {
675 if(_qos == false)
676 {
677 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
678 "UdpSocket2Windows::SetQos(), socket not capable of QOS");
679 return false;
680 }
681 if(overrideDSCP != 0)
682 {
683 FLOWSPEC f;
684 int32_t err = CreateFlowSpec(serviceType, tokenRate, bucketSize,
685 peekBandwith, minPolicedSize,
686 maxSduSize, &f);
687 if(err == -1)
688 {
689 return false;
690 }
691
692 SocketAddress socketName;
693 struct sockaddr_in* name =
694 reinterpret_cast<struct sockaddr_in*>(&socketName);
695 int nameLength = sizeof(SocketAddress);
696 if(AquireSocket())
697 {
698 getsockname(_socket, (struct sockaddr*)name, &nameLength);
699 ReleaseSocket();
700 }
701
702 if(serviceType == 0)
703 {
704 // Disable TOS byte setting.
705 return SetTrafficControl(0, -1, name, &f, &f) == 0;
706 }
707 return SetTrafficControl(overrideDSCP, -1, name, &f, &f) == 0;
708 }
709
710 QOS Qos;
711 DWORD BytesRet;
712 QOS_DESTADDR QosDestaddr;
713
714 memset (&Qos, QOS_NOT_SPECIFIED, sizeof(QOS));
715
716 Qos.SendingFlowspec.ServiceType = serviceType;
717 Qos.SendingFlowspec.TokenRate = tokenRate;
718 Qos.SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
719 Qos.SendingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
720 Qos.SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
721 Qos.SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
722 Qos.SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
723 Qos.SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
724
725 // Only ServiceType is needed for receiving.
726 Qos.ReceivingFlowspec.ServiceType = serviceType;
727 Qos.ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED;
728 Qos.ReceivingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
729 Qos.ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
730 Qos.ReceivingFlowspec.Latency = QOS_NOT_SPECIFIED;
731 Qos.ReceivingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
732 Qos.ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
733 Qos.ReceivingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
734
735 Qos.ProviderSpecific.len = 0;
736
737 Qos.ProviderSpecific.buf = NULL;
738
739 ZeroMemory((int8_t *)&QosDestaddr, sizeof(QosDestaddr));
740
741 OSVERSIONINFOEX osvie;
742 osvie.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
743 GetVersionEx((LPOSVERSIONINFO)&osvie);
744
745 // Operating system Version number dwMajorVersion dwMinorVersion
746 // Windows 7 6.1 6 1
747 // Windows Server 2008 R2 6.1 6 1
748 // Windows Server 2008 6.0 6 0
749 // Windows Vista 6.0 6 0
750 // Windows Server 2003 R2 5.2 5 2
751 // Windows Server 2003 5.2 5 2
752 // Windows XP 5.1 5 1
753 // Windows 2000 5.0 5 0
754
755 // SERVICE_NO_QOS_SIGNALING and QOS_DESTADDR should not be used if version
756 // is 6.0 or greater.
757 if(osvie.dwMajorVersion >= 6)
758 {
759 Qos.SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
760 Qos.ReceivingFlowspec.ServiceType = serviceType;
761
762 } else {
763 Qos.SendingFlowspec.MinimumPolicedSize =
764 QOS_NOT_SPECIFIED | SERVICE_NO_QOS_SIGNALING;
765 Qos.ReceivingFlowspec.ServiceType =
766 serviceType | SERVICE_NO_QOS_SIGNALING;
767
768 QosDestaddr.ObjectHdr.ObjectType = QOS_OBJECT_DESTADDR;
769 QosDestaddr.ObjectHdr.ObjectLength = sizeof(QosDestaddr);
770 QosDestaddr.SocketAddress = (SOCKADDR *)&stRemName;
771 if (AF_INET6 == _iProtocol)
772 {
773 QosDestaddr.SocketAddressLength = sizeof(SocketAddressInVersion6);
774 } else {
775 QosDestaddr.SocketAddressLength = sizeof(SocketAddressIn);
776 }
777
778 Qos.ProviderSpecific.len = QosDestaddr.ObjectHdr.ObjectLength;
779 Qos.ProviderSpecific.buf = (char*)&QosDestaddr;
780 }
781
782 if(!AquireSocket()) {
783 return false;
784 }
785 // To set QoS with SIO_SET_QOS the socket must be locally bound first
786 // or the call will fail with error code 10022.
787 int32_t result = WSAIoctl(GetFd(), SIO_SET_QOS, &Qos, sizeof(QOS),
788 NULL, 0, &BytesRet, NULL,NULL);
789 ReleaseSocket();
790 if (result == SOCKET_ERROR)
791 {
792 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
793 "UdpSocket2Windows::SetQos() WSAerror : %d",
794 WSAGetLastError());
795 return false;
796 }
797 return true;
798 }
799
800 int32_t UdpSocket2Windows::SetTOS(int32_t serviceType)
801 {
802 SocketAddress socketName;
803
804 struct sockaddr_in* name =
805 reinterpret_cast<struct sockaddr_in*>(&socketName);
806 int nameLength = sizeof(SocketAddress);
807 if(AquireSocket())
808 {
809 getsockname(_socket, (struct sockaddr*)name, &nameLength);
810 ReleaseSocket();
811 }
812
813 int32_t res = SetTrafficControl(serviceType, -1, name);
814 if (res == -1)
815 {
816 OSVERSIONINFO OsVersion;
817 OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
818 GetVersionEx (&OsVersion);
819
820 if ((OsVersion.dwMajorVersion == 4)) // NT 4.0
821 {
822 if(SetSockopt(IPPROTO_IP,IP_TOS ,
823 (int8_t*)&serviceType, 4) != 0)
824 {
825 return -1;
826 }
827 }
828 }
829 return res;
830 }
831
832 int32_t UdpSocket2Windows::SetPCP(int32_t pcp)
833 {
834 SocketAddress socketName;
835 struct sockaddr_in* name =
836 reinterpret_cast<struct sockaddr_in*>(&socketName);
837 int nameLength = sizeof(SocketAddress);
838 if(AquireSocket())
839 {
840 getsockname(_socket, (struct sockaddr*)name, &nameLength);
841 ReleaseSocket();
842 }
843 return SetTrafficControl(-1, pcp, name);
844 }
845
846 int32_t UdpSocket2Windows::SetTrafficControl(
847 int32_t dscp,
848 int32_t pcp,
849 const struct sockaddr_in* name,
850 FLOWSPEC* send, FLOWSPEC* recv)
851 {
852 if (pcp == _pcp)
853 {
854 // No change.
855 pcp = -1;
856 }
857 if ((-1 == pcp) && (-1 == dscp))
858 {
859 return 0;
860 }
861 if (!_gtc)
862 {
863 _gtc = TrafficControlWindows::GetInstance(_id);
864 }
865 if (!_gtc)
866 {
867 return -1;
868 }
869 if(_filterHandle)
870 {
871 _gtc->TcDeleteFilter(_filterHandle);
872 _filterHandle = NULL;
873 }
874 if(_flowHandle)
875 {
876 _gtc->TcDeleteFlow(_flowHandle);
877 _flowHandle = NULL;
878 }
879 if(_clientHandle)
880 {
881 _gtc->TcDeregisterClient(_clientHandle);
882 _clientHandle = NULL;
883 }
884 if ((0 == dscp) && (-2 == _pcp) && (-1 == pcp))
885 {
886 // TODO (pwestin): why is this not done before deleting old filter and
887 // flow? This scenario should probably be documented in
888 // the function declaration.
889 return 0;
890 }
891
892 TCI_CLIENT_FUNC_LIST QoSFunctions;
893 QoSFunctions.ClAddFlowCompleteHandler = NULL;
894 QoSFunctions.ClDeleteFlowCompleteHandler = NULL;
895 QoSFunctions.ClModifyFlowCompleteHandler = NULL;
896 QoSFunctions.ClNotifyHandler = (TCI_NOTIFY_HANDLER)MyClNotifyHandler;
897 // Register the client with Traffic control interface.
898 HANDLE ClientHandle;
899 ULONG result = _gtc->TcRegisterClient(CURRENT_TCI_VERSION, NULL,
900 &QoSFunctions,&ClientHandle);
901 if(result != NO_ERROR)
902 {
903 // This is likely caused by the application not being run as
904 // administrator.
905 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
906 "TcRegisterClient returned %d", result);
907 return result;
908 }
909
910 // Find traffic control-enabled network interfaces that matches this
911 // socket's IP address.
912 ULONG BufferSize = 0;
913 result = _gtc->TcEnumerateInterfaces(ClientHandle, &BufferSize, NULL);
914
915 if(result != NO_ERROR && result != ERROR_INSUFFICIENT_BUFFER)
916 {
917 _gtc->TcDeregisterClient(ClientHandle);
918 return result;
919 }
920
921 if(result != ERROR_INSUFFICIENT_BUFFER)
922 {
923 // Empty buffer contains all control-enabled network interfaces. I.e.
924 // QoS is not enabled.
925 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
926 "QOS faild since QOS is not installed on the interface");
927
928 _gtc->TcDeregisterClient(ClientHandle);
929 return -1;
930 }
931
932 PTC_IFC_DESCRIPTOR pInterfaceBuffer =
933 (PTC_IFC_DESCRIPTOR)malloc(BufferSize);
934 if(pInterfaceBuffer == NULL)
935 {
936 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
937 "Out ot memory failure");
938 _gtc->TcDeregisterClient(ClientHandle);
939 return ERROR_NOT_ENOUGH_MEMORY;
940 }
941
942 result = _gtc->TcEnumerateInterfaces(ClientHandle, &BufferSize,
943 pInterfaceBuffer);
944
945 if(result != NO_ERROR)
946 {
947 WEBRTC_TRACE(
948 kTraceError,
949 kTraceTransport,
950 _id,
951 "Critical: error enumerating interfaces when passing in correct\
952 buffer size: %d", result);
953 _gtc->TcDeregisterClient(ClientHandle);
954 free(pInterfaceBuffer);
955 return result;
956 }
957
958 PTC_IFC_DESCRIPTOR oneinterface;
959 HANDLE ifcHandle, iFilterHandle, iflowHandle;
960 bool addrFound = false;
961 ULONG filterSourceAddress = ULONG_MAX;
962
963 // Find the interface corresponding to the local address.
964 for(oneinterface = pInterfaceBuffer;
965 oneinterface != (PTC_IFC_DESCRIPTOR)
966 (((int8_t*)pInterfaceBuffer) + BufferSize);
967 oneinterface = (PTC_IFC_DESCRIPTOR)
968 ((int8_t *)oneinterface + oneinterface->Length))
969 {
970
971 char interfaceName[500];
972 WideCharToMultiByte(CP_ACP, 0, oneinterface->pInterfaceName, -1,
973 interfaceName, sizeof(interfaceName), 0, 0 );
974
975 PNETWORK_ADDRESS_LIST addresses =
976 &(oneinterface->AddressListDesc.AddressList);
977 for(LONG i = 0; i < addresses->AddressCount ; i++)
978 {
979 // Only look at TCP/IP addresses.
980 if(addresses->Address[i].AddressType != NDIS_PROTOCOL_ID_TCP_IP)
981 {
982 continue;
983 }
984
985 NETWORK_ADDRESS_IP* pIpAddr =
986 (NETWORK_ADDRESS_IP*)&(addresses->Address[i].Address);
987 struct in_addr in;
988 in.S_un.S_addr = pIpAddr->in_addr;
989 if(pIpAddr->in_addr == name->sin_addr.S_un.S_addr)
990 {
991 filterSourceAddress = pIpAddr->in_addr;
992 addrFound = true;
993 }
994 }
995 if(!addrFound)
996 {
997 continue;
998 } else
999 {
1000 break;
1001 }
1002 }
1003 if(!addrFound)
1004 {
1005 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
1006 "QOS faild since address is not found");
1007 _gtc->TcDeregisterClient(ClientHandle);
1008 free(pInterfaceBuffer);
1009 return -1;
1010 }
1011 result = _gtc->TcOpenInterfaceW(oneinterface->pInterfaceName, ClientHandle,
1012 NULL, &ifcHandle);
1013 if(result != NO_ERROR)
1014 {
1015 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
1016 "Error opening interface: %d", result);
1017 _gtc->TcDeregisterClient(ClientHandle);
1018 free(pInterfaceBuffer);
1019 return result;
1020 }
1021
1022 // Create flow if one doesn't exist.
1023 if (!_flow)
1024 {
1025 bool addPCP = ((pcp >= 0) || ((-1 == pcp) && (_pcp >= 0)));
1026 int allocSize = sizeof(TC_GEN_FLOW) + sizeof(QOS_DS_CLASS) +
1027 (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1028 _flow = (PTC_GEN_FLOW)malloc(allocSize);
1029
1030 _flow->SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
1031 _flow->SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
1032 _flow->SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
1033 _flow->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
1034 _flow->SendingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
1035 _flow->SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
1036 _flow->SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
1037 _flow->SendingFlowspec.TokenRate = QOS_NOT_SPECIFIED;
1038
1039 _flow->ReceivingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
1040 _flow->ReceivingFlowspec.Latency = QOS_NOT_SPECIFIED;
1041 _flow->ReceivingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
1042 _flow->ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
1043 _flow->ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
1044 _flow->ReceivingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
1045 _flow->ReceivingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
1046 _flow->ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED;
1047
1048 QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1049 dsClass->DSField = 0;
1050 dsClass->ObjectHdr.ObjectType = QOS_OBJECT_DS_CLASS;
1051 dsClass->ObjectHdr.ObjectLength = sizeof(QOS_DS_CLASS);
1052
1053 if (addPCP)
1054 {
1055 QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1);
1056 trafficClass->TrafficClass = 0;
1057 trafficClass->ObjectHdr.ObjectType = QOS_OBJECT_TRAFFIC_CLASS;
1058 trafficClass->ObjectHdr.ObjectLength = sizeof(QOS_TRAFFIC_CLASS);
1059 }
1060
1061 _flow->TcObjectsLength = sizeof(QOS_DS_CLASS) +
1062 (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1063 } else if (-1 != pcp) {
1064 // Reallocate memory since pcp has changed.
1065 PTC_GEN_FLOW oldFlow = _flow;
1066 bool addPCP = (pcp >= 0);
1067 int allocSize = sizeof(TC_GEN_FLOW) + sizeof(QOS_DS_CLASS) +
1068 (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1069 _flow = (PTC_GEN_FLOW)malloc(allocSize);
1070
1071 // Copy old flow.
1072 _flow->ReceivingFlowspec = oldFlow->ReceivingFlowspec;
1073 _flow->SendingFlowspec = oldFlow->SendingFlowspec;
1074 // The DS info is always the first object.
1075 QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1076 QOS_DS_CLASS* oldDsClass = (QOS_DS_CLASS*)oldFlow->TcObjects;
1077 dsClass->DSField = oldDsClass->DSField;
1078 dsClass->ObjectHdr.ObjectType = oldDsClass->ObjectHdr.ObjectType;
1079 dsClass->ObjectHdr.ObjectLength = oldDsClass->ObjectHdr.ObjectLength;
1080
1081 if (addPCP)
1082 {
1083 QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1);
1084 trafficClass->TrafficClass = 0;
1085 trafficClass->ObjectHdr.ObjectType = QOS_OBJECT_TRAFFIC_CLASS;
1086 trafficClass->ObjectHdr.ObjectLength = sizeof(QOS_TRAFFIC_CLASS);
1087 }
1088
1089 _flow->TcObjectsLength = sizeof(QOS_DS_CLASS) +
1090 (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1091 free(oldFlow);
1092 }
1093
1094 // Setup send and receive flow and DS object.
1095 if (dscp >= 0)
1096 {
1097 if (!send || (0 == dscp))
1098 {
1099 _flow->SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
1100 _flow->SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
1101 _flow->SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
1102 _flow->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
1103 _flow->SendingFlowspec.PeakBandwidth =
1104 (0 == dscp ? QOS_NOT_SPECIFIED : POSITIVE_INFINITY_RATE);
1105 _flow->SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
1106 _flow->SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
1107 // 128000 * 10 is 10mbit/s.
1108 _flow->SendingFlowspec.TokenRate =
1109 (0 == dscp ? QOS_NOT_SPECIFIED : 128000 * 10);
1110 }
1111 else
1112 {
1113 _flow->SendingFlowspec.DelayVariation = send->DelayVariation;
1114 _flow->SendingFlowspec.Latency = send->Latency;
1115 _flow->SendingFlowspec.MaxSduSize = send->MaxSduSize;
1116 _flow->SendingFlowspec.MinimumPolicedSize =
1117 send->MinimumPolicedSize;
1118 _flow->SendingFlowspec.PeakBandwidth = send->PeakBandwidth;
1119 _flow->SendingFlowspec.PeakBandwidth = POSITIVE_INFINITY_RATE;
1120 _flow->SendingFlowspec.ServiceType = send->ServiceType;
1121 _flow->SendingFlowspec.TokenBucketSize = send->TokenBucketSize;
1122 _flow->SendingFlowspec.TokenRate = send->TokenRate;
1123 }
1124
1125 if (!recv || (0 == dscp))
1126 {
1127 _flow->ReceivingFlowspec.DelayVariation =
1128 _flow->SendingFlowspec.DelayVariation;
1129 _flow->ReceivingFlowspec.Latency = _flow->SendingFlowspec.Latency;
1130 _flow->ReceivingFlowspec.MaxSduSize =
1131 _flow->SendingFlowspec.MaxSduSize;
1132 _flow->ReceivingFlowspec.MinimumPolicedSize =
1133 _flow->SendingFlowspec.MinimumPolicedSize;
1134 _flow->ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
1135 _flow->ReceivingFlowspec.ServiceType =
1136 0 == dscp ? SERVICETYPE_BESTEFFORT : SERVICETYPE_CONTROLLEDLOAD;
1137 _flow->ReceivingFlowspec.TokenBucketSize =
1138 _flow->SendingFlowspec.TokenBucketSize;
1139 _flow->ReceivingFlowspec.TokenRate =
1140 _flow->SendingFlowspec.TokenRate;
1141 } else {
1142 _flow->ReceivingFlowspec.DelayVariation = recv->DelayVariation;
1143 _flow->ReceivingFlowspec.Latency = recv->Latency;
1144 _flow->ReceivingFlowspec.MaxSduSize = recv->MaxSduSize;
1145 _flow->ReceivingFlowspec.MinimumPolicedSize =
1146 recv->MinimumPolicedSize;
1147 _flow->ReceivingFlowspec.PeakBandwidth = recv->PeakBandwidth;
1148 _flow->ReceivingFlowspec.ServiceType = recv->ServiceType;
1149 _flow->ReceivingFlowspec.TokenBucketSize = recv->TokenBucketSize;
1150 _flow->ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED;
1151 }
1152
1153 // Setup DS (for DSCP value).
1154 // DS is always the first object.
1155 QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1156 dsClass->DSField = dscp;
1157 }
1158
1159 // Setup PCP (802.1p priority in 802.1Q/VLAN tagging)
1160 if (pcp >= 0)
1161 {
1162 // DS is always first object.
1163 QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1164 QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1);
1165 trafficClass->TrafficClass = pcp;
1166 }
1167
1168 result = _gtc->TcAddFlow(ifcHandle, NULL, 0, _flow, &iflowHandle);
1169 if(result != NO_ERROR)
1170 {
1171 _gtc->TcCloseInterface(ifcHandle);
1172 _gtc->TcDeregisterClient(ClientHandle);
1173 free(pInterfaceBuffer);
1174 return -1;
1175 }
1176
1177 IP_PATTERN filterPattern, mask;
1178
1179 ZeroMemory((int8_t*)&filterPattern, sizeof(IP_PATTERN));
1180 ZeroMemory((int8_t*)&mask, sizeof(IP_PATTERN));
1181
1182 filterPattern.ProtocolId = IPPROTO_UDP;
1183 // "name" fields already in network order.
1184 filterPattern.S_un.S_un_ports.s_srcport = name->sin_port;
1185 filterPattern.SrcAddr = filterSourceAddress;
1186
1187 // Unsigned max of a type corresponds to a bitmask with all bits set to 1.
1188 // I.e. the filter should allow all ProtocolIds, any source port and any
1189 // IP address
1190 mask.ProtocolId = UCHAR_MAX;
1191 mask.S_un.S_un_ports.s_srcport = USHRT_MAX;
1192 mask.SrcAddr = ULONG_MAX;
1193
1194 TC_GEN_FILTER filter;
1195
1196 filter.AddressType = NDIS_PROTOCOL_ID_TCP_IP;
1197 filter.Mask = (LPVOID)&mask;
1198 filter.Pattern = (LPVOID)&filterPattern;
1199 filter.PatternSize = sizeof(IP_PATTERN);
1200
1201 result = _gtc->TcAddFilter(iflowHandle, &filter, &iFilterHandle);
1202 if(result != NO_ERROR)
1203 {
1204 _gtc->TcDeleteFlow(iflowHandle);
1205 _gtc->TcCloseInterface(ifcHandle);
1206 _gtc->TcDeregisterClient(ClientHandle);
1207 free(pInterfaceBuffer);
1208 return result;
1209 }
1210
1211 _flowHandle = iflowHandle;
1212 _filterHandle = iFilterHandle;
1213 _clientHandle = ClientHandle;
1214 if (-1 != pcp)
1215 {
1216 _pcp = pcp;
1217 }
1218
1219 _gtc->TcCloseInterface(ifcHandle);
1220 free(pInterfaceBuffer);
1221
1222 return 0;
1223 }
1224
1225 int32_t UdpSocket2Windows::CreateFlowSpec(int32_t serviceType,
1226 int32_t tokenRate,
1227 int32_t bucketSize,
1228 int32_t peekBandwith,
1229 int32_t minPolicedSize,
1230 int32_t maxSduSize,
1231 FLOWSPEC* f)
1232 {
1233 if (!f)
1234 {
1235 return -1;
1236 }
1237
1238 f->ServiceType = serviceType;
1239 f->TokenRate = tokenRate;
1240 f->TokenBucketSize = QOS_NOT_SPECIFIED;
1241 f->PeakBandwidth = QOS_NOT_SPECIFIED;
1242 f->DelayVariation = QOS_NOT_SPECIFIED;
1243 f->Latency = QOS_NOT_SPECIFIED;
1244 f->MaxSduSize = QOS_NOT_SPECIFIED;
1245 f->MinimumPolicedSize = QOS_NOT_SPECIFIED;
1246 return 0;
1247 }
1248
1249 bool UdpSocket2Windows::NewOutstandingCall()
1250 {
1251 assert(!_outstandingCallsDisabled);
1252
1253 ++_outstandingCalls;
1254 return true;
1255 }
1256
1257 void UdpSocket2Windows::OutstandingCallCompleted()
1258 {
1259 _ptrDestRWLock->AcquireLockShared();
1260 ++_outstandingCallComplete;
1261 if((--_outstandingCalls == 0) && _outstandingCallsDisabled)
1262 {
1263 // When there are no outstanding calls and new outstanding calls are
1264 // disabled it is time to terminate.
1265 _terminate = true;
1266 }
1267 _ptrDestRWLock->ReleaseLockShared();
1268
1269 if((--_outstandingCallComplete == 0) &&
1270 (_terminate))
1271 {
1272 // Only one thread will enter here. The thread with the last outstanding
1273 // call.
1274 delete_event_.Set();
1275 }
1276 }
1277
1278 void UdpSocket2Windows::DisableNewOutstandingCalls()
1279 {
1280 _ptrDestRWLock->AcquireLockExclusive();
1281 if(_outstandingCallsDisabled)
1282 {
1283 // Outstandning calls are already disabled.
1284 _ptrDestRWLock->ReleaseLockExclusive();
1285 return;
1286 }
1287 _outstandingCallsDisabled = true;
1288 const bool noOutstandingCalls = (_outstandingCalls.Value() == 0);
1289 _ptrDestRWLock->ReleaseLockExclusive();
1290
1291 RemoveSocketFromManager();
1292
1293 if(noOutstandingCalls)
1294 {
1295 delete_event_.Set();
1296 }
1297 }
1298
1299 void UdpSocket2Windows::RemoveSocketFromManager()
1300 {
1301 // New outstanding calls should be disabled at this point.
1302 assert(_outstandingCallsDisabled);
1303
1304 if(_addedToMgr)
1305 {
1306 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
1307 "calling UdpSocketManager::RemoveSocket()");
1308 if(_mgr->RemoveSocket(this))
1309 {
1310 _addedToMgr=false;
1311 }
1312 }
1313 }
1314
1315 bool UdpSocket2Windows::AquireSocket()
1316 {
1317 _ptrSocketRWLock->AcquireLockShared();
1318 const bool returnValue = _socket != INVALID_SOCKET;
1319 if(!returnValue)
1320 {
1321 _ptrSocketRWLock->ReleaseLockShared();
1322 }
1323 return returnValue;
1324 }
1325
1326 void UdpSocket2Windows::ReleaseSocket()
1327 {
1328 _ptrSocketRWLock->ReleaseLockShared();
1329 }
1330
1331 bool UdpSocket2Windows::InvalidateSocket()
1332 {
1333 _ptrSocketRWLock->AcquireLockExclusive();
1334 if(_socket == INVALID_SOCKET)
1335 {
1336 _ptrSocketRWLock->ReleaseLockExclusive();
1337 return true;
1338 }
1339 // Give the socket back to the system. All socket calls will fail from now
1340 // on.
1341 if(closesocket(_socket) == SOCKET_ERROR)
1342 {
1343 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
1344 "UdpSocket2Windows(%d)::InvalidateSocket() WSAerror: %d",
1345 (int32_t)this, WSAGetLastError());
1346 }
1347 _socket = INVALID_SOCKET;
1348 _ptrSocketRWLock->ReleaseLockExclusive();
1349 return true;
1350 }
1351
1352 } // namespace test
1353 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/test/channel_transport/udp_socket2_win.h ('k') | webrtc/test/channel_transport/udp_socket_manager_posix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698