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/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 
     23 namespace webrtc {
     24 namespace test {
     25 
     26 typedef struct _QOS_DESTADDR
     27 {
     28     QOS_OBJECT_HDR ObjectHdr;
     29     const struct sockaddr* SocketAddress;
     30     ULONG SocketAddressLength;
     31 } QOS_DESTADDR, *LPQOS_DESTADDR;
     32 
     33 typedef 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 
     42 UdpSocket2Windows::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 
    182 UdpSocket2Windows::~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 
    218 int32_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 
    228 bool UdpSocket2Windows::ValidHandle()
    229 {
    230     return GetFd() != INVALID_SOCKET;
    231 }
    232 
    233 bool 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 
    266 bool 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 
    286 bool 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 
    324 bool UdpSocket2Windows::StopReceiving()
    325 {
    326     WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
    327                  "UdpSocket2Windows::StopReceiving()");
    328     _wantsIncoming = false;
    329     return true;
    330 }
    331 
    332 bool 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 
    352 int32_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 
    445 void 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 
    553 int32_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 
    569 int32_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 
    668 void 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 
    690 bool 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 
    824 int32_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 
    856 int32_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 
    870 int32_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 
   1249 int32_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 
   1273 bool UdpSocket2Windows::NewOutstandingCall()
   1274 {
   1275     assert(!_outstandingCallsDisabled);
   1276 
   1277     ++_outstandingCalls;
   1278     return true;
   1279 }
   1280 
   1281 void 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 
   1304 void 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 
   1327 void UdpSocket2Windows::WaitForOutstandingCalls()
   1328 {
   1329     CriticalSectionScoped cs(_ptrDeleteCrit);
   1330     while(!_safeTodelete)
   1331     {
   1332         _ptrDeleteCond->SleepCS(*_ptrDeleteCrit);
   1333     }
   1334 }
   1335 
   1336 void 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 
   1352 bool 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 
   1363 void UdpSocket2Windows::ReleaseSocket()
   1364 {
   1365     _ptrSocketRWLock->ReleaseLockShared();
   1366 }
   1367 
   1368 bool 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