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