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