1999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org/*
2999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org *
4999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org *  Use of this source code is governed by a BSD-style license
5999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org *  that can be found in the LICENSE file in the root of the source
6999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org *  tree. An additional intellectual property rights grant can be found
7999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org *  in the file PATENTS.  All contributing project authors may
8999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org */
10999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
11999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#include "webrtc/test/channel_transport/udp_socket2_win.h"
12999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
13999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#include <assert.h>
14999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#include <stdlib.h>
15999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#include <winsock2.h>
16999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
174591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org#include "webrtc/base/format_macros.h"
1898f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/sleep.h"
19999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#include "webrtc/test/channel_transport/traffic_control_win.h"
20999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#include "webrtc/test/channel_transport/udp_socket2_manager_win.h"
21999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
22999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#pragma warning(disable : 4311)
23999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
24999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgnamespace webrtc {
25999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgnamespace test {
26999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
27999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgtypedef struct _QOS_DESTADDR
28999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
29999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    QOS_OBJECT_HDR ObjectHdr;
30999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    const struct sockaddr* SocketAddress;
31999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ULONG SocketAddressLength;
32999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org} QOS_DESTADDR, *LPQOS_DESTADDR;
33999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
34999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgtypedef const QOS_DESTADDR* LPCQOS_DESTADDR;
35999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
36999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org// TODO (patrikw): seems to be defined in ws2ipdef.h as 3. How come it's
37999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//                 redefined here (as a different value)?
38999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#define IP_TOS 8
39999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
40999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#define QOS_GENERAL_ID_BASE 2000
41999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org#define QOS_OBJECT_DESTADDR (0x00000004 + QOS_GENERAL_ID_BASE)
42999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
43a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgUdpSocket2Windows::UdpSocket2Windows(const int32_t id,
44999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                                     UdpSocketManager* mgr, bool ipV6Enable,
45999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                                     bool disableGQOS)
46999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    : _id(id),
47999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _qos(true),
48999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _iProtocol(0),
49999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _outstandingCalls(0),
50999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _outstandingCallComplete(0),
51999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _terminate(false),
52999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _addedToMgr(false),
53999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _safeTodelete(false),
54999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _outstandingCallsDisabled(false),
55999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _clientHandle(NULL),
56999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _flowHandle(NULL),
57999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _filterHandle(NULL),
58999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _flow(NULL),
59999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _gtc(NULL),
60999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _pcp(-2),
61999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      _receiveBuffers(0)
62999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
63999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id,
64999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                 "UdpSocket2Windows::UdpSocket2Windows()");
65999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
66999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _wantsIncoming = false;
67999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _mgr = static_cast<UdpSocket2ManagerWindows *>(mgr);
68999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
69999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _obj = NULL;
70999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _incomingCb = NULL;
71999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _socket = INVALID_SOCKET;
72999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _pCrit = CriticalSectionWrapper::CreateCriticalSection();
73999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrCbRWLock     = RWLockWrapper::CreateRWLock();
74999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrDestRWLock   = RWLockWrapper::CreateRWLock();
75999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrSocketRWLock = RWLockWrapper::CreateRWLock();
76999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrDeleteCrit   = CriticalSectionWrapper::CreateCriticalSection();
77999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrDeleteCond   = ConditionVariableWrapper::CreateConditionVariable();
78999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
79999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Check if QoS is supported.
80999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    BOOL bProtocolFound = FALSE;
81999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WSAPROTOCOL_INFO *lpProtocolBuf = NULL;
82999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WSAPROTOCOL_INFO    pProtocolInfo;
83999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
84999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!disableGQOS)
85999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
86999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        DWORD dwBufLen = 0;
87999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Set dwBufLen to the size needed to retreive all the requested
88999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // information from WSAEnumProtocols.
89a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org        int32_t nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
90999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        lpProtocolBuf = (WSAPROTOCOL_INFO*)malloc(dwBufLen);
91999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);
92999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
93999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if (ipV6Enable)
94999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
95999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _iProtocol=AF_INET6;
96999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        } else {
97999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _iProtocol=AF_INET;
98999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
99999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
100a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org        for (int32_t i=0; i<nRet; i++)
101999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
102999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if (_iProtocol == lpProtocolBuf[i].iAddressFamily &&
103999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                IPPROTO_UDP == lpProtocolBuf[i].iProtocol)
104999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
105999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                if ((XP1_QOS_SUPPORTED ==
106999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     (XP1_QOS_SUPPORTED & lpProtocolBuf[i].dwServiceFlags1)))
107999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                {
108999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    pProtocolInfo = lpProtocolBuf[i];
109999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    bProtocolFound = TRUE;
110999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    break;
111999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                }
112999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
113999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org         }
114999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
115999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
116999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!bProtocolFound)
117999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
118999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(lpProtocolBuf);
119999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _qos=false;
120999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
121999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceError,
122999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceTransport,
123999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _id,
124999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR_NO_QOS,\
125999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org !bProtocolFound");
126999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    } else {
127999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
128999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _socket = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
129999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                            FROM_PROTOCOL_INFO,&pProtocolInfo, 0,
130999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                            WSA_FLAG_OVERLAPPED);
131999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(lpProtocolBuf);
132999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
133999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if (_socket != INVALID_SOCKET)
134999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
135999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            return;
136999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        } else {
137999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _qos = false;
138999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            WEBRTC_TRACE(
139999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                kTraceError,
140999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                kTraceTransport,
141999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                _id,
142999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR_NO_QOS");
143999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
144999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
145999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // QoS not supported.
146999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(ipV6Enable)
147999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
148999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _socket = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, 0 , 0,
149999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                            WSA_FLAG_OVERLAPPED);
150999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }else
151999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
152999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0 , 0,
153999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                            WSA_FLAG_OVERLAPPED);
154999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
155999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (_socket == INVALID_SOCKET)
156999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
157999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
158999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceError,
159999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceTransport,
160999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _id,
161999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            "UdpSocket2Windows::UdpSocket2Windows(), INVALID_SOCKET,\
162999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org WSAerror: %d",
163999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            WSAGetLastError());
164999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
165999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
166999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Disable send buffering on the socket to improve CPU usage.
167999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // This is done by setting SO_SNDBUF to 0.
168a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t nZero = 0;
169a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t nRet = setsockopt(_socket, SOL_SOCKET, SO_SNDBUF,
170a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                              (char*)&nZero, sizeof(nZero));
171999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if( nRet == SOCKET_ERROR )
172999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
173999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
174999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceError,
175999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceTransport,
176999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _id,
177999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR,\
178999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org WSAerror: %d",
179999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            WSAGetLastError());
180999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
181999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
182999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
183999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgUdpSocket2Windows::~UdpSocket2Windows()
184999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
185999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id,
186999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                 "UdpSocket2Windows::~UdpSocket2Windows()");
187999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
188999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WaitForOutstandingCalls();
189999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
190999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    delete _ptrCbRWLock;
191999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    delete _ptrDeleteCrit;
192999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    delete _ptrDeleteCond;
193999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    delete _ptrDestRWLock;
194999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    delete _ptrSocketRWLock;
195999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
196999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_pCrit)
197999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        delete _pCrit;
198999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
199999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (_flow)
200999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
201999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(_flow);
202999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow = NULL;
203999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
204999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
205999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (_gtc)
206999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
207999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(_filterHandle)
208999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
209999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _gtc->TcDeleteFilter(_filterHandle);
210999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
211999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(_flowHandle)
212999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
213999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _gtc->TcDeleteFlow(_flowHandle);
214999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
215999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        TrafficControlWindows::Release( _gtc);
216999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
217999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
218999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
219999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgbool UdpSocket2Windows::ValidHandle()
220999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
221999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return GetFd() != INVALID_SOCKET;
222999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
223999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
224999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgbool UdpSocket2Windows::SetCallback(CallbackObj obj, IncomingSocketCallback cb)
225999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
226999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrCbRWLock->AcquireLockExclusive();
227999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _obj = obj;
228999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _incomingCb = cb;
229999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrCbRWLock->ReleaseLockExclusive();
230999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
231999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
232a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                 "UdpSocket2Windows(%d)::SetCallback ",(int32_t)this);
233999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_addedToMgr)
234999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
235999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
236999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows(%d)::SetCallback alreadey added",
237a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                     (int32_t) this);
238999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return false;
239999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
240999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
241999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (_mgr->AddSocket(this))
242999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
243999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
244999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceDebug, kTraceTransport, _id,
245999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            "UdpSocket2Windows(%d)::SetCallback socket added to manager",
246a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org            (int32_t)this);
247999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _addedToMgr = true;
248999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return true;
249999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
250999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
251999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
252999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                 "UdpSocket2Windows(%d)::SetCallback error adding me to mgr",
253a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                 (int32_t) this);
254999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return false;
255999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
256999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
257a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgbool UdpSocket2Windows::SetSockopt(int32_t level, int32_t optname,
258a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                   const int8_t* optval, int32_t optlen)
259999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
260999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    bool returnValue = true;
261999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!AquireSocket())
262999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
263999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return false;
264999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
265999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(0 != setsockopt(_socket, level, optname,
266999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                       reinterpret_cast<const char*>(optval), optlen ))
267999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
268999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
269999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows::SetSockopt(), WSAerror:%d",
270999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     WSAGetLastError());
271999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        returnValue = false;
272999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
273999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ReleaseSocket();
274999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return returnValue;
275999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
276999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
277a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgbool UdpSocket2Windows::StartReceiving(uint32_t receiveBuffers)
278999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
279999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
280a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                 "UdpSocket2Windows(%d)::StartReceiving(%d)", (int32_t)this,
281a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                 receiveBuffers);
282999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
283999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _wantsIncoming = true;
284999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
285a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t numberOfReceiveBuffersToCreate =
286999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        receiveBuffers - _receiveBuffers.Value();
287999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    numberOfReceiveBuffersToCreate = (numberOfReceiveBuffersToCreate < 0) ?
288999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        0 : numberOfReceiveBuffersToCreate;
289999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
290a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t error = 0;
291a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    for(int32_t i = 0;
292999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        i < numberOfReceiveBuffersToCreate;
293999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        i++)
294999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
295999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(PostRecv())
296999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
297999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
298999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                         "UdpSocket2Windows::StartReceiving() i=%d", i);
299999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            error = -1;
300999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            break;
301999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
302999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        ++_receiveBuffers;
303999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
304999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(error == -1)
305999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
306999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return false;
307999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
308999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
309999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
310999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                 "Socket receiving using:%d number of buffers",
311999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                 _receiveBuffers.Value());
312999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return true;
313999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
314999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
315999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgbool UdpSocket2Windows::StopReceiving()
316999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
317999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
318999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                 "UdpSocket2Windows::StopReceiving()");
319999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _wantsIncoming = false;
320999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return true;
321999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
322999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
323999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgbool UdpSocket2Windows::Bind(const SocketAddress& name)
324999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
325999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    const struct sockaddr* addr =
326999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        reinterpret_cast<const struct sockaddr*>(&name);
327999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    bool returnValue = true;
328999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!AquireSocket())
329999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
330999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return false;
331999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
332999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (0 != bind(_socket, addr, sizeof(SocketAddress)))
333999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
334999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
335999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows::Bind() WSAerror: %d",
336999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     WSAGetLastError());
337999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        returnValue = false;
338999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
339999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ReleaseSocket();
340999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return returnValue;
341999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
342999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
3434591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgint32_t UdpSocket2Windows::SendTo(const int8_t* buf, size_t len,
344a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                  const SocketAddress& to)
345999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
346a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t retVal = 0;
347a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t error = 0;
348999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    PerIoContext* pIoContext = _mgr->PopIoContext();
349999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(pIoContext == 0)
350999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
351999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
352999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows(%d)::SendTo(), pIoContext==0",
353a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                     (int32_t) this);
354999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
355999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
356999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // sizeof(pIoContext->buffer) is smaller than the highest number that
3574591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    // can be represented by a size_t.
3584591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    if(len >= sizeof(pIoContext->buffer))
359999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
360999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
361999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceError,
362999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceTransport,
363999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _id,
3644591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org            "UdpSocket2Windows(%d)::SendTo(), len= %" PRIuS
3654591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org            " > buffer_size = %d",
366a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org            (int32_t) this,
367999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            len,sizeof(pIoContext->buffer));
368999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        len = sizeof(pIoContext->buffer);
369999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
370999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
371999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    memcpy(pIoContext->buffer,buf,len);
372999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->wsabuf.buf = pIoContext->buffer;
3734591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    pIoContext->wsabuf.len = static_cast<ULONG>(len);
374999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->fromLen=sizeof(SocketAddress);
375999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->ioOperation = OP_WRITE;
376999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->nTotalBytes = len;
377999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->nSentBytes=0;
378999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
379999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    DWORD numOfbytesSent = 0;
380999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    const struct sockaddr* addr = reinterpret_cast<const struct sockaddr*>(&to);
381999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
382999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!AquireSocket())
383999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
384999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _mgr->PushIoContext(pIoContext);
385999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
386999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
387999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Assume that the WSASendTo call will be successfull to make sure that
388999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // _outstandingCalls is positive. Roll back if WSASendTo failed.
389999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!NewOutstandingCall())
390999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
391999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _mgr->PushIoContext(pIoContext);
392999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        ReleaseSocket();
393999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
394999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
395999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    retVal = WSASendTo(_socket, &pIoContext->wsabuf, 1, &numOfbytesSent,
396999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                       0, addr, sizeof(SocketAddress),
397999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                       &(pIoContext->overlapped), 0);
398999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ReleaseSocket();
399999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
400999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if( retVal == SOCKET_ERROR  )
401999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
402999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        error =  WSAGetLastError();
403999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(error != ERROR_IO_PENDING)
404999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
405999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
406999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                         "UdpSocket2Windows::SendTo() WSAerror: %d",error);
407999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
408999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
409999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(retVal == 0 || (retVal == SOCKET_ERROR && error == ERROR_IO_PENDING))
410999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
4114591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org        return static_cast<int32_t>(len);
412999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
4136ac22e6b47f9a6ed70b0a376984b39b9a745dd94henrike@webrtc.org    error = _mgr->PushIoContext(pIoContext);
4146ac22e6b47f9a6ed70b0a376984b39b9a745dd94henrike@webrtc.org    if(error)
415999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
416999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
417999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceError,
418999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceTransport,
419999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _id,
420999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            "UdpSocket2Windows(%d)::SendTo(), error:%d pushing ioContext",
421a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org            (int32_t)this, error);
422999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
423999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
424999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Roll back.
425999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    OutstandingCallCompleted();
426999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return -1;
427999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
428999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
429999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgvoid UdpSocket2Windows::IOCompleted(PerIoContext* pIOContext,
430a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                    uint32_t ioSize, uint32_t error)
431999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
432999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(pIOContext == NULL || error == ERROR_OPERATION_ABORTED)
433999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
434999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if ((pIOContext != NULL) &&
43512411ef40e08c5e28ccde54ab3418c96676ffcbcpbos            !pIOContext->ioInitiatedByPlatformThread &&
436999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            (error == ERROR_OPERATION_ABORTED) &&
437999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            (pIOContext->ioOperation == OP_READ) &&
438999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _outstandingCallsDisabled)
439999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
44012411ef40e08c5e28ccde54ab3418c96676ffcbcpbos            // !pIOContext->initiatedIOByPlatformThread indicate that the I/O
44112411ef40e08c5e28ccde54ab3418c96676ffcbcpbos            // was not initiated by a PlatformThread thread.
442999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // This may happen if the thread that initiated receiving (e.g.
443999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // by calling StartListen())) is deleted before any packets have
444999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // been received.
445999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // In this case there is no packet in the PerIoContext. Re-use it
446999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // to post a new PostRecv(..).
447999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // Note 1: the PerIoContext will henceforth be posted by a thread
448999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            //         that is controlled by the socket implementation.
449999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // Note 2: This is more likely to happen to RTCP packets as
450999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            //         they are less frequent than RTP packets.
451999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // Note 3: _outstandingCallsDisabled being false indicates
452999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            //         that the socket isn't being shut down.
453999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // Note 4: This should only happen buffers set to receive packets
454999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            //         (OP_READ).
455999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        } else {
456999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if(pIOContext == NULL)
457999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
458999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                WEBRTC_TRACE(
459999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    kTraceError,
460999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    kTraceTransport,
461999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    _id,
462999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    "UdpSocket2Windows::IOCompleted(%d,%d,%d), %d",
463a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                    (int32_t)pIOContext,
464999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    ioSize,
465999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    error,
466a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                    pIOContext ? (int32_t)pIOContext->ioOperation : -1);
467999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            } else {
468999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                WEBRTC_TRACE(
469999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    kTraceDebug,
470999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    kTraceTransport,
471999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    _id,
472999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    "UdpSocket2Windows::IOCompleted() Operation aborted");
473999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
474999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if(pIOContext)
475999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
476a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                int32_t remainingReceiveBuffers = --_receiveBuffers;
477999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                if(remainingReceiveBuffers < 0)
478999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                {
479999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    assert(false);
480999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                }
4816ac22e6b47f9a6ed70b0a376984b39b9a745dd94henrike@webrtc.org                int32_t err = _mgr->PushIoContext(pIOContext);
4826ac22e6b47f9a6ed70b0a376984b39b9a745dd94henrike@webrtc.org                if(err)
483999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                {
484999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    WEBRTC_TRACE(
485999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                        kTraceError,
486999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                        kTraceTransport,
487999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                        _id,
488999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                        "UdpSocket2Windows::IOCompleted(), err = %d, when\
489999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org pushing ioContext after error",
490999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                        err);
491999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                }
492999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
493999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            OutstandingCallCompleted();
494999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            return;
495999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
496d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org    }  // if (pIOContext == NULL || error == ERROR_OPERATION_ABORTED)
497999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
498999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(pIOContext->ioOperation == OP_WRITE)
499999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
500999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _mgr->PushIoContext(pIOContext);
501999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
502999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    else if(pIOContext->ioOperation == OP_READ)
503999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
504999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(!error && ioSize != 0)
505999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
506999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _ptrCbRWLock->AcquireLockShared();
507999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if(_wantsIncoming && _incomingCb)
508999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
509999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                _incomingCb(_obj,
510a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                            reinterpret_cast<const int8_t*>(
511999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                                pIOContext->wsabuf.buf),
512999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                            ioSize,
513999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                            &pIOContext->from);
514999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
515999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _ptrCbRWLock->ReleaseLockShared();
516999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
517a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org        int32_t err = PostRecv(pIOContext);
518999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(err == 0)
519999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
520999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // The PerIoContext was posted by a thread controlled by the socket
521999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // implementation.
52212411ef40e08c5e28ccde54ab3418c96676ffcbcpbos            pIOContext->ioInitiatedByPlatformThread = true;
523999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
524999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        OutstandingCallCompleted();
525999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return;
526999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    } else {
527999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Unknown operation. Should not happen. Return pIOContext to avoid
528999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // memory leak.
529999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        assert(false);
530999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _mgr->PushIoContext(pIOContext);
531999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
532999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    OutstandingCallCompleted();
533999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Don't touch any members after OutstandingCallCompleted() since the socket
534999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // may be deleted at this point.
535999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
536999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
537a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgint32_t UdpSocket2Windows::PostRecv()
538999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
539999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    PerIoContext* pIoContext=_mgr->PopIoContext();
540999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(pIoContext == 0)
541999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
542999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
543999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows(%d)::PostRecv(), pIoContext == 0",
544a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                     (int32_t)this);
545999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
546999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
547999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // This function may have been called by thread not controlled by the socket
548999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // implementation.
54912411ef40e08c5e28ccde54ab3418c96676ffcbcpbos    pIoContext->ioInitiatedByPlatformThread = false;
550999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return PostRecv(pIoContext);
551999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
552999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
553a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgint32_t UdpSocket2Windows::PostRecv(PerIoContext* pIoContext)
554999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
555999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(pIoContext==0)
556999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
557999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
558999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows(%d)::PostRecv(?), pIoContext==0",
559a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                     (int32_t)this);
560999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
561999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
562999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
563999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    DWORD numOfRecivedBytes = 0;
564999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    DWORD flags = 0;
565999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->wsabuf.buf = pIoContext->buffer;
566999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->wsabuf.len = sizeof(pIoContext->buffer);
567999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->fromLen = sizeof(SocketAddress);
568999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    pIoContext->ioOperation = OP_READ;
569a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t rxError = 0;
570a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t nRet = 0;
571a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t postingSucessfull = false;
572999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
573999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!AquireSocket())
574999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
575999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _mgr->PushIoContext(pIoContext);
576999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
577999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
578999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
579999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Assume that the WSARecvFrom() call will be successfull to make sure that
580999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // _outstandingCalls is positive. Roll back if WSARecvFrom() failed.
581999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!NewOutstandingCall())
582999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
583999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _mgr->PushIoContext(pIoContext);
584999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        ReleaseSocket();
585999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
586999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
587a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    for(int32_t tries = 0; tries < 10; tries++)
588999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
589999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        nRet = WSARecvFrom(
590999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _socket,
591999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            &(pIoContext->wsabuf),
592999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            1,
593999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            &numOfRecivedBytes,
594999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            &flags,
595999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            reinterpret_cast<struct sockaddr*>(&(pIoContext->from)),
596999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            &(pIoContext->fromLen),
597999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            &(pIoContext->overlapped),
598999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            0);
599999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
600999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if( nRet == SOCKET_ERROR)
601999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
602999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            rxError = WSAGetLastError();
603999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if(rxError != ERROR_IO_PENDING)
604999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
605999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                WEBRTC_TRACE(
606999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    kTraceError,
607999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    kTraceTransport,
608999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    _id,
609999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    "UdpSocket2Windows(%d)::PostRecv(?), WSAerror:%d when\
610999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org posting new recieve,trie:%d",
611a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                    (int32_t)this,
612999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    rxError,
613999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                    tries);
614999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                // Tell the OS that this is a good place to context switch if
615999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                // it wants to.
616fcb7c38b15319aa021ba55bc3a06a3269ac3ea6fhta@webrtc.org                SleepMs(0);
617999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
618999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
619999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if((rxError == ERROR_IO_PENDING) || (nRet == 0))
620999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
621999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            postingSucessfull = true;
622999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            break;
623999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
624999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
625999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ReleaseSocket();
626999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
627999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(postingSucessfull)
628999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
629999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return 0;
630999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
631a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t remainingReceiveBuffers = --_receiveBuffers;
632999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(remainingReceiveBuffers < 0)
633999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
634999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        assert(false);
635999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
6366ac22e6b47f9a6ed70b0a376984b39b9a745dd94henrike@webrtc.org    int32_t error = _mgr->PushIoContext(pIoContext);
6376ac22e6b47f9a6ed70b0a376984b39b9a745dd94henrike@webrtc.org    if(error)
638999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
639999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
640999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceError,
641999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceTransport,
642999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _id,
643999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            "UdpSocket2Windows(%d)::PostRecv(?), error:%d when PushIoContext",
644a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org            (int32_t)this,
645999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            error);
646999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
647999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Roll back.
648999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    OutstandingCallCompleted();
649999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return -1;
650999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
651999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
652999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgvoid UdpSocket2Windows::CloseBlocking()
653999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
654999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    LINGER  lingerStruct;
655999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
656999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    lingerStruct.l_onoff = 1;
657999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    lingerStruct.l_linger = 0;
658999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(AquireSocket())
659999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
660999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        setsockopt(_socket, SOL_SOCKET, SO_LINGER,
661999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                   reinterpret_cast<const char*>(&lingerStruct),
662999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                   sizeof(lingerStruct));
663999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        ReleaseSocket();
664999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
665999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
666999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _wantsIncoming = false;
667999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Reclaims the socket and prevents it from being used again.
668999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    InvalidateSocket();
669999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    DisableNewOutstandingCalls();
670999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    WaitForOutstandingCalls();
671999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    delete this;
672999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
673999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
674a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgbool UdpSocket2Windows::SetQos(int32_t serviceType,
675a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                               int32_t tokenRate,
676a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                               int32_t bucketSize,
677a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                               int32_t peekBandwith,
678a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                               int32_t minPolicedSize,
679a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                               int32_t maxSduSize,
680999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                               const SocketAddress &stRemName,
681a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                               int32_t overrideDSCP)
682999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
683999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_qos == false)
684999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
685999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
686999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows::SetQos(), socket not capable of QOS");
687999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return false;
688999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
689999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(overrideDSCP != 0)
690999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
691999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        FLOWSPEC f;
692a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org        int32_t err = CreateFlowSpec(serviceType, tokenRate, bucketSize,
693a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                     peekBandwith, minPolicedSize,
694a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                     maxSduSize, &f);
695999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(err == -1)
696999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
697999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            return false;
698999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
699999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
700999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        SocketAddress socketName;
701999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        struct sockaddr_in* name =
702999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            reinterpret_cast<struct sockaddr_in*>(&socketName);
703999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        int nameLength = sizeof(SocketAddress);
704999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(AquireSocket())
705999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
706999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            getsockname(_socket, (struct sockaddr*)name, &nameLength);
707999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            ReleaseSocket();
708999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
709999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
710999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(serviceType == 0)
711999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
712999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // Disable TOS byte setting.
713999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            return SetTrafficControl(0, -1, name, &f, &f) == 0;
714999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
715999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return SetTrafficControl(overrideDSCP, -1, name, &f, &f) == 0;
716999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
717999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
718999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    QOS Qos;
719999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    DWORD BytesRet;
720999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    QOS_DESTADDR QosDestaddr;
721999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
722999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    memset (&Qos, QOS_NOT_SPECIFIED, sizeof(QOS));
723999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
724999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.ServiceType        = serviceType;
725999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.TokenRate          = tokenRate;
726999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.TokenBucketSize    = QOS_NOT_SPECIFIED;
727999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.PeakBandwidth      = QOS_NOT_SPECIFIED;
728999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.DelayVariation     = QOS_NOT_SPECIFIED;
729999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.Latency            = QOS_NOT_SPECIFIED;
730999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
731999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.SendingFlowspec.MaxSduSize         = QOS_NOT_SPECIFIED;
732999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
733999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Only ServiceType is needed for receiving.
734999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.ServiceType        = serviceType;
735999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.TokenRate          = QOS_NOT_SPECIFIED;
736999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.TokenBucketSize    = QOS_NOT_SPECIFIED;
737999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.PeakBandwidth      = QOS_NOT_SPECIFIED;
738999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.Latency            = QOS_NOT_SPECIFIED;
739999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.DelayVariation     = QOS_NOT_SPECIFIED;
740999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
741999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ReceivingFlowspec.MaxSduSize         = QOS_NOT_SPECIFIED;
742999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
743999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ProviderSpecific.len = 0;
744999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
745999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    Qos.ProviderSpecific.buf = NULL;
746999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
747a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    ZeroMemory((int8_t *)&QosDestaddr, sizeof(QosDestaddr));
748999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
749999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    OSVERSIONINFOEX osvie;
750999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    osvie.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
751999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    GetVersionEx((LPOSVERSIONINFO)&osvie);
752999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
753999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Operating system        Version number    dwMajorVersion    dwMinorVersion
754999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows 7                6.1                6                1
755999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows Server 2008 R2   6.1                6                1
756999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows Server 2008      6.0                6                0
757999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows Vista            6.0                6                0
758999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows Server 2003 R2   5.2                5                2
759999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows Server 2003      5.2                5                2
760999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows XP               5.1                5                1
761999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org//    Windows 2000             5.0                5                0
762999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
763999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // SERVICE_NO_QOS_SIGNALING and QOS_DESTADDR should not be used if version
764999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // is 6.0 or greater.
765999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(osvie.dwMajorVersion >= 6)
766999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
767999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        Qos.SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
768999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        Qos.ReceivingFlowspec.ServiceType = serviceType;
769999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
770999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    } else {
771999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        Qos.SendingFlowspec.MinimumPolicedSize =
772999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            QOS_NOT_SPECIFIED | SERVICE_NO_QOS_SIGNALING;
773999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        Qos.ReceivingFlowspec.ServiceType =
774999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            serviceType | SERVICE_NO_QOS_SIGNALING;
775999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
776999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QosDestaddr.ObjectHdr.ObjectType   = QOS_OBJECT_DESTADDR;
777999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QosDestaddr.ObjectHdr.ObjectLength = sizeof(QosDestaddr);
778999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QosDestaddr.SocketAddress = (SOCKADDR *)&stRemName;
779999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if (AF_INET6 == _iProtocol)
780999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
781999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            QosDestaddr.SocketAddressLength = sizeof(SocketAddressInVersion6);
782999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        } else {
783999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            QosDestaddr.SocketAddressLength = sizeof(SocketAddressIn);
784999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
785999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
786999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        Qos.ProviderSpecific.len = QosDestaddr.ObjectHdr.ObjectLength;
787999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        Qos.ProviderSpecific.buf = (char*)&QosDestaddr;
788999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
789999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
790999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!AquireSocket()) {
791999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return false;
792999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
793999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // To set QoS with SIO_SET_QOS the socket must be locally bound first
794999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // or the call will fail with error code 10022.
795a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t result = WSAIoctl(GetFd(), SIO_SET_QOS, &Qos, sizeof(QOS),
796999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                                    NULL, 0, &BytesRet, NULL,NULL);
797999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ReleaseSocket();
798999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (result == SOCKET_ERROR)
799999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
800999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
801999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows::SetQos() WSAerror : %d",
802999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     WSAGetLastError());
803999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return false;
804999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
805999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return true;
806999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
807999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
808a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgint32_t UdpSocket2Windows::SetTOS(int32_t serviceType)
809999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
810999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    SocketAddress socketName;
811999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
812999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    struct sockaddr_in* name =
813999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        reinterpret_cast<struct sockaddr_in*>(&socketName);
814999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    int nameLength = sizeof(SocketAddress);
815999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(AquireSocket())
816999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
817999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        getsockname(_socket, (struct sockaddr*)name, &nameLength);
818999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        ReleaseSocket();
819999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
820999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
821a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t res = SetTrafficControl(serviceType, -1, name);
822999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (res == -1)
823999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
824999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        OSVERSIONINFO OsVersion;
825999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
826999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        GetVersionEx (&OsVersion);
827999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
828999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if ((OsVersion.dwMajorVersion == 4)) // NT 4.0
829999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
830999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if(SetSockopt(IPPROTO_IP,IP_TOS ,
831a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                          (int8_t*)&serviceType, 4) != 0)
832999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
833999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                return -1;
834999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
835999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
836999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
837999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return res;
838999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
839999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
840a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgint32_t UdpSocket2Windows::SetPCP(int32_t pcp)
841999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
842999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    SocketAddress socketName;
843999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    struct sockaddr_in* name =
844999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        reinterpret_cast<struct sockaddr_in*>(&socketName);
845999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    int nameLength = sizeof(SocketAddress);
846999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(AquireSocket())
847999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
848999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        getsockname(_socket, (struct sockaddr*)name, &nameLength);
849999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        ReleaseSocket();
850999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
851999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return SetTrafficControl(-1, pcp, name);
852999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
853999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
854a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgint32_t UdpSocket2Windows::SetTrafficControl(
855a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t dscp,
856a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    int32_t pcp,
857999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    const struct sockaddr_in* name,
858999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    FLOWSPEC* send, FLOWSPEC* recv)
859999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
860999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (pcp == _pcp)
861999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
862999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // No change.
863999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        pcp = -1;
864999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
865999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if ((-1 == pcp) && (-1 == dscp))
866999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
867999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return 0;
868999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
869999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (!_gtc)
870999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
871999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc = TrafficControlWindows::GetInstance(_id);
872999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
873999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (!_gtc)
874999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
875999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
876999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
877999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_filterHandle)
878999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
879999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeleteFilter(_filterHandle);
880999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _filterHandle = NULL;
881999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
882999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_flowHandle)
883999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
884999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeleteFlow(_flowHandle);
885999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flowHandle = NULL;
886999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
887999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_clientHandle)
888999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
889999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(_clientHandle);
890999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _clientHandle = NULL;
891999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
892999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if ((0 == dscp) && (-2 == _pcp) && (-1 == pcp))
893999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
894999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // TODO (pwestin): why is this not done before deleting old filter and
895999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        //                 flow? This scenario should probably be documented in
896999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        //                 the function declaration.
897999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return 0;
898999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
899999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
900999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    TCI_CLIENT_FUNC_LIST QoSFunctions;
901999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    QoSFunctions.ClAddFlowCompleteHandler = NULL;
902999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    QoSFunctions.ClDeleteFlowCompleteHandler = NULL;
903999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    QoSFunctions.ClModifyFlowCompleteHandler = NULL;
904999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    QoSFunctions.ClNotifyHandler = (TCI_NOTIFY_HANDLER)MyClNotifyHandler;
905999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Register the client with Traffic control interface.
906999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    HANDLE ClientHandle;
907999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ULONG result = _gtc->TcRegisterClient(CURRENT_TCI_VERSION, NULL,
908999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                                          &QoSFunctions,&ClientHandle);
909999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(result != NO_ERROR)
910999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
911999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // This is likely caused by the application not being run as
912999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // administrator.
913999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
914999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                   "TcRegisterClient returned %d", result);
915999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return result;
916999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
917999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
918999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Find traffic control-enabled network interfaces that matches this
919999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // socket's IP address.
920999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ULONG BufferSize = 0;
921999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    result = _gtc->TcEnumerateInterfaces(ClientHandle, &BufferSize, NULL);
922999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
923999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(result != NO_ERROR && result != ERROR_INSUFFICIENT_BUFFER)
924999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
925999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
926999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return result;
927999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
928999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
929999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(result != ERROR_INSUFFICIENT_BUFFER)
930999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
931999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Empty buffer contains all control-enabled network interfaces. I.e.
932999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // QoS is not enabled.
933999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
934999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "QOS faild since QOS is not installed on the interface");
935999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
936999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
937999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
938999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
939999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
940999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    PTC_IFC_DESCRIPTOR pInterfaceBuffer =
941999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        (PTC_IFC_DESCRIPTOR)malloc(BufferSize);
942999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(pInterfaceBuffer == NULL)
943999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
944999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
945999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "Out ot memory failure");
946999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
947999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return ERROR_NOT_ENOUGH_MEMORY;
948999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
949999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
950999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    result = _gtc->TcEnumerateInterfaces(ClientHandle, &BufferSize,
951999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                                         pInterfaceBuffer);
952999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
953999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(result != NO_ERROR)
954999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
955999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(
956999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceError,
957999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            kTraceTransport,
958999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _id,
959999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            "Critical: error enumerating interfaces when passing in correct\
960999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org buffer size: %d", result);
961999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
962999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(pInterfaceBuffer);
963999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return result;
964999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
965999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
966999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    PTC_IFC_DESCRIPTOR oneinterface;
967999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    HANDLE ifcHandle, iFilterHandle, iflowHandle;
968999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    bool addrFound = false;
969999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ULONG filterSourceAddress = ULONG_MAX;
970999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
971999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Find the interface corresponding to the local address.
972999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    for(oneinterface = pInterfaceBuffer;
973999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        oneinterface != (PTC_IFC_DESCRIPTOR)
974a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org            (((int8_t*)pInterfaceBuffer) + BufferSize);
975999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        oneinterface = (PTC_IFC_DESCRIPTOR)
976a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org            ((int8_t *)oneinterface + oneinterface->Length))
977999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
978999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
979999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        char interfaceName[500];
980999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WideCharToMultiByte(CP_ACP, 0, oneinterface->pInterfaceName, -1,
981999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                            interfaceName, sizeof(interfaceName), 0, 0 );
982999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
983999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        PNETWORK_ADDRESS_LIST addresses =
984999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            &(oneinterface->AddressListDesc.AddressList);
985999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        for(LONG i = 0; i < addresses->AddressCount ; i++)
986999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
987999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // Only look at TCP/IP addresses.
988999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if(addresses->Address[i].AddressType != NDIS_PROTOCOL_ID_TCP_IP)
989999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
990999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                continue;
991999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
992999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
993999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            NETWORK_ADDRESS_IP* pIpAddr =
994999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                (NETWORK_ADDRESS_IP*)&(addresses->Address[i].Address);
995999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            struct in_addr in;
996999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            in.S_un.S_addr = pIpAddr->in_addr;
997999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            if(pIpAddr->in_addr == name->sin_addr.S_un.S_addr)
998999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            {
999999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                filterSourceAddress = pIpAddr->in_addr;
1000999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                addrFound = true;
1001999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            }
1002999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1003999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(!addrFound)
1004999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1005999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            continue;
1006999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        } else
1007999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1008999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            break;
1009999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1010999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1011999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!addrFound)
1012999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1013999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
1014999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "QOS faild since address is not found");
1015999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
1016999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(pInterfaceBuffer);
1017999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
1018999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1019999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    result = _gtc->TcOpenInterfaceW(oneinterface->pInterfaceName, ClientHandle,
1020999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                                    NULL, &ifcHandle);
1021999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(result != NO_ERROR)
1022999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1023999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
1024999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "Error opening interface: %d", result);
1025999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
1026999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(pInterfaceBuffer);
1027999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return result;
1028999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1029999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1030999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Create flow if one doesn't exist.
1031999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (!_flow)
1032999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1033999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        bool addPCP = ((pcp >= 0) || ((-1 == pcp) && (_pcp >= 0)));
1034999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        int allocSize = sizeof(TC_GEN_FLOW) + sizeof(QOS_DS_CLASS) +
1035999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1036999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow = (PTC_GEN_FLOW)malloc(allocSize);
1037999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1038999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
1039999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
1040999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
1041999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
1042999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
1043999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
1044999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
1045999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec.TokenRate = QOS_NOT_SPECIFIED;
1046999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1047999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
1048999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.Latency = QOS_NOT_SPECIFIED;
1049999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
1050999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
1051999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
1052999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
1053999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
1054999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED;
1055999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1056999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1057999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        dsClass->DSField = 0;
1058999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        dsClass->ObjectHdr.ObjectType = QOS_OBJECT_DS_CLASS;
1059999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        dsClass->ObjectHdr.ObjectLength = sizeof(QOS_DS_CLASS);
1060999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1061999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if (addPCP)
1062999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1063999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1);
1064999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            trafficClass->TrafficClass = 0;
1065999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            trafficClass->ObjectHdr.ObjectType = QOS_OBJECT_TRAFFIC_CLASS;
1066999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            trafficClass->ObjectHdr.ObjectLength = sizeof(QOS_TRAFFIC_CLASS);
1067999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1068999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1069999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->TcObjectsLength = sizeof(QOS_DS_CLASS) +
1070999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1071999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    } else if (-1 != pcp) {
1072999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Reallocate memory since pcp has changed.
1073999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        PTC_GEN_FLOW oldFlow = _flow;
1074999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        bool addPCP = (pcp >= 0);
1075999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        int allocSize = sizeof(TC_GEN_FLOW) + sizeof(QOS_DS_CLASS) +
1076999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1077999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow = (PTC_GEN_FLOW)malloc(allocSize);
1078999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1079999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Copy old flow.
1080999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->ReceivingFlowspec = oldFlow->ReceivingFlowspec;
1081999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->SendingFlowspec = oldFlow->SendingFlowspec;
1082999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // The DS info is always the first object.
1083999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1084999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QOS_DS_CLASS* oldDsClass = (QOS_DS_CLASS*)oldFlow->TcObjects;
1085999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        dsClass->DSField = oldDsClass->DSField;
1086999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        dsClass->ObjectHdr.ObjectType = oldDsClass->ObjectHdr.ObjectType;
1087999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        dsClass->ObjectHdr.ObjectLength = oldDsClass->ObjectHdr.ObjectLength;
1088999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1089999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if (addPCP)
1090999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1091999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1);
1092999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            trafficClass->TrafficClass = 0;
1093999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            trafficClass->ObjectHdr.ObjectType = QOS_OBJECT_TRAFFIC_CLASS;
1094999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            trafficClass->ObjectHdr.ObjectLength = sizeof(QOS_TRAFFIC_CLASS);
1095999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1096999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1097999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _flow->TcObjectsLength = sizeof(QOS_DS_CLASS) +
1098999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0);
1099999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(oldFlow);
1100999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1101999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1102999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Setup send and receive flow and DS object.
1103999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (dscp >= 0)
1104999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1105999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if (!send || (0 == dscp))
1106999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1107999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
1108999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
1109999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
1110999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
1111999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.PeakBandwidth =
1112999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                (0 == dscp ? QOS_NOT_SPECIFIED : POSITIVE_INFINITY_RATE);
1113999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;
1114999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
1115999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            // 128000 * 10 is 10mbit/s.
1116999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.TokenRate =
1117999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                (0 == dscp ? QOS_NOT_SPECIFIED : 128000 * 10);
1118999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1119999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        else
1120999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1121999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.DelayVariation = send->DelayVariation;
1122999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.Latency = send->Latency;
1123999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.MaxSduSize = send->MaxSduSize;
1124999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.MinimumPolicedSize =
1125999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                send->MinimumPolicedSize;
1126999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.PeakBandwidth = send->PeakBandwidth;
1127999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.PeakBandwidth = POSITIVE_INFINITY_RATE;
1128999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.ServiceType = send->ServiceType;
1129999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.TokenBucketSize = send->TokenBucketSize;
1130999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->SendingFlowspec.TokenRate = send->TokenRate;
1131999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1132999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1133999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if (!recv  || (0 == dscp))
1134999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1135999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.DelayVariation =
1136999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                _flow->SendingFlowspec.DelayVariation;
1137999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.Latency = _flow->SendingFlowspec.Latency;
1138999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.MaxSduSize =
1139999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                _flow->SendingFlowspec.MaxSduSize;
1140999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.MinimumPolicedSize =
1141999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                _flow->SendingFlowspec.MinimumPolicedSize;
1142999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
1143999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.ServiceType =
1144999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                0 == dscp ? SERVICETYPE_BESTEFFORT : SERVICETYPE_CONTROLLEDLOAD;
1145999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.TokenBucketSize =
1146999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                _flow->SendingFlowspec.TokenBucketSize;
1147999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.TokenRate =
1148999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                _flow->SendingFlowspec.TokenRate;
1149999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        } else {
1150999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.DelayVariation = recv->DelayVariation;
1151999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.Latency = recv->Latency;
1152999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.MaxSduSize = recv->MaxSduSize;
1153999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.MinimumPolicedSize =
1154999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                recv->MinimumPolicedSize;
1155999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.PeakBandwidth = recv->PeakBandwidth;
1156999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.ServiceType = recv->ServiceType;
1157999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.TokenBucketSize = recv->TokenBucketSize;
1158999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _flow->ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED;
1159999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1160999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1161999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Setup DS (for DSCP value).
1162999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // DS is always the first object.
1163999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1164999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        dsClass->DSField = dscp;
1165999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1166999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1167999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Setup PCP (802.1p priority in 802.1Q/VLAN tagging)
1168999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (pcp >= 0)
1169999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1170999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // DS is always first object.
1171999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects;
1172999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1);
1173999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        trafficClass->TrafficClass = pcp;
1174999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1175999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1176999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    result = _gtc->TcAddFlow(ifcHandle, NULL, 0, _flow, &iflowHandle);
1177999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(result != NO_ERROR)
1178999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1179999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcCloseInterface(ifcHandle);
1180999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
1181999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(pInterfaceBuffer);
1182999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
1183999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1184999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1185999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    IP_PATTERN filterPattern, mask;
1186999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1187a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    ZeroMemory((int8_t*)&filterPattern, sizeof(IP_PATTERN));
1188a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org    ZeroMemory((int8_t*)&mask, sizeof(IP_PATTERN));
1189999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1190999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    filterPattern.ProtocolId = IPPROTO_UDP;
1191999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // "name" fields already in network order.
1192999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    filterPattern.S_un.S_un_ports.s_srcport = name->sin_port;
1193999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    filterPattern.SrcAddr = filterSourceAddress;
1194999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1195999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Unsigned max of a type corresponds to a bitmask with all bits set to 1.
1196999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // I.e. the filter should allow all ProtocolIds, any source port and any
1197999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // IP address
1198999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    mask.ProtocolId = UCHAR_MAX;
1199999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    mask.S_un.S_un_ports.s_srcport = USHRT_MAX;
1200999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    mask.SrcAddr = ULONG_MAX;
1201999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1202999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    TC_GEN_FILTER filter;
1203999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1204999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    filter.AddressType = NDIS_PROTOCOL_ID_TCP_IP;
1205999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    filter.Mask = (LPVOID)&mask;
1206999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    filter.Pattern = (LPVOID)&filterPattern;
1207999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    filter.PatternSize = sizeof(IP_PATTERN);
1208999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1209999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    result = _gtc->TcAddFilter(iflowHandle, &filter, &iFilterHandle);
1210999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(result != NO_ERROR)
1211999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1212999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeleteFlow(iflowHandle);
1213999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcCloseInterface(ifcHandle);
1214999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _gtc->TcDeregisterClient(ClientHandle);
1215999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        free(pInterfaceBuffer);
1216999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return result;
1217999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1218999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1219999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _flowHandle = iflowHandle;
1220999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _filterHandle = iFilterHandle;
1221999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _clientHandle = ClientHandle;
1222999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (-1 != pcp)
1223999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1224999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _pcp = pcp;
1225999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1226999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1227999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _gtc->TcCloseInterface(ifcHandle);
1228999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    free(pInterfaceBuffer);
1229999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1230999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return 0;
1231999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1232999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1233a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.orgint32_t UdpSocket2Windows::CreateFlowSpec(int32_t serviceType,
1234a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                          int32_t tokenRate,
1235a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                          int32_t bucketSize,
1236a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                          int32_t peekBandwith,
1237a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                          int32_t minPolicedSize,
1238a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                          int32_t maxSduSize,
1239a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                                          FLOWSPEC* f)
1240999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1241999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if (!f)
1242999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1243999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return -1;
1244999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1245999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1246999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->ServiceType        = serviceType;
1247999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->TokenRate          = tokenRate;
1248999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->TokenBucketSize    = QOS_NOT_SPECIFIED;
1249999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->PeakBandwidth      = QOS_NOT_SPECIFIED;
1250999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->DelayVariation     = QOS_NOT_SPECIFIED;
1251999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->Latency            = QOS_NOT_SPECIFIED;
1252999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->MaxSduSize         = QOS_NOT_SPECIFIED;
1253999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    f->MinimumPolicedSize = QOS_NOT_SPECIFIED;
1254999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return 0;
1255999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1256999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1257999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgbool UdpSocket2Windows::NewOutstandingCall()
1258999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1259999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    assert(!_outstandingCallsDisabled);
1260999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1261999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ++_outstandingCalls;
1262999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return true;
1263999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1264999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1265999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgvoid UdpSocket2Windows::OutstandingCallCompleted()
1266999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1267999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrDestRWLock->AcquireLockShared();
1268999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    ++_outstandingCallComplete;
1269999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if((--_outstandingCalls == 0) && _outstandingCallsDisabled)
1270999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1271999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // When there are no outstanding calls and new outstanding calls are
1272999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // disabled it is time to terminate.
1273999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _terminate = true;
1274999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1275999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrDestRWLock->ReleaseLockShared();
1276999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1277999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if((--_outstandingCallComplete == 0) &&
1278999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        (_terminate))
1279999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1280999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Only one thread will enter here. The thread with the last outstanding
1281999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // call.
1282999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        CriticalSectionScoped cs(_ptrDeleteCrit);
1283999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _safeTodelete = true;
1284999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _ptrDeleteCond->Wake();
1285999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1286999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1287999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1288999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgvoid UdpSocket2Windows::DisableNewOutstandingCalls()
1289999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1290999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrDestRWLock->AcquireLockExclusive();
1291999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_outstandingCallsDisabled)
1292999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1293999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        // Outstandning calls are already disabled.
1294999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _ptrDestRWLock->ReleaseLockExclusive();
1295999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return;
1296999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1297999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _outstandingCallsDisabled = true;
1298999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    const bool noOutstandingCalls = (_outstandingCalls.Value() == 0);
1299999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrDestRWLock->ReleaseLockExclusive();
1300999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1301999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    RemoveSocketFromManager();
1302999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1303999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(noOutstandingCalls)
1304999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1305999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        CriticalSectionScoped cs(_ptrDeleteCrit);
1306999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _safeTodelete = true;
1307999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _ptrDeleteCond->Wake();
1308999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1309999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1310999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1311999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgvoid UdpSocket2Windows::WaitForOutstandingCalls()
1312999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1313999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    CriticalSectionScoped cs(_ptrDeleteCrit);
1314999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    while(!_safeTodelete)
1315999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1316999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _ptrDeleteCond->SleepCS(*_ptrDeleteCrit);
1317999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1318999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1319999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1320999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgvoid UdpSocket2Windows::RemoveSocketFromManager()
1321999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1322999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // New outstanding calls should be disabled at this point.
1323999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    assert(_outstandingCallsDisabled);
1324999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1325999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_addedToMgr)
1326999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1327999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
1328999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "calling UdpSocketManager::RemoveSocket()");
1329999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        if(_mgr->RemoveSocket(this))
1330999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        {
1331999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org            _addedToMgr=false;
1332999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        }
1333999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1334999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1335999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1336999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgbool UdpSocket2Windows::AquireSocket()
1337999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1338999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrSocketRWLock->AcquireLockShared();
1339999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    const bool returnValue = _socket != INVALID_SOCKET;
1340999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(!returnValue)
1341999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1342999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _ptrSocketRWLock->ReleaseLockShared();
1343999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1344999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return returnValue;
1345999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1346999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1347999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgvoid UdpSocket2Windows::ReleaseSocket()
1348999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1349999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrSocketRWLock->ReleaseLockShared();
1350999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1351999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1352999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.orgbool UdpSocket2Windows::InvalidateSocket()
1353999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org{
1354999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrSocketRWLock->AcquireLockExclusive();
1355999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(_socket == INVALID_SOCKET)
1356999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1357999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        _ptrSocketRWLock->ReleaseLockExclusive();
1358999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        return true;
1359999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1360999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // Give the socket back to the system. All socket calls will fail from now
1361999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    // on.
1362999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    if(closesocket(_socket) == SOCKET_ERROR)
1363999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    {
1364999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
1365999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org                     "UdpSocket2Windows(%d)::InvalidateSocket() WSAerror: %d",
1366a5f1787f63cb580a50f5a7be98600102454594e2pbos@webrtc.org                     (int32_t)this, WSAGetLastError());
1367999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    }
1368999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _socket = INVALID_SOCKET;
1369999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    _ptrSocketRWLock->ReleaseLockExclusive();
1370999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org    return true;
1371999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}
1372999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org
1373999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}  // namespace test
1374999e900fb6ed324bad5cb59b856936257824f43fpwestin@webrtc.org}  // namespace webrtc
1375