Index: webrtc/voice_engine/test/channel_transport/udp_socket2_win.cc |
diff --git a/webrtc/voice_engine/test/channel_transport/udp_socket2_win.cc b/webrtc/voice_engine/test/channel_transport/udp_socket2_win.cc |
deleted file mode 100644 |
index ffe71390935b17ed107c32920eccb5a75792814e..0000000000000000000000000000000000000000 |
--- a/webrtc/voice_engine/test/channel_transport/udp_socket2_win.cc |
+++ /dev/null |
@@ -1,1353 +0,0 @@ |
-/* |
- * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
- * |
- * Use of this source code is governed by a BSD-style license |
- * that can be found in the LICENSE file in the root of the source |
- * tree. An additional intellectual property rights grant can be found |
- * in the file PATENTS. All contributing project authors may |
- * be found in the AUTHORS file in the root of the source tree. |
- */ |
- |
-#include "webrtc/voice_engine/test/channel_transport/udp_socket2_win.h" |
- |
-#include <assert.h> |
-#include <stdlib.h> |
-#include <winsock2.h> |
- |
-#include "webrtc/base/format_macros.h" |
-#include "webrtc/system_wrappers/include/sleep.h" |
-#include "webrtc/voice_engine/test/channel_transport/traffic_control_win.h" |
-#include "webrtc/voice_engine/test/channel_transport/udp_socket2_manager_win.h" |
- |
-#pragma warning(disable : 4311) |
- |
-namespace webrtc { |
-namespace test { |
- |
-typedef struct _QOS_DESTADDR |
-{ |
- QOS_OBJECT_HDR ObjectHdr; |
- const struct sockaddr* SocketAddress; |
- ULONG SocketAddressLength; |
-} QOS_DESTADDR, *LPQOS_DESTADDR; |
- |
-typedef const QOS_DESTADDR* LPCQOS_DESTADDR; |
- |
-// TODO (patrikw): seems to be defined in ws2ipdef.h as 3. How come it's |
-// redefined here (as a different value)? |
-#define IP_TOS 8 |
- |
-#define QOS_GENERAL_ID_BASE 2000 |
-#define QOS_OBJECT_DESTADDR (0x00000004 + QOS_GENERAL_ID_BASE) |
- |
-UdpSocket2Windows::UdpSocket2Windows(const int32_t id, |
- UdpSocketManager* mgr, bool ipV6Enable, |
- bool disableGQOS) |
- : _id(id), |
- _qos(true), |
- _iProtocol(0), |
- _outstandingCalls(0), |
- _outstandingCallComplete(0), |
- _terminate(false), |
- _addedToMgr(false), |
- delete_event_(true, false), |
- _outstandingCallsDisabled(false), |
- _clientHandle(NULL), |
- _flowHandle(NULL), |
- _filterHandle(NULL), |
- _flow(NULL), |
- _gtc(NULL), |
- _pcp(-2), |
- _receiveBuffers(0) |
-{ |
- WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id, |
- "UdpSocket2Windows::UdpSocket2Windows()"); |
- |
- _wantsIncoming = false; |
- _mgr = static_cast<UdpSocket2ManagerWindows *>(mgr); |
- |
- _obj = NULL; |
- _incomingCb = NULL; |
- _socket = INVALID_SOCKET; |
- _ptrCbRWLock = RWLockWrapper::CreateRWLock(); |
- _ptrDestRWLock = RWLockWrapper::CreateRWLock(); |
- _ptrSocketRWLock = RWLockWrapper::CreateRWLock(); |
- |
- // Check if QoS is supported. |
- BOOL bProtocolFound = FALSE; |
- WSAPROTOCOL_INFO *lpProtocolBuf = NULL; |
- WSAPROTOCOL_INFO pProtocolInfo; |
- |
- if(!disableGQOS) |
- { |
- DWORD dwBufLen = 0; |
- // Set dwBufLen to the size needed to retreive all the requested |
- // information from WSAEnumProtocols. |
- int32_t nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen); |
- lpProtocolBuf = (WSAPROTOCOL_INFO*)malloc(dwBufLen); |
- nRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen); |
- |
- if (ipV6Enable) |
- { |
- _iProtocol=AF_INET6; |
- } else { |
- _iProtocol=AF_INET; |
- } |
- |
- for (int32_t i=0; i<nRet; i++) |
- { |
- if (_iProtocol == lpProtocolBuf[i].iAddressFamily && |
- IPPROTO_UDP == lpProtocolBuf[i].iProtocol) |
- { |
- if ((XP1_QOS_SUPPORTED == |
- (XP1_QOS_SUPPORTED & lpProtocolBuf[i].dwServiceFlags1))) |
- { |
- pProtocolInfo = lpProtocolBuf[i]; |
- bProtocolFound = TRUE; |
- break; |
- } |
- } |
- } |
- } |
- |
- if(!bProtocolFound) |
- { |
- free(lpProtocolBuf); |
- _qos=false; |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR_NO_QOS,\ |
- !bProtocolFound"); |
- } else { |
- |
- _socket = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, |
- FROM_PROTOCOL_INFO,&pProtocolInfo, 0, |
- WSA_FLAG_OVERLAPPED); |
- free(lpProtocolBuf); |
- |
- if (_socket != INVALID_SOCKET) |
- { |
- return; |
- } else { |
- _qos = false; |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR_NO_QOS"); |
- } |
- } |
- // QoS not supported. |
- if(ipV6Enable) |
- { |
- _socket = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, 0 , 0, |
- WSA_FLAG_OVERLAPPED); |
- }else |
- { |
- _socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0 , 0, |
- WSA_FLAG_OVERLAPPED); |
- } |
- if (_socket == INVALID_SOCKET) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows::UdpSocket2Windows(), INVALID_SOCKET,\ |
- WSAerror: %d", |
- WSAGetLastError()); |
- } |
- |
- // Disable send buffering on the socket to improve CPU usage. |
- // This is done by setting SO_SNDBUF to 0. |
- int32_t nZero = 0; |
- int32_t nRet = setsockopt(_socket, SOL_SOCKET, SO_SNDBUF, |
- (char*)&nZero, sizeof(nZero)); |
- if( nRet == SOCKET_ERROR ) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows::UdpSocket2Windows(), SOCKET_ERROR,\ |
- WSAerror: %d", |
- WSAGetLastError()); |
- } |
-} |
- |
-UdpSocket2Windows::~UdpSocket2Windows() |
-{ |
- WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id, |
- "UdpSocket2Windows::~UdpSocket2Windows()"); |
- |
- delete_event_.Wait(rtc::Event::kForever); |
- |
- |
- delete _ptrCbRWLock; |
- delete _ptrDestRWLock; |
- delete _ptrSocketRWLock; |
- |
- if (_flow) |
- { |
- free(_flow); |
- _flow = NULL; |
- } |
- |
- if (_gtc) |
- { |
- if(_filterHandle) |
- { |
- _gtc->TcDeleteFilter(_filterHandle); |
- } |
- if(_flowHandle) |
- { |
- _gtc->TcDeleteFlow(_flowHandle); |
- } |
- TrafficControlWindows::Release( _gtc); |
- } |
-} |
- |
-bool UdpSocket2Windows::ValidHandle() |
-{ |
- return GetFd() != INVALID_SOCKET; |
-} |
- |
-bool UdpSocket2Windows::SetCallback(CallbackObj obj, IncomingSocketCallback cb) |
-{ |
- _ptrCbRWLock->AcquireLockExclusive(); |
- _obj = obj; |
- _incomingCb = cb; |
- _ptrCbRWLock->ReleaseLockExclusive(); |
- |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::SetCallback ",(int32_t)this); |
- if(_addedToMgr) |
- { |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::SetCallback alreadey added", |
- (int32_t) this); |
- return false; |
- |
- } |
- if (_mgr->AddSocket(this)) |
- { |
- WEBRTC_TRACE( |
- kTraceDebug, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::SetCallback socket added to manager", |
- (int32_t)this); |
- _addedToMgr = true; |
- return true; |
- } |
- |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::SetCallback error adding me to mgr", |
- (int32_t) this); |
- return false; |
-} |
- |
-bool UdpSocket2Windows::SetSockopt(int32_t level, int32_t optname, |
- const int8_t* optval, int32_t optlen) |
-{ |
- bool returnValue = true; |
- if(!AquireSocket()) |
- { |
- return false; |
- } |
- if(0 != setsockopt(_socket, level, optname, |
- reinterpret_cast<const char*>(optval), optlen )) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows::SetSockopt(), WSAerror:%d", |
- WSAGetLastError()); |
- returnValue = false; |
- } |
- ReleaseSocket(); |
- return returnValue; |
-} |
- |
-bool UdpSocket2Windows::StartReceiving(uint32_t receiveBuffers) |
-{ |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::StartReceiving(%d)", (int32_t)this, |
- receiveBuffers); |
- |
- _wantsIncoming = true; |
- |
- int32_t numberOfReceiveBuffersToCreate = |
- receiveBuffers - _receiveBuffers.Value(); |
- numberOfReceiveBuffersToCreate = (numberOfReceiveBuffersToCreate < 0) ? |
- 0 : numberOfReceiveBuffersToCreate; |
- |
- int32_t error = 0; |
- for(int32_t i = 0; |
- i < numberOfReceiveBuffersToCreate; |
- i++) |
- { |
- if(PostRecv()) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows::StartReceiving() i=%d", i); |
- error = -1; |
- break; |
- } |
- ++_receiveBuffers; |
- } |
- if(error == -1) |
- { |
- return false; |
- } |
- |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "Socket receiving using:%d number of buffers", |
- _receiveBuffers.Value()); |
- return true; |
-} |
- |
-bool UdpSocket2Windows::StopReceiving() |
-{ |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "UdpSocket2Windows::StopReceiving()"); |
- _wantsIncoming = false; |
- return true; |
-} |
- |
-bool UdpSocket2Windows::Bind(const SocketAddress& name) |
-{ |
- const struct sockaddr* addr = |
- reinterpret_cast<const struct sockaddr*>(&name); |
- bool returnValue = true; |
- if(!AquireSocket()) |
- { |
- return false; |
- } |
- if (0 != bind(_socket, addr, sizeof(SocketAddress))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows::Bind() WSAerror: %d", |
- WSAGetLastError()); |
- returnValue = false; |
- } |
- ReleaseSocket(); |
- return returnValue; |
-} |
- |
-int32_t UdpSocket2Windows::SendTo(const int8_t* buf, size_t len, |
- const SocketAddress& to) |
-{ |
- int32_t retVal = 0; |
- int32_t error = 0; |
- PerIoContext* pIoContext = _mgr->PopIoContext(); |
- if(pIoContext == 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::SendTo(), pIoContext==0", |
- (int32_t) this); |
- return -1; |
- } |
- // sizeof(pIoContext->buffer) is smaller than the highest number that |
- // can be represented by a size_t. |
- if(len >= sizeof(pIoContext->buffer)) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows(%d)::SendTo(), len= %" PRIuS |
- " > buffer_size = %d", |
- (int32_t) this, |
- len,sizeof(pIoContext->buffer)); |
- len = sizeof(pIoContext->buffer); |
- } |
- |
- memcpy(pIoContext->buffer,buf,len); |
- pIoContext->wsabuf.buf = pIoContext->buffer; |
- pIoContext->wsabuf.len = static_cast<ULONG>(len); |
- pIoContext->fromLen=sizeof(SocketAddress); |
- pIoContext->ioOperation = OP_WRITE; |
- pIoContext->nTotalBytes = len; |
- pIoContext->nSentBytes=0; |
- |
- DWORD numOfbytesSent = 0; |
- const struct sockaddr* addr = reinterpret_cast<const struct sockaddr*>(&to); |
- |
- if(!AquireSocket()) |
- { |
- _mgr->PushIoContext(pIoContext); |
- return -1; |
- } |
- // Assume that the WSASendTo call will be successfull to make sure that |
- // _outstandingCalls is positive. Roll back if WSASendTo failed. |
- if(!NewOutstandingCall()) |
- { |
- _mgr->PushIoContext(pIoContext); |
- ReleaseSocket(); |
- return -1; |
- } |
- retVal = WSASendTo(_socket, &pIoContext->wsabuf, 1, &numOfbytesSent, |
- 0, addr, sizeof(SocketAddress), |
- &(pIoContext->overlapped), 0); |
- ReleaseSocket(); |
- |
- if( retVal == SOCKET_ERROR ) |
- { |
- error = WSAGetLastError(); |
- if(error != ERROR_IO_PENDING) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows::SendTo() WSAerror: %d",error); |
- } |
- } |
- if(retVal == 0 || (retVal == SOCKET_ERROR && error == ERROR_IO_PENDING)) |
- { |
- return static_cast<int32_t>(len); |
- } |
- error = _mgr->PushIoContext(pIoContext); |
- if(error) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows(%d)::SendTo(), error:%d pushing ioContext", |
- (int32_t)this, error); |
- } |
- |
- // Roll back. |
- OutstandingCallCompleted(); |
- return -1; |
-} |
- |
-void UdpSocket2Windows::IOCompleted(PerIoContext* pIOContext, |
- uint32_t ioSize, uint32_t error) |
-{ |
- if(pIOContext == NULL || error == ERROR_OPERATION_ABORTED) |
- { |
- if ((pIOContext != NULL) && |
- !pIOContext->ioInitiatedByPlatformThread && |
- (error == ERROR_OPERATION_ABORTED) && |
- (pIOContext->ioOperation == OP_READ) && |
- _outstandingCallsDisabled) |
- { |
- // !pIOContext->initiatedIOByPlatformThread indicate that the I/O |
- // was not initiated by a PlatformThread thread. |
- // This may happen if the thread that initiated receiving (e.g. |
- // by calling StartListen())) is deleted before any packets have |
- // been received. |
- // In this case there is no packet in the PerIoContext. Re-use it |
- // to post a new PostRecv(..). |
- // Note 1: the PerIoContext will henceforth be posted by a thread |
- // that is controlled by the socket implementation. |
- // Note 2: This is more likely to happen to RTCP packets as |
- // they are less frequent than RTP packets. |
- // Note 3: _outstandingCallsDisabled being false indicates |
- // that the socket isn't being shut down. |
- // Note 4: This should only happen buffers set to receive packets |
- // (OP_READ). |
- } else { |
- if(pIOContext == NULL) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows::IOCompleted(%d,%d,%d), %d", |
- (int32_t)pIOContext, |
- ioSize, |
- error, |
- pIOContext ? (int32_t)pIOContext->ioOperation : -1); |
- } else { |
- WEBRTC_TRACE( |
- kTraceDebug, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows::IOCompleted() Operation aborted"); |
- } |
- if(pIOContext) |
- { |
- int32_t remainingReceiveBuffers = --_receiveBuffers; |
- if(remainingReceiveBuffers < 0) |
- { |
- assert(false); |
- } |
- int32_t err = _mgr->PushIoContext(pIOContext); |
- if(err) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows::IOCompleted(), err = %d, when\ |
- pushing ioContext after error", |
- err); |
- } |
- } |
- OutstandingCallCompleted(); |
- return; |
- } |
- } // if (pIOContext == NULL || error == ERROR_OPERATION_ABORTED) |
- |
- if(pIOContext->ioOperation == OP_WRITE) |
- { |
- _mgr->PushIoContext(pIOContext); |
- } |
- else if(pIOContext->ioOperation == OP_READ) |
- { |
- if(!error && ioSize != 0) |
- { |
- _ptrCbRWLock->AcquireLockShared(); |
- if(_wantsIncoming && _incomingCb) |
- { |
- _incomingCb(_obj, |
- reinterpret_cast<const int8_t*>( |
- pIOContext->wsabuf.buf), |
- ioSize, |
- &pIOContext->from); |
- } |
- _ptrCbRWLock->ReleaseLockShared(); |
- } |
- int32_t err = PostRecv(pIOContext); |
- if(err == 0) |
- { |
- // The PerIoContext was posted by a thread controlled by the socket |
- // implementation. |
- pIOContext->ioInitiatedByPlatformThread = true; |
- } |
- OutstandingCallCompleted(); |
- return; |
- } else { |
- // Unknown operation. Should not happen. Return pIOContext to avoid |
- // memory leak. |
- assert(false); |
- _mgr->PushIoContext(pIOContext); |
- } |
- OutstandingCallCompleted(); |
- // Don't touch any members after OutstandingCallCompleted() since the socket |
- // may be deleted at this point. |
-} |
- |
-int32_t UdpSocket2Windows::PostRecv() |
-{ |
- PerIoContext* pIoContext=_mgr->PopIoContext(); |
- if(pIoContext == 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::PostRecv(), pIoContext == 0", |
- (int32_t)this); |
- return -1; |
- } |
- // This function may have been called by thread not controlled by the socket |
- // implementation. |
- pIoContext->ioInitiatedByPlatformThread = false; |
- return PostRecv(pIoContext); |
-} |
- |
-int32_t UdpSocket2Windows::PostRecv(PerIoContext* pIoContext) |
-{ |
- if(pIoContext==0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::PostRecv(?), pIoContext==0", |
- (int32_t)this); |
- return -1; |
- } |
- |
- DWORD numOfRecivedBytes = 0; |
- DWORD flags = 0; |
- pIoContext->wsabuf.buf = pIoContext->buffer; |
- pIoContext->wsabuf.len = sizeof(pIoContext->buffer); |
- pIoContext->fromLen = sizeof(SocketAddress); |
- pIoContext->ioOperation = OP_READ; |
- int32_t rxError = 0; |
- int32_t nRet = 0; |
- int32_t postingSucessfull = false; |
- |
- if(!AquireSocket()) |
- { |
- _mgr->PushIoContext(pIoContext); |
- return -1; |
- } |
- |
- // Assume that the WSARecvFrom() call will be successfull to make sure that |
- // _outstandingCalls is positive. Roll back if WSARecvFrom() failed. |
- if(!NewOutstandingCall()) |
- { |
- _mgr->PushIoContext(pIoContext); |
- ReleaseSocket(); |
- return -1; |
- } |
- for(int32_t tries = 0; tries < 10; tries++) |
- { |
- nRet = WSARecvFrom( |
- _socket, |
- &(pIoContext->wsabuf), |
- 1, |
- &numOfRecivedBytes, |
- &flags, |
- reinterpret_cast<struct sockaddr*>(&(pIoContext->from)), |
- &(pIoContext->fromLen), |
- &(pIoContext->overlapped), |
- 0); |
- |
- if( nRet == SOCKET_ERROR) |
- { |
- rxError = WSAGetLastError(); |
- if(rxError != ERROR_IO_PENDING) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows(%d)::PostRecv(?), WSAerror:%d when\ |
- posting new recieve,trie:%d", |
- (int32_t)this, |
- rxError, |
- tries); |
- // Tell the OS that this is a good place to context switch if |
- // it wants to. |
- SleepMs(0); |
- } |
- } |
- if((rxError == ERROR_IO_PENDING) || (nRet == 0)) |
- { |
- postingSucessfull = true; |
- break; |
- } |
- } |
- ReleaseSocket(); |
- |
- if(postingSucessfull) |
- { |
- return 0; |
- } |
- int32_t remainingReceiveBuffers = --_receiveBuffers; |
- if(remainingReceiveBuffers < 0) |
- { |
- assert(false); |
- } |
- int32_t error = _mgr->PushIoContext(pIoContext); |
- if(error) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpSocket2Windows(%d)::PostRecv(?), error:%d when PushIoContext", |
- (int32_t)this, |
- error); |
- } |
- // Roll back. |
- OutstandingCallCompleted(); |
- return -1; |
-} |
- |
-void UdpSocket2Windows::CloseBlocking() |
-{ |
- LINGER lingerStruct; |
- |
- lingerStruct.l_onoff = 1; |
- lingerStruct.l_linger = 0; |
- if(AquireSocket()) |
- { |
- setsockopt(_socket, SOL_SOCKET, SO_LINGER, |
- reinterpret_cast<const char*>(&lingerStruct), |
- sizeof(lingerStruct)); |
- ReleaseSocket(); |
- } |
- |
- _wantsIncoming = false; |
- // Reclaims the socket and prevents it from being used again. |
- InvalidateSocket(); |
- DisableNewOutstandingCalls(); |
- delete this; |
-} |
- |
-bool UdpSocket2Windows::SetQos(int32_t serviceType, |
- int32_t tokenRate, |
- int32_t bucketSize, |
- int32_t peekBandwith, |
- int32_t minPolicedSize, |
- int32_t maxSduSize, |
- const SocketAddress &stRemName, |
- int32_t overrideDSCP) |
-{ |
- if(_qos == false) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows::SetQos(), socket not capable of QOS"); |
- return false; |
- } |
- if(overrideDSCP != 0) |
- { |
- FLOWSPEC f; |
- int32_t err = CreateFlowSpec(serviceType, tokenRate, bucketSize, |
- peekBandwith, minPolicedSize, |
- maxSduSize, &f); |
- if(err == -1) |
- { |
- return false; |
- } |
- |
- SocketAddress socketName; |
- struct sockaddr_in* name = |
- reinterpret_cast<struct sockaddr_in*>(&socketName); |
- int nameLength = sizeof(SocketAddress); |
- if(AquireSocket()) |
- { |
- getsockname(_socket, (struct sockaddr*)name, &nameLength); |
- ReleaseSocket(); |
- } |
- |
- if(serviceType == 0) |
- { |
- // Disable TOS byte setting. |
- return SetTrafficControl(0, -1, name, &f, &f) == 0; |
- } |
- return SetTrafficControl(overrideDSCP, -1, name, &f, &f) == 0; |
- } |
- |
- QOS Qos; |
- DWORD BytesRet; |
- QOS_DESTADDR QosDestaddr; |
- |
- memset (&Qos, QOS_NOT_SPECIFIED, sizeof(QOS)); |
- |
- Qos.SendingFlowspec.ServiceType = serviceType; |
- Qos.SendingFlowspec.TokenRate = tokenRate; |
- Qos.SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED; |
- Qos.SendingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED; |
- Qos.SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED; |
- Qos.SendingFlowspec.Latency = QOS_NOT_SPECIFIED; |
- Qos.SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED; |
- Qos.SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED; |
- |
- // Only ServiceType is needed for receiving. |
- Qos.ReceivingFlowspec.ServiceType = serviceType; |
- Qos.ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED; |
- Qos.ReceivingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED; |
- Qos.ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED; |
- Qos.ReceivingFlowspec.Latency = QOS_NOT_SPECIFIED; |
- Qos.ReceivingFlowspec.DelayVariation = QOS_NOT_SPECIFIED; |
- Qos.ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED; |
- Qos.ReceivingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED; |
- |
- Qos.ProviderSpecific.len = 0; |
- |
- Qos.ProviderSpecific.buf = NULL; |
- |
- ZeroMemory((int8_t *)&QosDestaddr, sizeof(QosDestaddr)); |
- |
- OSVERSIONINFOEX osvie; |
- osvie.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); |
- GetVersionEx((LPOSVERSIONINFO)&osvie); |
- |
-// Operating system Version number dwMajorVersion dwMinorVersion |
-// Windows 7 6.1 6 1 |
-// Windows Server 2008 R2 6.1 6 1 |
-// Windows Server 2008 6.0 6 0 |
-// Windows Vista 6.0 6 0 |
-// Windows Server 2003 R2 5.2 5 2 |
-// Windows Server 2003 5.2 5 2 |
-// Windows XP 5.1 5 1 |
-// Windows 2000 5.0 5 0 |
- |
- // SERVICE_NO_QOS_SIGNALING and QOS_DESTADDR should not be used if version |
- // is 6.0 or greater. |
- if(osvie.dwMajorVersion >= 6) |
- { |
- Qos.SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED; |
- Qos.ReceivingFlowspec.ServiceType = serviceType; |
- |
- } else { |
- Qos.SendingFlowspec.MinimumPolicedSize = |
- QOS_NOT_SPECIFIED | SERVICE_NO_QOS_SIGNALING; |
- Qos.ReceivingFlowspec.ServiceType = |
- serviceType | SERVICE_NO_QOS_SIGNALING; |
- |
- QosDestaddr.ObjectHdr.ObjectType = QOS_OBJECT_DESTADDR; |
- QosDestaddr.ObjectHdr.ObjectLength = sizeof(QosDestaddr); |
- QosDestaddr.SocketAddress = (SOCKADDR *)&stRemName; |
- if (AF_INET6 == _iProtocol) |
- { |
- QosDestaddr.SocketAddressLength = sizeof(SocketAddressInVersion6); |
- } else { |
- QosDestaddr.SocketAddressLength = sizeof(SocketAddressIn); |
- } |
- |
- Qos.ProviderSpecific.len = QosDestaddr.ObjectHdr.ObjectLength; |
- Qos.ProviderSpecific.buf = (char*)&QosDestaddr; |
- } |
- |
- if(!AquireSocket()) { |
- return false; |
- } |
- // To set QoS with SIO_SET_QOS the socket must be locally bound first |
- // or the call will fail with error code 10022. |
- int32_t result = WSAIoctl(GetFd(), SIO_SET_QOS, &Qos, sizeof(QOS), |
- NULL, 0, &BytesRet, NULL,NULL); |
- ReleaseSocket(); |
- if (result == SOCKET_ERROR) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows::SetQos() WSAerror : %d", |
- WSAGetLastError()); |
- return false; |
- } |
- return true; |
-} |
- |
-int32_t UdpSocket2Windows::SetTOS(int32_t serviceType) |
-{ |
- SocketAddress socketName; |
- |
- struct sockaddr_in* name = |
- reinterpret_cast<struct sockaddr_in*>(&socketName); |
- int nameLength = sizeof(SocketAddress); |
- if(AquireSocket()) |
- { |
- getsockname(_socket, (struct sockaddr*)name, &nameLength); |
- ReleaseSocket(); |
- } |
- |
- int32_t res = SetTrafficControl(serviceType, -1, name); |
- if (res == -1) |
- { |
- OSVERSIONINFO OsVersion; |
- OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
- GetVersionEx (&OsVersion); |
- |
- if ((OsVersion.dwMajorVersion == 4)) // NT 4.0 |
- { |
- if(SetSockopt(IPPROTO_IP,IP_TOS , |
- (int8_t*)&serviceType, 4) != 0) |
- { |
- return -1; |
- } |
- } |
- } |
- return res; |
-} |
- |
-int32_t UdpSocket2Windows::SetPCP(int32_t pcp) |
-{ |
- SocketAddress socketName; |
- struct sockaddr_in* name = |
- reinterpret_cast<struct sockaddr_in*>(&socketName); |
- int nameLength = sizeof(SocketAddress); |
- if(AquireSocket()) |
- { |
- getsockname(_socket, (struct sockaddr*)name, &nameLength); |
- ReleaseSocket(); |
- } |
- return SetTrafficControl(-1, pcp, name); |
-} |
- |
-int32_t UdpSocket2Windows::SetTrafficControl( |
- int32_t dscp, |
- int32_t pcp, |
- const struct sockaddr_in* name, |
- FLOWSPEC* send, FLOWSPEC* recv) |
-{ |
- if (pcp == _pcp) |
- { |
- // No change. |
- pcp = -1; |
- } |
- if ((-1 == pcp) && (-1 == dscp)) |
- { |
- return 0; |
- } |
- if (!_gtc) |
- { |
- _gtc = TrafficControlWindows::GetInstance(_id); |
- } |
- if (!_gtc) |
- { |
- return -1; |
- } |
- if(_filterHandle) |
- { |
- _gtc->TcDeleteFilter(_filterHandle); |
- _filterHandle = NULL; |
- } |
- if(_flowHandle) |
- { |
- _gtc->TcDeleteFlow(_flowHandle); |
- _flowHandle = NULL; |
- } |
- if(_clientHandle) |
- { |
- _gtc->TcDeregisterClient(_clientHandle); |
- _clientHandle = NULL; |
- } |
- if ((0 == dscp) && (-2 == _pcp) && (-1 == pcp)) |
- { |
- // TODO (pwestin): why is this not done before deleting old filter and |
- // flow? This scenario should probably be documented in |
- // the function declaration. |
- return 0; |
- } |
- |
- TCI_CLIENT_FUNC_LIST QoSFunctions; |
- QoSFunctions.ClAddFlowCompleteHandler = NULL; |
- QoSFunctions.ClDeleteFlowCompleteHandler = NULL; |
- QoSFunctions.ClModifyFlowCompleteHandler = NULL; |
- QoSFunctions.ClNotifyHandler = (TCI_NOTIFY_HANDLER)MyClNotifyHandler; |
- // Register the client with Traffic control interface. |
- HANDLE ClientHandle; |
- ULONG result = _gtc->TcRegisterClient(CURRENT_TCI_VERSION, NULL, |
- &QoSFunctions,&ClientHandle); |
- if(result != NO_ERROR) |
- { |
- // This is likely caused by the application not being run as |
- // administrator. |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "TcRegisterClient returned %d", result); |
- return result; |
- } |
- |
- // Find traffic control-enabled network interfaces that matches this |
- // socket's IP address. |
- ULONG BufferSize = 0; |
- result = _gtc->TcEnumerateInterfaces(ClientHandle, &BufferSize, NULL); |
- |
- if(result != NO_ERROR && result != ERROR_INSUFFICIENT_BUFFER) |
- { |
- _gtc->TcDeregisterClient(ClientHandle); |
- return result; |
- } |
- |
- if(result != ERROR_INSUFFICIENT_BUFFER) |
- { |
- // Empty buffer contains all control-enabled network interfaces. I.e. |
- // QoS is not enabled. |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "QOS faild since QOS is not installed on the interface"); |
- |
- _gtc->TcDeregisterClient(ClientHandle); |
- return -1; |
- } |
- |
- PTC_IFC_DESCRIPTOR pInterfaceBuffer = |
- (PTC_IFC_DESCRIPTOR)malloc(BufferSize); |
- if(pInterfaceBuffer == NULL) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Out ot memory failure"); |
- _gtc->TcDeregisterClient(ClientHandle); |
- return ERROR_NOT_ENOUGH_MEMORY; |
- } |
- |
- result = _gtc->TcEnumerateInterfaces(ClientHandle, &BufferSize, |
- pInterfaceBuffer); |
- |
- if(result != NO_ERROR) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "Critical: error enumerating interfaces when passing in correct\ |
- buffer size: %d", result); |
- _gtc->TcDeregisterClient(ClientHandle); |
- free(pInterfaceBuffer); |
- return result; |
- } |
- |
- PTC_IFC_DESCRIPTOR oneinterface; |
- HANDLE ifcHandle, iFilterHandle, iflowHandle; |
- bool addrFound = false; |
- ULONG filterSourceAddress = ULONG_MAX; |
- |
- // Find the interface corresponding to the local address. |
- for(oneinterface = pInterfaceBuffer; |
- oneinterface != (PTC_IFC_DESCRIPTOR) |
- (((int8_t*)pInterfaceBuffer) + BufferSize); |
- oneinterface = (PTC_IFC_DESCRIPTOR) |
- ((int8_t *)oneinterface + oneinterface->Length)) |
- { |
- |
- char interfaceName[500]; |
- WideCharToMultiByte(CP_ACP, 0, oneinterface->pInterfaceName, -1, |
- interfaceName, sizeof(interfaceName), 0, 0 ); |
- |
- PNETWORK_ADDRESS_LIST addresses = |
- &(oneinterface->AddressListDesc.AddressList); |
- for(LONG i = 0; i < addresses->AddressCount ; i++) |
- { |
- // Only look at TCP/IP addresses. |
- if(addresses->Address[i].AddressType != NDIS_PROTOCOL_ID_TCP_IP) |
- { |
- continue; |
- } |
- |
- NETWORK_ADDRESS_IP* pIpAddr = |
- (NETWORK_ADDRESS_IP*)&(addresses->Address[i].Address); |
- struct in_addr in; |
- in.S_un.S_addr = pIpAddr->in_addr; |
- if(pIpAddr->in_addr == name->sin_addr.S_un.S_addr) |
- { |
- filterSourceAddress = pIpAddr->in_addr; |
- addrFound = true; |
- } |
- } |
- if(!addrFound) |
- { |
- continue; |
- } else |
- { |
- break; |
- } |
- } |
- if(!addrFound) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "QOS faild since address is not found"); |
- _gtc->TcDeregisterClient(ClientHandle); |
- free(pInterfaceBuffer); |
- return -1; |
- } |
- result = _gtc->TcOpenInterfaceW(oneinterface->pInterfaceName, ClientHandle, |
- NULL, &ifcHandle); |
- if(result != NO_ERROR) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Error opening interface: %d", result); |
- _gtc->TcDeregisterClient(ClientHandle); |
- free(pInterfaceBuffer); |
- return result; |
- } |
- |
- // Create flow if one doesn't exist. |
- if (!_flow) |
- { |
- bool addPCP = ((pcp >= 0) || ((-1 == pcp) && (_pcp >= 0))); |
- int allocSize = sizeof(TC_GEN_FLOW) + sizeof(QOS_DS_CLASS) + |
- (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0); |
- _flow = (PTC_GEN_FLOW)malloc(allocSize); |
- |
- _flow->SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.Latency = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT; |
- _flow->SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.TokenRate = QOS_NOT_SPECIFIED; |
- |
- _flow->ReceivingFlowspec.DelayVariation = QOS_NOT_SPECIFIED; |
- _flow->ReceivingFlowspec.Latency = QOS_NOT_SPECIFIED; |
- _flow->ReceivingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED; |
- _flow->ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED; |
- _flow->ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED; |
- _flow->ReceivingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT; |
- _flow->ReceivingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED; |
- _flow->ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED; |
- |
- QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects; |
- dsClass->DSField = 0; |
- dsClass->ObjectHdr.ObjectType = QOS_OBJECT_DS_CLASS; |
- dsClass->ObjectHdr.ObjectLength = sizeof(QOS_DS_CLASS); |
- |
- if (addPCP) |
- { |
- QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1); |
- trafficClass->TrafficClass = 0; |
- trafficClass->ObjectHdr.ObjectType = QOS_OBJECT_TRAFFIC_CLASS; |
- trafficClass->ObjectHdr.ObjectLength = sizeof(QOS_TRAFFIC_CLASS); |
- } |
- |
- _flow->TcObjectsLength = sizeof(QOS_DS_CLASS) + |
- (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0); |
- } else if (-1 != pcp) { |
- // Reallocate memory since pcp has changed. |
- PTC_GEN_FLOW oldFlow = _flow; |
- bool addPCP = (pcp >= 0); |
- int allocSize = sizeof(TC_GEN_FLOW) + sizeof(QOS_DS_CLASS) + |
- (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0); |
- _flow = (PTC_GEN_FLOW)malloc(allocSize); |
- |
- // Copy old flow. |
- _flow->ReceivingFlowspec = oldFlow->ReceivingFlowspec; |
- _flow->SendingFlowspec = oldFlow->SendingFlowspec; |
- // The DS info is always the first object. |
- QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects; |
- QOS_DS_CLASS* oldDsClass = (QOS_DS_CLASS*)oldFlow->TcObjects; |
- dsClass->DSField = oldDsClass->DSField; |
- dsClass->ObjectHdr.ObjectType = oldDsClass->ObjectHdr.ObjectType; |
- dsClass->ObjectHdr.ObjectLength = oldDsClass->ObjectHdr.ObjectLength; |
- |
- if (addPCP) |
- { |
- QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1); |
- trafficClass->TrafficClass = 0; |
- trafficClass->ObjectHdr.ObjectType = QOS_OBJECT_TRAFFIC_CLASS; |
- trafficClass->ObjectHdr.ObjectLength = sizeof(QOS_TRAFFIC_CLASS); |
- } |
- |
- _flow->TcObjectsLength = sizeof(QOS_DS_CLASS) + |
- (addPCP ? sizeof(QOS_TRAFFIC_CLASS) : 0); |
- free(oldFlow); |
- } |
- |
- // Setup send and receive flow and DS object. |
- if (dscp >= 0) |
- { |
- if (!send || (0 == dscp)) |
- { |
- _flow->SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.Latency = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED; |
- _flow->SendingFlowspec.PeakBandwidth = |
- (0 == dscp ? QOS_NOT_SPECIFIED : POSITIVE_INFINITY_RATE); |
- _flow->SendingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT; |
- _flow->SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED; |
- // 128000 * 10 is 10mbit/s. |
- _flow->SendingFlowspec.TokenRate = |
- (0 == dscp ? QOS_NOT_SPECIFIED : 128000 * 10); |
- } |
- else |
- { |
- _flow->SendingFlowspec.DelayVariation = send->DelayVariation; |
- _flow->SendingFlowspec.Latency = send->Latency; |
- _flow->SendingFlowspec.MaxSduSize = send->MaxSduSize; |
- _flow->SendingFlowspec.MinimumPolicedSize = |
- send->MinimumPolicedSize; |
- _flow->SendingFlowspec.PeakBandwidth = send->PeakBandwidth; |
- _flow->SendingFlowspec.PeakBandwidth = POSITIVE_INFINITY_RATE; |
- _flow->SendingFlowspec.ServiceType = send->ServiceType; |
- _flow->SendingFlowspec.TokenBucketSize = send->TokenBucketSize; |
- _flow->SendingFlowspec.TokenRate = send->TokenRate; |
- } |
- |
- if (!recv || (0 == dscp)) |
- { |
- _flow->ReceivingFlowspec.DelayVariation = |
- _flow->SendingFlowspec.DelayVariation; |
- _flow->ReceivingFlowspec.Latency = _flow->SendingFlowspec.Latency; |
- _flow->ReceivingFlowspec.MaxSduSize = |
- _flow->SendingFlowspec.MaxSduSize; |
- _flow->ReceivingFlowspec.MinimumPolicedSize = |
- _flow->SendingFlowspec.MinimumPolicedSize; |
- _flow->ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED; |
- _flow->ReceivingFlowspec.ServiceType = |
- 0 == dscp ? SERVICETYPE_BESTEFFORT : SERVICETYPE_CONTROLLEDLOAD; |
- _flow->ReceivingFlowspec.TokenBucketSize = |
- _flow->SendingFlowspec.TokenBucketSize; |
- _flow->ReceivingFlowspec.TokenRate = |
- _flow->SendingFlowspec.TokenRate; |
- } else { |
- _flow->ReceivingFlowspec.DelayVariation = recv->DelayVariation; |
- _flow->ReceivingFlowspec.Latency = recv->Latency; |
- _flow->ReceivingFlowspec.MaxSduSize = recv->MaxSduSize; |
- _flow->ReceivingFlowspec.MinimumPolicedSize = |
- recv->MinimumPolicedSize; |
- _flow->ReceivingFlowspec.PeakBandwidth = recv->PeakBandwidth; |
- _flow->ReceivingFlowspec.ServiceType = recv->ServiceType; |
- _flow->ReceivingFlowspec.TokenBucketSize = recv->TokenBucketSize; |
- _flow->ReceivingFlowspec.TokenRate = QOS_NOT_SPECIFIED; |
- } |
- |
- // Setup DS (for DSCP value). |
- // DS is always the first object. |
- QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects; |
- dsClass->DSField = dscp; |
- } |
- |
- // Setup PCP (802.1p priority in 802.1Q/VLAN tagging) |
- if (pcp >= 0) |
- { |
- // DS is always first object. |
- QOS_DS_CLASS* dsClass = (QOS_DS_CLASS*)_flow->TcObjects; |
- QOS_TRAFFIC_CLASS* trafficClass = (QOS_TRAFFIC_CLASS*)(dsClass + 1); |
- trafficClass->TrafficClass = pcp; |
- } |
- |
- result = _gtc->TcAddFlow(ifcHandle, NULL, 0, _flow, &iflowHandle); |
- if(result != NO_ERROR) |
- { |
- _gtc->TcCloseInterface(ifcHandle); |
- _gtc->TcDeregisterClient(ClientHandle); |
- free(pInterfaceBuffer); |
- return -1; |
- } |
- |
- IP_PATTERN filterPattern, mask; |
- |
- ZeroMemory((int8_t*)&filterPattern, sizeof(IP_PATTERN)); |
- ZeroMemory((int8_t*)&mask, sizeof(IP_PATTERN)); |
- |
- filterPattern.ProtocolId = IPPROTO_UDP; |
- // "name" fields already in network order. |
- filterPattern.S_un.S_un_ports.s_srcport = name->sin_port; |
- filterPattern.SrcAddr = filterSourceAddress; |
- |
- // Unsigned max of a type corresponds to a bitmask with all bits set to 1. |
- // I.e. the filter should allow all ProtocolIds, any source port and any |
- // IP address |
- mask.ProtocolId = UCHAR_MAX; |
- mask.S_un.S_un_ports.s_srcport = USHRT_MAX; |
- mask.SrcAddr = ULONG_MAX; |
- |
- TC_GEN_FILTER filter; |
- |
- filter.AddressType = NDIS_PROTOCOL_ID_TCP_IP; |
- filter.Mask = (LPVOID)&mask; |
- filter.Pattern = (LPVOID)&filterPattern; |
- filter.PatternSize = sizeof(IP_PATTERN); |
- |
- result = _gtc->TcAddFilter(iflowHandle, &filter, &iFilterHandle); |
- if(result != NO_ERROR) |
- { |
- _gtc->TcDeleteFlow(iflowHandle); |
- _gtc->TcCloseInterface(ifcHandle); |
- _gtc->TcDeregisterClient(ClientHandle); |
- free(pInterfaceBuffer); |
- return result; |
- } |
- |
- _flowHandle = iflowHandle; |
- _filterHandle = iFilterHandle; |
- _clientHandle = ClientHandle; |
- if (-1 != pcp) |
- { |
- _pcp = pcp; |
- } |
- |
- _gtc->TcCloseInterface(ifcHandle); |
- free(pInterfaceBuffer); |
- |
- return 0; |
-} |
- |
-int32_t UdpSocket2Windows::CreateFlowSpec(int32_t serviceType, |
- int32_t tokenRate, |
- int32_t bucketSize, |
- int32_t peekBandwith, |
- int32_t minPolicedSize, |
- int32_t maxSduSize, |
- FLOWSPEC* f) |
-{ |
- if (!f) |
- { |
- return -1; |
- } |
- |
- f->ServiceType = serviceType; |
- f->TokenRate = tokenRate; |
- f->TokenBucketSize = QOS_NOT_SPECIFIED; |
- f->PeakBandwidth = QOS_NOT_SPECIFIED; |
- f->DelayVariation = QOS_NOT_SPECIFIED; |
- f->Latency = QOS_NOT_SPECIFIED; |
- f->MaxSduSize = QOS_NOT_SPECIFIED; |
- f->MinimumPolicedSize = QOS_NOT_SPECIFIED; |
- return 0; |
-} |
- |
-bool UdpSocket2Windows::NewOutstandingCall() |
-{ |
- assert(!_outstandingCallsDisabled); |
- |
- ++_outstandingCalls; |
- return true; |
-} |
- |
-void UdpSocket2Windows::OutstandingCallCompleted() |
-{ |
- _ptrDestRWLock->AcquireLockShared(); |
- ++_outstandingCallComplete; |
- if((--_outstandingCalls == 0) && _outstandingCallsDisabled) |
- { |
- // When there are no outstanding calls and new outstanding calls are |
- // disabled it is time to terminate. |
- _terminate = true; |
- } |
- _ptrDestRWLock->ReleaseLockShared(); |
- |
- if((--_outstandingCallComplete == 0) && |
- (_terminate)) |
- { |
- // Only one thread will enter here. The thread with the last outstanding |
- // call. |
- delete_event_.Set(); |
- } |
-} |
- |
-void UdpSocket2Windows::DisableNewOutstandingCalls() |
-{ |
- _ptrDestRWLock->AcquireLockExclusive(); |
- if(_outstandingCallsDisabled) |
- { |
- // Outstandning calls are already disabled. |
- _ptrDestRWLock->ReleaseLockExclusive(); |
- return; |
- } |
- _outstandingCallsDisabled = true; |
- const bool noOutstandingCalls = (_outstandingCalls.Value() == 0); |
- _ptrDestRWLock->ReleaseLockExclusive(); |
- |
- RemoveSocketFromManager(); |
- |
- if(noOutstandingCalls) |
- { |
- delete_event_.Set(); |
- } |
-} |
- |
-void UdpSocket2Windows::RemoveSocketFromManager() |
-{ |
- // New outstanding calls should be disabled at this point. |
- assert(_outstandingCallsDisabled); |
- |
- if(_addedToMgr) |
- { |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "calling UdpSocketManager::RemoveSocket()"); |
- if(_mgr->RemoveSocket(this)) |
- { |
- _addedToMgr=false; |
- } |
- } |
-} |
- |
-bool UdpSocket2Windows::AquireSocket() |
-{ |
- _ptrSocketRWLock->AcquireLockShared(); |
- const bool returnValue = _socket != INVALID_SOCKET; |
- if(!returnValue) |
- { |
- _ptrSocketRWLock->ReleaseLockShared(); |
- } |
- return returnValue; |
-} |
- |
-void UdpSocket2Windows::ReleaseSocket() |
-{ |
- _ptrSocketRWLock->ReleaseLockShared(); |
-} |
- |
-bool UdpSocket2Windows::InvalidateSocket() |
-{ |
- _ptrSocketRWLock->AcquireLockExclusive(); |
- if(_socket == INVALID_SOCKET) |
- { |
- _ptrSocketRWLock->ReleaseLockExclusive(); |
- return true; |
- } |
- // Give the socket back to the system. All socket calls will fail from now |
- // on. |
- if(closesocket(_socket) == SOCKET_ERROR) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "UdpSocket2Windows(%d)::InvalidateSocket() WSAerror: %d", |
- (int32_t)this, WSAGetLastError()); |
- } |
- _socket = INVALID_SOCKET; |
- _ptrSocketRWLock->ReleaseLockExclusive(); |
- return true; |
-} |
- |
-} // namespace test |
-} // namespace webrtc |