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