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