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