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