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/voice_engine/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/voice_engine/test/channel_transport/traffic_control_win.h"
20 #include "webrtc/voice_engine/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       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 
~UdpSocket2Windows()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 
ValidHandle()212 bool UdpSocket2Windows::ValidHandle()
213 {
214     return GetFd() != INVALID_SOCKET;
215 }
216 
SetCallback(CallbackObj obj,IncomingSocketCallback cb)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 
SetSockopt(int32_t level,int32_t optname,const int8_t * optval,int32_t optlen)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 
StartReceiving(uint32_t receiveBuffers)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 
StopReceiving()308 bool UdpSocket2Windows::StopReceiving()
309 {
310     WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
311                  "UdpSocket2Windows::StopReceiving()");
312     _wantsIncoming = false;
313     return true;
314 }
315 
Bind(const SocketAddress & name)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 
SendTo(const int8_t * buf,size_t len,const SocketAddress & to)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 
IOCompleted(PerIoContext * pIOContext,uint32_t ioSize,uint32_t error)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 
PostRecv()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 
PostRecv(PerIoContext * pIoContext)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 
CloseBlocking()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 
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)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 
SetTOS(int32_t serviceType)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 
SetPCP(int32_t pcp)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 
SetTrafficControl(int32_t dscp,int32_t pcp,const struct sockaddr_in * name,FLOWSPEC * send,FLOWSPEC * recv)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 
CreateFlowSpec(int32_t serviceType,int32_t tokenRate,int32_t bucketSize,int32_t peekBandwith,int32_t minPolicedSize,int32_t maxSduSize,FLOWSPEC * f)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 
NewOutstandingCall()1249 bool UdpSocket2Windows::NewOutstandingCall()
1250 {
1251     assert(!_outstandingCallsDisabled);
1252 
1253     ++_outstandingCalls;
1254     return true;
1255 }
1256 
OutstandingCallCompleted()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 
DisableNewOutstandingCalls()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 
RemoveSocketFromManager()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 
AquireSocket()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 
ReleaseSocket()1326 void UdpSocket2Windows::ReleaseSocket()
1327 {
1328     _ptrSocketRWLock->ReleaseLockShared();
1329 }
1330 
InvalidateSocket()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
1354