Home | History | Annotate | Download | only in channel_transport
      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_transport_impl.h"
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <time.h>
     17 
     18 #if defined(_WIN32)
     19 #include <winsock2.h>
     20 #include <ws2tcpip.h>
     21 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
     22 #include <arpa/inet.h>
     23 #include <ctype.h>
     24 #include <fcntl.h>
     25 #include <net/if.h>
     26 #include <netdb.h>
     27 #include <netinet/in.h>
     28 #include <stdlib.h>
     29 #include <sys/ioctl.h>
     30 #include <sys/socket.h>
     31 #include <sys/time.h>
     32 #include <unistd.h>
     33 #ifndef WEBRTC_IOS
     34 #include <net/if_arp.h>
     35 #endif
     36 #endif // defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
     37 
     38 #if defined(WEBRTC_MAC)
     39 #include <ifaddrs.h>
     40 #include <machine/types.h>
     41 #endif
     42 #if defined(WEBRTC_LINUX)
     43 #include <linux/netlink.h>
     44 #include <linux/rtnetlink.h>
     45 #endif
     46 
     47 #include "webrtc/common_types.h"
     48 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
     49 #include "webrtc/system_wrappers/include/rw_lock_wrapper.h"
     50 #include "webrtc/system_wrappers/include/trace.h"
     51 #include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
     52 #include "webrtc/typedefs.h"
     53 
     54 #if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
     55 #define GetLastError() errno
     56 
     57 #define IFRSIZE ((int)(size * sizeof (struct ifreq)))
     58 
     59 #define NLMSG_OK_NO_WARNING(nlh,len)                                    \
     60   ((len) >= (int)sizeof(struct nlmsghdr) &&                             \
     61    (int)(nlh)->nlmsg_len >= (int)sizeof(struct nlmsghdr) &&             \
     62    (int)(nlh)->nlmsg_len <= (len))
     63 
     64 #endif // defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
     65 
     66 namespace webrtc {
     67 namespace test {
     68 
     69 class SocketFactory : public UdpTransportImpl::SocketFactoryInterface {
     70  public:
     71   UdpSocketWrapper* CreateSocket(const int32_t id,
     72                                  UdpSocketManager* mgr,
     73                                  CallbackObj obj,
     74                                  IncomingSocketCallback cb,
     75                                  bool ipV6Enable,
     76                                  bool disableGQOS) override {
     77     return UdpSocketWrapper::CreateSocket(id, mgr, obj, cb, ipV6Enable,
     78                                           disableGQOS);
     79   }
     80 };
     81 
     82 // Creates an UdpTransport using the definition of SocketFactory above,
     83 // and passes (creating if needed) a pointer to the static singleton
     84 // UdpSocketManager.
     85 UdpTransport* UdpTransport::Create(const int32_t id,
     86                                    uint8_t& numSocketThreads)
     87 {
     88   return new UdpTransportImpl(id,
     89                               new SocketFactory(),
     90                               UdpSocketManager::Create(id, numSocketThreads));
     91 }
     92 
     93 // Deletes the UdpTransport and decrements the refcount of the
     94 // static singleton UdpSocketManager, possibly destroying it.
     95 // Should only be used on UdpTransports that are created using Create.
     96 void UdpTransport::Destroy(UdpTransport* module)
     97 {
     98     if(module)
     99     {
    100         delete module;
    101         UdpSocketManager::Return();
    102     }
    103 }
    104 
    105 UdpTransportImpl::UdpTransportImpl(const int32_t id,
    106                                    SocketFactoryInterface* maker,
    107                                    UdpSocketManager* socket_manager)
    108     : _id(id),
    109       _socket_creator(maker),
    110       _crit(CriticalSectionWrapper::CreateCriticalSection()),
    111       _critFilter(CriticalSectionWrapper::CreateCriticalSection()),
    112       _critPacketCallback(CriticalSectionWrapper::CreateCriticalSection()),
    113       _mgr(socket_manager),
    114       _lastError(kNoSocketError),
    115       _destPort(0),
    116       _destPortRTCP(0),
    117       _localPort(0),
    118       _localPortRTCP(0),
    119       _srcPort(0),
    120       _srcPortRTCP(0),
    121       _fromPort(0),
    122       _fromPortRTCP(0),
    123       _fromIP(),
    124       _destIP(),
    125       _localIP(),
    126       _localMulticastIP(),
    127       _ptrRtpSocket(NULL),
    128       _ptrRtcpSocket(NULL),
    129       _ptrSendRtpSocket(NULL),
    130       _ptrSendRtcpSocket(NULL),
    131       _remoteRTPAddr(),
    132       _remoteRTCPAddr(),
    133       _localRTPAddr(),
    134       _localRTCPAddr(),
    135       _tos(0),
    136       _receiving(false),
    137       _useSetSockOpt(false),
    138       _qos(false),
    139       _pcp(0),
    140       _ipV6Enabled(false),
    141       _serviceType(0),
    142       _overrideDSCP(0),
    143       _maxBitrate(0),
    144       _cachLock(RWLockWrapper::CreateRWLock()),
    145       _previousAddress(),
    146       _previousIP(),
    147       _previousIPSize(0),
    148       _previousSourcePort(0),
    149       _filterIPAddress(),
    150       _rtpFilterPort(0),
    151       _rtcpFilterPort(0),
    152       _packetCallback(0)
    153 {
    154     memset(&_remoteRTPAddr, 0, sizeof(_remoteRTPAddr));
    155     memset(&_remoteRTCPAddr, 0, sizeof(_remoteRTCPAddr));
    156     memset(&_localRTPAddr, 0, sizeof(_localRTPAddr));
    157     memset(&_localRTCPAddr, 0, sizeof(_localRTCPAddr));
    158 
    159     memset(_fromIP, 0, sizeof(_fromIP));
    160     memset(_destIP, 0, sizeof(_destIP));
    161     memset(_localIP, 0, sizeof(_localIP));
    162     memset(_localMulticastIP, 0, sizeof(_localMulticastIP));
    163 
    164     memset(&_filterIPAddress, 0, sizeof(_filterIPAddress));
    165 
    166     WEBRTC_TRACE(kTraceMemory, kTraceTransport, id, "%s created", __FUNCTION__);
    167 }
    168 
    169 UdpTransportImpl::~UdpTransportImpl()
    170 {
    171     CloseSendSockets();
    172     CloseReceiveSockets();
    173     delete _crit;
    174     delete _critFilter;
    175     delete _critPacketCallback;
    176     delete _cachLock;
    177     delete _socket_creator;
    178 
    179     WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id, "%s deleted",
    180                  __FUNCTION__);
    181 }
    182 
    183 UdpTransport::ErrorCode UdpTransportImpl::LastError() const
    184 {
    185     return _lastError;
    186 }
    187 
    188 bool SameAddress(const SocketAddress& address1, const SocketAddress& address2)
    189 {
    190     return (memcmp(&address1,&address2,sizeof(address1)) == 0);
    191 }
    192 
    193 void UdpTransportImpl::GetCachedAddress(char* ip,
    194                                         uint32_t& ipSize,
    195                                         uint16_t& sourcePort)
    196 {
    197     const uint32_t originalIPSize = ipSize;
    198     // If the incoming string is too small, fill it as much as there is room
    199     // for. Make sure that there is room for the '\0' character.
    200     ipSize = (ipSize - 1 < _previousIPSize) ? ipSize - 1 : _previousIPSize;
    201     memcpy(ip,_previousIP,sizeof(int8_t)*(ipSize + 1));
    202     ip[originalIPSize - 1] = '\0';
    203     sourcePort = _previousSourcePort;
    204 }
    205 
    206 int32_t UdpTransportImpl::IPAddressCached(const SocketAddress& address,
    207                                           char* ip,
    208                                           uint32_t& ipSize,
    209                                           uint16_t& sourcePort)
    210 {
    211     {
    212         ReadLockScoped rl(*_cachLock);
    213         // Check if the old address can be re-used (is the same).
    214         if(SameAddress(address,_previousAddress))
    215         {
    216             GetCachedAddress(ip,ipSize,sourcePort);
    217             return 0;
    218         }
    219     }
    220     // Get the new address and store it.
    221     WriteLockScoped wl(*_cachLock);
    222     ipSize = kIpAddressVersion6Length;
    223     if(IPAddress(address,_previousIP,ipSize,_previousSourcePort) != 0)
    224     {
    225         return -1;
    226     }
    227     _previousIPSize = ipSize;
    228     memcpy(&_previousAddress, &address, sizeof(address));
    229     // Address has been cached at this point.
    230     GetCachedAddress(ip,ipSize,sourcePort);
    231     return 0;
    232 }
    233 
    234 int32_t UdpTransportImpl::InitializeReceiveSockets(
    235     UdpTransportData* const packetCallback,
    236     const uint16_t portnr,
    237     const char* ip,
    238     const char* multicastIpAddr,
    239     const uint16_t rtcpPort)
    240 {
    241     {
    242         CriticalSectionScoped cs(_critPacketCallback);
    243         _packetCallback = packetCallback;
    244 
    245         if(packetCallback == NULL)
    246         {
    247             WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id,
    248                          "Closing down receive sockets");
    249             return 0;
    250         }
    251     }
    252 
    253     CriticalSectionScoped cs(_crit);
    254     CloseReceiveSockets();
    255 
    256     if(portnr == 0)
    257     {
    258         // TODO (hellner): why not just fail here?
    259         if(_destPort == 0)
    260         {
    261             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    262                          "InitializeReceiveSockets port 0 not allowed");
    263             _lastError = kPortInvalid;
    264             return -1;
    265         }
    266         _localPort = _destPort;
    267     } else {
    268         _localPort = portnr;
    269     }
    270     if(rtcpPort)
    271     {
    272         _localPortRTCP = rtcpPort;
    273     }else {
    274         _localPortRTCP = _localPort + 1;
    275         WEBRTC_TRACE(
    276             kTraceStateInfo,
    277             kTraceTransport,
    278             _id,
    279             "InitializeReceiveSockets RTCP port not configured using RTP\
    280  port+1=%d",
    281             _localPortRTCP);
    282     }
    283 
    284     if(ip)
    285     {
    286         if(IsIpAddressValid(ip,IpV6Enabled()))
    287         {
    288             strncpy(_localIP, ip,kIpAddressVersion6Length);
    289         } else
    290         {
    291             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    292                          "InitializeReceiveSockets invalid IP address");
    293             _lastError = kIpAddressInvalid;
    294             return -1;
    295         }
    296     }else
    297     {
    298         // Don't bind to a specific IP address.
    299         if(! IpV6Enabled())
    300         {
    301             strncpy(_localIP, "0.0.0.0",16);
    302         } else
    303         {
    304             strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000",
    305                     kIpAddressVersion6Length);
    306         }
    307     }
    308     if(multicastIpAddr && !IpV6Enabled())
    309     {
    310         if(IsIpAddressValid(multicastIpAddr,IpV6Enabled()))
    311         {
    312             strncpy(_localMulticastIP, multicastIpAddr,
    313                     kIpAddressVersion6Length);
    314         } else
    315         {
    316             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    317                          "InitializeReceiveSockets invalid IP address");
    318             _lastError =  kIpAddressInvalid;
    319             return -1;
    320         }
    321     }
    322     if(_mgr == NULL)
    323     {
    324         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    325                      "InitializeReceiveSockets no socket manager");
    326         return -1;
    327     }
    328 
    329     _useSetSockOpt=false;
    330     _tos=0;
    331     _pcp=0;
    332 
    333     _ptrRtpSocket = _socket_creator->CreateSocket(_id, _mgr, this,
    334                                     IncomingRTPCallback,
    335                                     IpV6Enabled(), false);
    336 
    337     _ptrRtcpSocket = _socket_creator->CreateSocket(_id, _mgr, this,
    338                                      IncomingRTCPCallback,
    339                                      IpV6Enabled(), false);
    340 
    341     ErrorCode retVal = BindLocalRTPSocket();
    342     if(retVal != kNoSocketError)
    343     {
    344         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    345                      "InitializeReceiveSockets faild to bind RTP socket");
    346         _lastError = retVal;
    347         CloseReceiveSockets();
    348         return -1;
    349     }
    350     retVal = BindLocalRTCPSocket();
    351     if(retVal != kNoSocketError)
    352     {
    353         _lastError = retVal;
    354         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    355                      "InitializeReceiveSockets faild to bind RTCP socket");
    356         CloseReceiveSockets();
    357         return -1;
    358     }
    359     return 0;
    360 }
    361 
    362 int32_t UdpTransportImpl::ReceiveSocketInformation(
    363     char ipAddr[kIpAddressVersion6Length],
    364     uint16_t& rtpPort,
    365     uint16_t& rtcpPort,
    366     char multicastIpAddr[kIpAddressVersion6Length]) const
    367 {
    368     CriticalSectionScoped cs(_crit);
    369     rtpPort = _localPort;
    370     rtcpPort = _localPortRTCP;
    371     if (ipAddr)
    372     {
    373         strncpy(ipAddr, _localIP, IpV6Enabled() ?
    374                 UdpTransport::kIpAddressVersion6Length :
    375                 UdpTransport::kIpAddressVersion4Length);
    376     }
    377     if (multicastIpAddr)
    378     {
    379         strncpy(multicastIpAddr, _localMulticastIP, IpV6Enabled() ?
    380                 UdpTransport::kIpAddressVersion6Length :
    381                 UdpTransport::kIpAddressVersion4Length);
    382     }
    383     return 0;
    384 }
    385 
    386 int32_t UdpTransportImpl::SendSocketInformation(
    387     char ipAddr[kIpAddressVersion6Length],
    388     uint16_t& rtpPort,
    389     uint16_t& rtcpPort) const
    390 {
    391     CriticalSectionScoped cs(_crit);
    392     rtpPort = _destPort;
    393     rtcpPort = _destPortRTCP;
    394     strncpy(ipAddr, _destIP, IpV6Enabled() ?
    395             UdpTransport::kIpAddressVersion6Length :
    396             UdpTransport::kIpAddressVersion4Length);
    397     return 0;
    398 }
    399 
    400 int32_t UdpTransportImpl::RemoteSocketInformation(
    401     char ipAddr[kIpAddressVersion6Length],
    402     uint16_t& rtpPort,
    403     uint16_t& rtcpPort) const
    404 {
    405     CriticalSectionScoped cs(_crit);
    406     rtpPort = _fromPort;
    407     rtcpPort = _fromPortRTCP;
    408     if(ipAddr)
    409     {
    410         strncpy(ipAddr, _fromIP, IpV6Enabled() ?
    411                 kIpAddressVersion6Length :
    412                 kIpAddressVersion4Length);
    413     }
    414     return 0;
    415 }
    416 
    417 int32_t UdpTransportImpl::FilterPorts(
    418     uint16_t& rtpFilterPort,
    419     uint16_t& rtcpFilterPort) const
    420 {
    421     CriticalSectionScoped cs(_critFilter);
    422     rtpFilterPort = _rtpFilterPort;
    423     rtcpFilterPort = _rtcpFilterPort;
    424     return 0;
    425 }
    426 
    427 int32_t UdpTransportImpl::SetQoS(bool QoS, int32_t serviceType,
    428                                  uint32_t maxBitrate,
    429                                  int32_t overrideDSCP, bool audio)
    430 {
    431     if(QoS)
    432     {
    433         return EnableQoS(serviceType, audio, maxBitrate, overrideDSCP);
    434     }else
    435     {
    436         return DisableQoS();
    437     }
    438 }
    439 
    440 int32_t UdpTransportImpl::EnableQoS(int32_t serviceType,
    441                                     bool audio, uint32_t maxBitrate,
    442                                     int32_t overrideDSCP)
    443 {
    444     if (_ipV6Enabled)
    445     {
    446         WEBRTC_TRACE(
    447             kTraceError,
    448             kTraceTransport,
    449             _id,
    450             "QOS is enabled but will be ignored since IPv6 is enabled");
    451         _lastError = kQosError;
    452         return -1;
    453     }
    454     if (_tos)
    455     {
    456         WEBRTC_TRACE(
    457             kTraceError,
    458             kTraceTransport,
    459             _id,
    460             "TOS already enabled, can't use TOS and QoS at the same time");
    461         _lastError = kQosError;
    462         return -1;
    463     }
    464     if (_pcp)
    465     {
    466         WEBRTC_TRACE(
    467             kTraceError,
    468             kTraceTransport,
    469             _id,
    470             "PCP already enabled, can't use PCP and QoS at the same time");
    471         _lastError = kQosError;
    472         return -1;
    473     }
    474     if(_destPort == 0)
    475     {
    476         WEBRTC_TRACE(
    477             kTraceError,
    478             kTraceTransport,
    479             _id,
    480             "QOS is enabled but not started since we have not yet configured\
    481  the send destination");
    482         return -1;
    483     }
    484     if(_qos)
    485     {
    486         if(_overrideDSCP == 0 && overrideDSCP != 0)
    487         {
    488             WEBRTC_TRACE(
    489                 kTraceError,
    490                 kTraceTransport,
    491                 _id,
    492                 "QOS is already enabled and overrideDSCP differs, not allowed");
    493             return -1;
    494         }
    495     }
    496     CriticalSectionScoped cs(_crit);
    497 
    498     UdpSocketWrapper* rtpSock = _ptrSendRtpSocket ?
    499         _ptrSendRtpSocket :
    500         _ptrRtpSocket;
    501     if (!rtpSock || !rtpSock->ValidHandle())
    502     {
    503         WEBRTC_TRACE(
    504             kTraceError,
    505             kTraceTransport,
    506             _id,
    507             "QOS is enabled but not started since we have not yet created the\
    508  RTP socket");
    509         return -1;
    510     }
    511     UdpSocketWrapper* rtcpSock = _ptrSendRtcpSocket ?
    512         _ptrSendRtcpSocket :
    513         _ptrRtcpSocket;
    514     if (!rtcpSock || !rtcpSock->ValidHandle())
    515     {
    516         WEBRTC_TRACE(
    517             kTraceError,
    518             kTraceTransport,
    519             _id,
    520             "QOS is enabled but not started since we have not yet created the\
    521  RTCP socket");
    522         return -1;
    523     }
    524 
    525     // Minimum packet size in bytes for which the requested quality of service
    526     // will be provided. The smallest RTP header is 12 byte.
    527     const int32_t min_policed_size = 12;
    528     // Max SDU, maximum packet size permitted or used in the traffic flow, in
    529     // bytes.
    530     const int32_t max_sdu_size = 1500;
    531 
    532     // Enable QoS for RTP sockets.
    533     if(maxBitrate)
    534     {
    535         // Note: 1 kbit is 125 bytes.
    536         // Token Rate is typically set to the average bit rate from peak to
    537         // peak.
    538         // Bucket size is normally set to the largest average frame size.
    539         if(audio)
    540         {
    541             WEBRTC_TRACE(kTraceStateInfo,
    542                          kTraceTransport,
    543                          _id,
    544                          "Enable QOS for audio with max bitrate:%d",
    545                          maxBitrate);
    546 
    547             const int32_t token_rate = maxBitrate*125;
    548             // The largest audio packets are 60ms frames. This is a fraction
    549             // more than 16 packets/second. These 16 frames are sent, at max,
    550             // at a bitrate of maxBitrate*125 -> 1 frame is maxBitrate*125/16 ~
    551             // maxBitrate * 8.
    552             const int32_t bucket_size = maxBitrate * 8;
    553             const int32_t peek_bandwith =  maxBitrate * 125;
    554             if (!rtpSock->SetQos(serviceType, token_rate, bucket_size,
    555                                  peek_bandwith, min_policed_size,
    556                                  max_sdu_size, _remoteRTPAddr, overrideDSCP))
    557             {
    558                 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    559                              "QOS failed on the RTP socket");
    560                 _lastError = kQosError;
    561                 return -1;
    562             }
    563         }else
    564         {
    565             WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id,
    566                          "Enable QOS for video with max bitrate:%d",
    567                          maxBitrate);
    568 
    569             // Allow for a token rate that is twice that of the maximum bitrate
    570             // (in bytes).
    571             const int32_t token_rate = maxBitrate*250;
    572             // largest average frame size (key frame size). Assuming that a
    573             // keyframe is 25% of the bitrate during the second its sent
    574             // Assume that a key frame is 25% of the bitrate the second that it
    575             // is sent. The largest frame size is then maxBitrate* 125 * 0.25 ~
    576             // 31.
    577             const int32_t bucket_size = maxBitrate*31;
    578             const int32_t peek_bandwith = maxBitrate*125;
    579             if (!rtpSock->SetQos(serviceType, token_rate, bucket_size,
    580                                 peek_bandwith, min_policed_size, max_sdu_size,
    581                                 _remoteRTPAddr, overrideDSCP))
    582             {
    583                 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    584                              "QOS failed on the RTP socket");
    585                 _lastError = kQosError;
    586                 return -1;
    587             }
    588         }
    589     } else if(audio)
    590     {
    591         // No max bitrate set. Audio.
    592         WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id,
    593                      "Enable QOS for audio with default max bitrate");
    594 
    595         // Let max bitrate be 240kbit/s.
    596         const int32_t token_rate = 30000;
    597         const int32_t bucket_size = 2000;
    598         const int32_t peek_bandwith = 30000;
    599         if (!rtpSock->SetQos(serviceType, token_rate, bucket_size,
    600                              peek_bandwith, min_policed_size, max_sdu_size,
    601                              _remoteRTPAddr, overrideDSCP))
    602         {
    603             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    604                          "QOS failed on the RTP socket");
    605             _lastError = kQosError;
    606             return -1;
    607         }
    608     }else
    609     {
    610         // No max bitrate set. Video.
    611         WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id,
    612                      "Enable QOS for video with default max bitrate");
    613 
    614         // Let max bitrate be 10mbit/s.
    615         const int32_t token_rate = 128000*10;
    616         const int32_t bucket_size = 32000;
    617         const int32_t peek_bandwith = 256000;
    618         if (!rtpSock->SetQos(serviceType, token_rate, bucket_size,
    619                              peek_bandwith, min_policed_size, max_sdu_size,
    620                              _remoteRTPAddr, overrideDSCP))
    621         {
    622             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    623                          "QOS failed on the RTP socket");
    624             _lastError = kQosError;
    625             return -1;
    626         }
    627     }
    628 
    629     // Enable QoS for RTCP sockets.
    630     // TODO (hellner): shouldn't RTCP be based on 5% of the maximum bandwidth?
    631     if(audio)
    632     {
    633         const int32_t token_rate = 200;
    634         const int32_t bucket_size = 200;
    635         const int32_t peek_bandwith = 400;
    636         if (!rtcpSock->SetQos(serviceType, token_rate, bucket_size,
    637                               peek_bandwith, min_policed_size, max_sdu_size,
    638                               _remoteRTCPAddr, overrideDSCP))
    639         {
    640             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
    641                          "QOS failed on the RTCP socket");
    642             _lastError = kQosError;
    643         }
    644     }else
    645     {
    646         const int32_t token_rate = 5000;
    647         const int32_t bucket_size = 100;
    648         const int32_t peek_bandwith = 10000;
    649         if (!rtcpSock->SetQos(serviceType, token_rate, bucket_size,
    650                               peek_bandwith, min_policed_size, max_sdu_size,
    651                             _remoteRTCPAddr, _overrideDSCP))
    652         {
    653             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
    654                          "QOS failed on the RTCP socket");
    655             _lastError = kQosError;
    656         }
    657     }
    658     _qos = true;
    659     _serviceType = serviceType;
    660     _maxBitrate = maxBitrate;
    661     _overrideDSCP = overrideDSCP;
    662     return 0;
    663 }
    664 
    665 int32_t UdpTransportImpl::DisableQoS()
    666 {
    667     if(_qos == false)
    668     {
    669         return 0;
    670     }
    671     CriticalSectionScoped cs(_crit);
    672 
    673     UdpSocketWrapper* rtpSock = (_ptrSendRtpSocket ?
    674                                  _ptrSendRtpSocket : _ptrRtpSocket);
    675     if (!rtpSock || !rtpSock->ValidHandle())
    676     {
    677         WEBRTC_TRACE(
    678             kTraceError,
    679             kTraceTransport,
    680             _id,
    681             "QOS is enabled but not started since we have not yet created the\
    682  RTP socket");
    683         return -1;
    684     }
    685     UdpSocketWrapper* rtcpSock = (_ptrSendRtcpSocket ?
    686                                   _ptrSendRtcpSocket : _ptrRtcpSocket);
    687     if (!rtcpSock || !rtcpSock->ValidHandle())
    688     {
    689         WEBRTC_TRACE(
    690             kTraceError,
    691             kTraceTransport,
    692             _id,
    693             "QOS is enabled but not started since we have not yet created the\
    694  RTCP socket");
    695         return -1;
    696     }
    697 
    698     const int32_t service_type = 0;   // = SERVICETYPE_NOTRAFFIC
    699     const int32_t not_specified = -1;
    700     if (!rtpSock->SetQos(service_type, not_specified, not_specified,
    701                          not_specified, not_specified, not_specified,
    702                          _remoteRTPAddr, _overrideDSCP))
    703     {
    704         _lastError = kQosError;
    705         return -1;
    706     }
    707     if (!rtcpSock->SetQos(service_type, not_specified, not_specified,
    708                          not_specified, not_specified, not_specified,
    709                          _remoteRTCPAddr,_overrideDSCP))
    710     {
    711         _lastError = kQosError;
    712     }
    713     _qos = false;
    714     return 0;
    715 }
    716 
    717 int32_t UdpTransportImpl::QoS(bool& QoS, int32_t& serviceType,
    718                               int32_t& overrideDSCP) const
    719 {
    720     CriticalSectionScoped cs(_crit);
    721     QoS = _qos;
    722     serviceType = _serviceType;
    723     overrideDSCP = _overrideDSCP;
    724     return 0;
    725 }
    726 
    727 int32_t UdpTransportImpl::SetToS(int32_t DSCP, bool useSetSockOpt)
    728 {
    729     if (_qos)
    730     {
    731         WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "QoS already enabled");
    732         _lastError = kQosError;
    733         return -1;
    734     }
    735     if (DSCP < 0 || DSCP > 63)
    736     {
    737         WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "Invalid DSCP");
    738         _lastError = kTosInvalid;
    739         return -1;
    740     }
    741     if(_tos)
    742     {
    743         if(useSetSockOpt != _useSetSockOpt)
    744         {
    745             WEBRTC_TRACE(
    746                 kTraceError,
    747                 kTraceTransport,
    748                 _id,
    749                 "Can't switch SetSockOpt method without disabling TOS first");
    750             _lastError = kTosInvalid;
    751             return -1;
    752         }
    753     }
    754     CriticalSectionScoped cs(_crit);
    755     UdpSocketWrapper* rtpSock = NULL;
    756     UdpSocketWrapper* rtcpSock = NULL;
    757     if(_ptrSendRtpSocket)
    758     {
    759         rtpSock = _ptrSendRtpSocket;
    760     }else
    761     {
    762         rtpSock = _ptrRtpSocket;
    763     }
    764     if (rtpSock == NULL)
    765     {
    766         _lastError = kSocketInvalid;
    767         return -1;
    768     }
    769     if(!rtpSock->ValidHandle())
    770     {
    771         _lastError = kSocketInvalid;
    772         return -1;
    773     }
    774     if(_ptrSendRtcpSocket)
    775     {
    776         rtcpSock = _ptrSendRtcpSocket;
    777     }else
    778     {
    779         rtcpSock = _ptrRtcpSocket;
    780     }
    781     if (rtcpSock == NULL)
    782     {
    783         _lastError = kSocketInvalid;
    784         return -1;
    785     }
    786     if(!rtcpSock->ValidHandle())
    787     {
    788         _lastError = kSocketInvalid;
    789         return -1;
    790     }
    791 
    792     if (useSetSockOpt)
    793     {
    794 #ifdef _WIN32
    795         OSVERSIONINFO OsVersion;
    796         OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    797         GetVersionEx(&OsVersion);
    798         // Disable QoS before setting ToS on Windows XP. This is done by closing
    799         // and re-opening the sockets.
    800         // TODO (hellner): why not just fail here and force the user to
    801         //                 re-initialize sockets? Doing this may trick the user
    802         //                 into thinking that the sockets are in a state which
    803         //                 they aren't.
    804         if (OsVersion.dwMajorVersion == 5 &&
    805             OsVersion.dwMinorVersion == 1)
    806         {
    807             if(!_useSetSockOpt)
    808             {
    809                 if(_ptrSendRtpSocket)
    810                 {
    811                     CloseSendSockets();
    812                     _ptrSendRtpSocket =
    813                         _socket_creator->CreateSocket(_id, _mgr, NULL,
    814                                         NULL, IpV6Enabled(),
    815                                         true);
    816                     _ptrSendRtcpSocket =
    817                         _socket_creator->CreateSocket(_id, _mgr, NULL,
    818                                         NULL, IpV6Enabled(),
    819                                         true);
    820                     rtpSock=_ptrSendRtpSocket;
    821                     rtcpSock=_ptrSendRtcpSocket;
    822                     ErrorCode retVal = BindRTPSendSocket();
    823                     if(retVal != kNoSocketError)
    824                     {
    825                         _lastError = retVal;
    826                         return -1;
    827                     }
    828                     retVal = BindRTCPSendSocket();
    829                     if(retVal != kNoSocketError)
    830                     {
    831                         _lastError = retVal;
    832                         return -1;
    833                     }
    834                 }
    835                 else
    836                 {
    837                     bool receiving=_receiving;
    838                     uint32_t noOfReceiveBuffers = 0;
    839                     if(receiving)
    840                     {
    841                         noOfReceiveBuffers=_ptrRtpSocket->ReceiveBuffers();
    842                         if(StopReceiving()!=0)
    843                         {
    844                             return -1;
    845                         }
    846                     }
    847                     CloseReceiveSockets();
    848                     _ptrRtpSocket = _socket_creator->CreateSocket(
    849                         _id, _mgr, this, IncomingRTPCallback, IpV6Enabled(),
    850                         true);
    851                     _ptrRtcpSocket = _socket_creator->CreateSocket(
    852                         _id, _mgr, this, IncomingRTCPCallback, IpV6Enabled(),
    853                         true);
    854                     rtpSock=_ptrRtpSocket;
    855                     rtcpSock=_ptrRtcpSocket;
    856                     ErrorCode retVal = BindLocalRTPSocket();
    857                     if(retVal != kNoSocketError)
    858                     {
    859                         _lastError = retVal;
    860                         return -1;
    861                     }
    862                     retVal = BindLocalRTCPSocket();
    863                     if(retVal != kNoSocketError)
    864                     {
    865                         _lastError = retVal;
    866                         return -1;
    867                     }
    868                     if(receiving)
    869                     {
    870                         if(StartReceiving(noOfReceiveBuffers) !=
    871                            kNoSocketError)
    872                         {
    873                             return -1;
    874                         }
    875                     }
    876                 }
    877             }
    878         }
    879 #endif // #ifdef _WIN32
    880         WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
    881                      "Setting TOS using SetSockopt");
    882         int32_t TOSShifted = DSCP << 2;
    883         if (!rtpSock->SetSockopt(IPPROTO_IP, IP_TOS,
    884                                  (int8_t*) &TOSShifted, 4))
    885         {
    886             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    887                          "Could not SetSockopt tos value on RTP socket");
    888             _lastError = kTosInvalid;
    889             return -1;
    890         }
    891         if (!rtcpSock->SetSockopt(IPPROTO_IP, IP_TOS,
    892                                   (int8_t*) &TOSShifted, 4))
    893         {
    894             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    895                          "Could not sSetSockopt tos value on RTCP socket");
    896             _lastError = kTosInvalid;
    897             return -1;
    898         }
    899     } else
    900     {
    901         WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
    902                      "Setting TOS NOT using SetSockopt");
    903         if (rtpSock->SetTOS(DSCP) != 0)
    904         {
    905             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    906                          "Could not set tos value on RTP socket");
    907             _lastError = kTosError;
    908             return -1;
    909         }
    910         if (rtcpSock->SetTOS(DSCP) != 0)
    911         {
    912             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    913                          "Could not set tos value on RTCP socket");
    914             _lastError = kTosError;
    915             return -1;
    916         }
    917     }
    918     _useSetSockOpt = useSetSockOpt;
    919     _tos = DSCP;
    920     return 0;
    921 }
    922 
    923 int32_t UdpTransportImpl::ToS(int32_t& DSCP,
    924                               bool& useSetSockOpt) const
    925 {
    926     CriticalSectionScoped cs(_crit);
    927     DSCP = _tos;
    928     useSetSockOpt = _useSetSockOpt;
    929     return 0;
    930 }
    931 
    932 int32_t UdpTransportImpl::SetPCP(int32_t PCP)
    933 {
    934 
    935     if (_qos)
    936     {
    937         WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "QoS already enabled");
    938         _lastError = kQosError;
    939         return -1;
    940     }
    941     if ((PCP < 0) || (PCP > 7))
    942     {
    943         WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "Invalid PCP");
    944         _lastError = kPcpError;
    945         return -1;
    946     }
    947 
    948     CriticalSectionScoped cs(_crit);
    949     UdpSocketWrapper* rtpSock = NULL;
    950     UdpSocketWrapper* rtcpSock = NULL;
    951     if(_ptrSendRtpSocket)
    952     {
    953         rtpSock = _ptrSendRtpSocket;
    954     }else
    955     {
    956         rtpSock = _ptrRtpSocket;
    957     }
    958     if (rtpSock == NULL)
    959     {
    960         _lastError = kSocketInvalid;
    961         return -1;
    962     }
    963     if(!rtpSock->ValidHandle())
    964     {
    965         _lastError = kSocketInvalid;
    966         return -1;
    967     }
    968     if(_ptrSendRtcpSocket)
    969     {
    970         rtcpSock = _ptrSendRtcpSocket;
    971     }else
    972     {
    973         rtcpSock = _ptrRtcpSocket;
    974     }
    975     if (rtcpSock == NULL)
    976     {
    977         _lastError = kSocketInvalid;
    978         return -1;
    979     }
    980     if(!rtcpSock->ValidHandle())
    981     {
    982         _lastError = kSocketInvalid;
    983         return -1;
    984     }
    985 
    986 #if defined(_WIN32)
    987     if (rtpSock->SetPCP(PCP) != 0)
    988     {
    989         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    990                      "Could not set PCP value on RTP socket");
    991         _lastError = kPcpError;
    992         return -1;
    993     }
    994     if (rtcpSock->SetPCP(PCP) != 0)
    995     {
    996         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
    997                      "Could not set PCP value on RTCP socket");
    998         _lastError = kPcpError;
    999         return -1;
   1000     }
   1001 
   1002 #elif defined(WEBRTC_LINUX)
   1003     if (!rtpSock->SetSockopt(SOL_SOCKET, SO_PRIORITY, (int8_t*) &PCP,
   1004                              sizeof(PCP)))
   1005     {
   1006         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1007                      "Could not SetSockopt PCP value on RTP socket");
   1008         _lastError = kPcpError;
   1009         return -1;
   1010     }
   1011     if (!rtcpSock->SetSockopt(SOL_SOCKET, SO_PRIORITY, (int8_t*) &PCP,
   1012                               sizeof(PCP)))
   1013     {
   1014         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1015                      "Could not SetSockopt PCP value on RTCP socket");
   1016         _lastError = kPcpError;
   1017         return -1;
   1018     }
   1019 #else
   1020     // Not supported on other platforms (WEBRTC_MAC)
   1021     _lastError = kPcpError;
   1022     return -1;
   1023 #endif
   1024     _pcp = PCP;
   1025     return 0;
   1026 }
   1027 
   1028 int32_t UdpTransportImpl::PCP(int32_t& PCP) const
   1029 {
   1030     CriticalSectionScoped cs(_crit);
   1031     PCP = _pcp;
   1032     return 0;
   1033 }
   1034 
   1035 bool UdpTransportImpl::SetSockOptUsed()
   1036 {
   1037     return _useSetSockOpt;
   1038 }
   1039 
   1040 int32_t UdpTransportImpl::EnableIpV6() {
   1041 
   1042   CriticalSectionScoped cs(_crit);
   1043   const bool initialized = (_ptrSendRtpSocket || _ptrRtpSocket);
   1044 
   1045   if (_ipV6Enabled) {
   1046     return 0;
   1047   }
   1048   if (initialized) {
   1049     _lastError = kIpVersion6Error;
   1050     return -1;
   1051   }
   1052   _ipV6Enabled = true;
   1053   return 0;
   1054 }
   1055 
   1056 int32_t UdpTransportImpl::FilterIP(
   1057     char filterIPAddress[kIpAddressVersion6Length]) const
   1058 {
   1059 
   1060     if(filterIPAddress == NULL)
   1061     {
   1062         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1063                      "FilterIP: Invalid argument");
   1064         return -1;
   1065     }
   1066     if(_filterIPAddress._sockaddr_storage.sin_family == 0)
   1067     {
   1068         WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "No Filter configured");
   1069         return -1;
   1070     }
   1071     CriticalSectionScoped cs(_critFilter);
   1072     uint32_t ipSize = kIpAddressVersion6Length;
   1073     uint16_t sourcePort;
   1074     return IPAddress(_filterIPAddress, filterIPAddress, ipSize, sourcePort);
   1075 }
   1076 
   1077 int32_t UdpTransportImpl::SetFilterIP(
   1078     const char filterIPAddress[kIpAddressVersion6Length])
   1079 {
   1080     if(filterIPAddress == NULL)
   1081     {
   1082         memset(&_filterIPAddress, 0, sizeof(_filterIPAddress));
   1083         WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, "Filter IP reset");
   1084         return 0;
   1085     }
   1086     CriticalSectionScoped cs(_critFilter);
   1087     if (_ipV6Enabled)
   1088     {
   1089         _filterIPAddress._sockaddr_storage.sin_family = AF_INET6;
   1090 
   1091         if (InetPresentationToNumeric(
   1092                 AF_INET6,
   1093                 filterIPAddress,
   1094                 &_filterIPAddress._sockaddr_in6.sin6_addr) < 0)
   1095         {
   1096             WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "Failed to set\
   1097  filter IP for IPv6");
   1098             _lastError = FILTER_ERROR;
   1099             return -1;
   1100         }
   1101     }
   1102     else
   1103     {
   1104         _filterIPAddress._sockaddr_storage.sin_family = AF_INET;
   1105 
   1106         if(InetPresentationToNumeric(
   1107                AF_INET,
   1108                filterIPAddress,
   1109                &_filterIPAddress._sockaddr_in.sin_addr) < 0)
   1110         {
   1111             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1112                          "Failed to set filter IP for IPv4");
   1113             _lastError = FILTER_ERROR;
   1114             return -1;
   1115         }
   1116     }
   1117     WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, "Filter IP set");
   1118     return 0;
   1119 }
   1120 
   1121 int32_t UdpTransportImpl::SetFilterPorts(uint16_t rtpFilterPort,
   1122                                          uint16_t rtcpFilterPort)
   1123 {
   1124     CriticalSectionScoped cs(_critFilter);
   1125     _rtpFilterPort = rtpFilterPort;
   1126     _rtcpFilterPort = rtcpFilterPort;
   1127     return 0;
   1128 }
   1129 
   1130 bool UdpTransportImpl::SendSocketsInitialized() const
   1131 {
   1132     CriticalSectionScoped cs(_crit);
   1133     if(_ptrSendRtpSocket)
   1134     {
   1135         return true;
   1136     }
   1137     if(_destPort !=0)
   1138     {
   1139         return true;
   1140     }
   1141     return false;
   1142 }
   1143 
   1144 bool UdpTransportImpl::ReceiveSocketsInitialized() const
   1145 {
   1146     if(_ptrRtpSocket)
   1147     {
   1148         return true;
   1149     }
   1150     return false;
   1151 }
   1152 
   1153 bool UdpTransportImpl::SourcePortsInitialized() const
   1154 {
   1155     if(_ptrSendRtpSocket)
   1156     {
   1157         return true;
   1158     }
   1159     return false;
   1160 }
   1161 
   1162 bool UdpTransportImpl::IpV6Enabled() const
   1163 {
   1164     WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, "%s", __FUNCTION__);
   1165     return _ipV6Enabled;
   1166 }
   1167 
   1168 void UdpTransportImpl::BuildRemoteRTPAddr()
   1169 {
   1170     if(_ipV6Enabled)
   1171     {
   1172 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1173         _remoteRTPAddr.sin_length = 0;
   1174         _remoteRTPAddr.sin_family = PF_INET6;
   1175 #else
   1176         _remoteRTPAddr._sockaddr_storage.sin_family = PF_INET6;
   1177 #endif
   1178 
   1179         _remoteRTPAddr._sockaddr_in6.sin6_flowinfo=0;
   1180         _remoteRTPAddr._sockaddr_in6.sin6_scope_id=0;
   1181         _remoteRTPAddr._sockaddr_in6.sin6_port = Htons(_destPort);
   1182         InetPresentationToNumeric(AF_INET6,_destIP,
   1183                                   &_remoteRTPAddr._sockaddr_in6.sin6_addr);
   1184     } else
   1185     {
   1186 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1187         _remoteRTPAddr.sin_length = 0;
   1188         _remoteRTPAddr.sin_family = PF_INET;
   1189 #else
   1190         _remoteRTPAddr._sockaddr_storage.sin_family = PF_INET;
   1191 #endif
   1192         _remoteRTPAddr._sockaddr_in.sin_port = Htons(_destPort);
   1193         _remoteRTPAddr._sockaddr_in.sin_addr = InetAddrIPV4(_destIP);
   1194     }
   1195 }
   1196 
   1197 void UdpTransportImpl::BuildRemoteRTCPAddr()
   1198 {
   1199     if(_ipV6Enabled)
   1200     {
   1201 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1202         _remoteRTCPAddr.sin_length = 0;
   1203         _remoteRTCPAddr.sin_family = PF_INET6;
   1204 #else
   1205         _remoteRTCPAddr._sockaddr_storage.sin_family = PF_INET6;
   1206 #endif
   1207 
   1208         _remoteRTCPAddr._sockaddr_in6.sin6_flowinfo=0;
   1209         _remoteRTCPAddr._sockaddr_in6.sin6_scope_id=0;
   1210         _remoteRTCPAddr._sockaddr_in6.sin6_port = Htons(_destPortRTCP);
   1211         InetPresentationToNumeric(AF_INET6,_destIP,
   1212                                   &_remoteRTCPAddr._sockaddr_in6.sin6_addr);
   1213 
   1214     } else
   1215     {
   1216 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1217         _remoteRTCPAddr.sin_length = 0;
   1218         _remoteRTCPAddr.sin_family = PF_INET;
   1219 #else
   1220         _remoteRTCPAddr._sockaddr_storage.sin_family = PF_INET;
   1221 #endif
   1222         _remoteRTCPAddr._sockaddr_in.sin_port = Htons(_destPortRTCP);
   1223         _remoteRTCPAddr._sockaddr_in.sin_addr= InetAddrIPV4(_destIP);
   1224     }
   1225 }
   1226 
   1227 UdpTransportImpl::ErrorCode UdpTransportImpl::BindRTPSendSocket()
   1228 {
   1229     if(!_ptrSendRtpSocket)
   1230     {
   1231         return kSocketInvalid;
   1232     }
   1233     if(!_ptrSendRtpSocket->ValidHandle())
   1234     {
   1235         return kIpAddressInvalid;
   1236     }
   1237     if(_ipV6Enabled)
   1238     {
   1239 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1240         _localRTPAddr.sin_length = 0;
   1241         _localRTPAddr.sin_family = PF_INET6;
   1242 #else
   1243         _localRTPAddr._sockaddr_storage.sin_family = PF_INET6;
   1244 #endif
   1245         _localRTPAddr._sockaddr_in6.sin6_flowinfo=0;
   1246         _localRTPAddr._sockaddr_in6.sin6_scope_id=0;
   1247         _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[0] =
   1248             0; // = INADDR_ANY
   1249         _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[1] =
   1250             0;
   1251         _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[2] =
   1252             0;
   1253         _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[3] =
   1254             0;
   1255         _localRTPAddr._sockaddr_in6.sin6_port = Htons(_srcPort);
   1256         if(_ptrSendRtpSocket->Bind(_localRTPAddr) == false)
   1257         {
   1258             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1259                          "Failed to bind to port:%d ", _srcPort);
   1260             return kFailedToBindPort;
   1261         }
   1262 
   1263     } else {
   1264 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1265         _localRTPAddr.sin_length = 0;
   1266         _localRTPAddr.sin_family = PF_INET;
   1267 #else
   1268         _localRTPAddr._sockaddr_storage.sin_family = PF_INET;
   1269 #endif
   1270         _localRTPAddr._sockaddr_in.sin_addr = 0;
   1271         _localRTPAddr._sockaddr_in.sin_port = Htons(_srcPort);
   1272         if(_ptrSendRtpSocket->Bind(_localRTPAddr) == false)
   1273         {
   1274             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1275                          "Failed to bind to port:%d ", _srcPort);
   1276             return kFailedToBindPort;
   1277         }
   1278     }
   1279     return kNoSocketError;
   1280 }
   1281 
   1282 UdpTransportImpl::ErrorCode UdpTransportImpl::BindRTCPSendSocket()
   1283 {
   1284     if(!_ptrSendRtcpSocket)
   1285     {
   1286         return kSocketInvalid;
   1287     }
   1288 
   1289     if(_ipV6Enabled)
   1290     {
   1291 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1292         _localRTCPAddr.sin_length = 0;
   1293         _localRTCPAddr.sin_family = PF_INET6;
   1294 #else
   1295         _localRTCPAddr._sockaddr_storage.sin_family = PF_INET6;
   1296 #endif
   1297         _localRTCPAddr._sockaddr_in6.sin6_flowinfo=0;
   1298         _localRTCPAddr._sockaddr_in6.sin6_scope_id=0;
   1299         _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[0] =
   1300             0; // = INADDR_ANY
   1301         _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[1] =
   1302             0;
   1303         _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[2] =
   1304             0;
   1305         _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[3] =
   1306             0;
   1307         _localRTCPAddr._sockaddr_in6.sin6_port = Htons(_srcPortRTCP);
   1308         if(_ptrSendRtcpSocket->Bind(_localRTCPAddr) == false)
   1309         {
   1310             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1311                          "Failed to bind to port:%d ", _srcPortRTCP);
   1312             return kFailedToBindPort;
   1313         }
   1314     } else {
   1315 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1316         _localRTCPAddr.sin_length = 0;
   1317         _localRTCPAddr.sin_family = PF_INET;
   1318 #else
   1319         _localRTCPAddr._sockaddr_storage.sin_family = PF_INET;
   1320 #endif
   1321         _localRTCPAddr._sockaddr_in.sin_addr= 0;
   1322         _localRTCPAddr._sockaddr_in.sin_port = Htons(_srcPortRTCP);
   1323         if(_ptrSendRtcpSocket->Bind(_localRTCPAddr) == false)
   1324         {
   1325             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1326                          "Failed to bind to port:%d ", _srcPortRTCP);
   1327             return kFailedToBindPort;
   1328         }
   1329     }
   1330     return kNoSocketError;
   1331 }
   1332 
   1333 UdpTransportImpl::ErrorCode UdpTransportImpl::BindLocalRTPSocket()
   1334 {
   1335     if(!_ptrRtpSocket)
   1336     {
   1337         return kSocketInvalid;
   1338     }
   1339     if(!IpV6Enabled())
   1340     {
   1341         SocketAddress recAddr;
   1342         memset(&recAddr, 0, sizeof(SocketAddress));
   1343         recAddr._sockaddr_storage.sin_family = AF_INET;
   1344 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1345         recAddr.sin_length = 0;
   1346         recAddr.sin_family = PF_INET;
   1347 #else
   1348         recAddr._sockaddr_storage.sin_family = PF_INET;
   1349 #endif
   1350         recAddr._sockaddr_in.sin_addr = InetAddrIPV4(_localIP);
   1351         recAddr._sockaddr_in.sin_port = Htons(_localPort);
   1352 
   1353         if (!_ptrRtpSocket->Bind(recAddr))
   1354         {
   1355             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1356                          "Failed to bind to port:%d ", _localPort);
   1357             return kFailedToBindPort;
   1358         }
   1359     }
   1360     else
   1361     {
   1362         SocketAddress stLclName;
   1363 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1364         stLclName.sin_lenght = 0;
   1365         stLclName.sin_family = PF_INET6;
   1366 #else
   1367         stLclName._sockaddr_storage.sin_family = PF_INET6;
   1368 #endif
   1369         InetPresentationToNumeric(AF_INET6,_localIP,
   1370                                   &stLclName._sockaddr_in6.sin6_addr);
   1371         stLclName._sockaddr_in6.sin6_port = Htons(_localPort);
   1372         stLclName._sockaddr_in6.sin6_flowinfo = 0;
   1373         stLclName._sockaddr_in6.sin6_scope_id = 0;
   1374 
   1375         if (!_ptrRtpSocket->Bind(stLclName))
   1376         {
   1377             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1378                          "Failed to bind to port:%d ", _localPort);
   1379             return kFailedToBindPort;
   1380         }
   1381     }
   1382 
   1383     if(_localMulticastIP[0] != 0)
   1384     {
   1385         // Join the multicast group from which to receive datagrams.
   1386         struct ip_mreq mreq;
   1387         mreq.imr_multiaddr.s_addr = InetAddrIPV4(_localMulticastIP);
   1388         mreq.imr_interface.s_addr = INADDR_ANY;
   1389 
   1390         if (!_ptrRtpSocket->SetSockopt(IPPROTO_IP,IP_ADD_MEMBERSHIP,
   1391                                        (int8_t*)&mreq,sizeof (mreq)))
   1392         {
   1393            WEBRTC_TRACE(
   1394                 kTraceError,
   1395                 kTraceTransport,
   1396                 _id,
   1397                 "setsockopt() for multicast failed, not closing socket");
   1398         }else
   1399         {
   1400             WEBRTC_TRACE(kTraceInfo, kTraceTransport, _id,
   1401                          "multicast group successfully joined");
   1402         }
   1403     }
   1404     return kNoSocketError;
   1405 }
   1406 
   1407 UdpTransportImpl::ErrorCode UdpTransportImpl::BindLocalRTCPSocket()
   1408 {
   1409     if(!_ptrRtcpSocket)
   1410     {
   1411         return kSocketInvalid;
   1412     }
   1413     if(! IpV6Enabled())
   1414     {
   1415         SocketAddress recAddr;
   1416         memset(&recAddr, 0, sizeof(SocketAddress));
   1417 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1418         recAddr.sin_length = 0;
   1419         recAddr.sin_family = AF_INET;
   1420 #else
   1421         recAddr._sockaddr_storage.sin_family = AF_INET;
   1422 #endif
   1423         recAddr._sockaddr_in.sin_addr = InetAddrIPV4(_localIP);
   1424         recAddr._sockaddr_in.sin_port = Htons(_localPortRTCP);
   1425 
   1426         if (!_ptrRtcpSocket->Bind(recAddr))
   1427         {
   1428             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1429                          "Failed to bind to port:%d ", _localPortRTCP);
   1430             return kFailedToBindPort;
   1431         }
   1432     }
   1433     else
   1434     {
   1435         SocketAddress stLclName;
   1436 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1437         stLclName.sin_length = 0;
   1438         stLclName.sin_family = PF_INET6;
   1439 #else
   1440         stLclName._sockaddr_storage.sin_family = PF_INET6;
   1441 #endif
   1442         stLclName._sockaddr_in6.sin6_flowinfo = 0;
   1443         stLclName._sockaddr_in6.sin6_scope_id = 0;
   1444         stLclName._sockaddr_in6.sin6_port = Htons(_localPortRTCP);
   1445 
   1446         InetPresentationToNumeric(AF_INET6,_localIP,
   1447                                   &stLclName._sockaddr_in6.sin6_addr);
   1448         if (!_ptrRtcpSocket->Bind(stLclName))
   1449         {
   1450             WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id,
   1451                          "Failed to bind to port:%d ", _localPortRTCP);
   1452             return kFailedToBindPort;
   1453         }
   1454     }
   1455     if(_localMulticastIP[0] != 0)
   1456     {
   1457         // Join the multicast group from which to receive datagrams.
   1458         struct ip_mreq mreq;
   1459         mreq.imr_multiaddr.s_addr = InetAddrIPV4(_localMulticastIP);
   1460         mreq.imr_interface.s_addr = INADDR_ANY;
   1461 
   1462         if (!_ptrRtcpSocket->SetSockopt(IPPROTO_IP,IP_ADD_MEMBERSHIP,
   1463                                         (int8_t*)&mreq,sizeof (mreq)))
   1464         {
   1465             WEBRTC_TRACE(
   1466                 kTraceError,
   1467                 kTraceTransport,
   1468                 _id,
   1469                 "setsockopt() for multicast failed, not closing socket");
   1470         }else
   1471         {
   1472             WEBRTC_TRACE(kTraceInfo, kTraceTransport, _id,
   1473                          "multicast group successfully joined");
   1474         }
   1475     }
   1476     return kNoSocketError;
   1477 }
   1478 
   1479 int32_t UdpTransportImpl::InitializeSourcePorts(uint16_t rtpPort,
   1480                                                 uint16_t rtcpPort)
   1481 {
   1482 
   1483     if(rtpPort == 0)
   1484     {
   1485         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1486                      "InitializeSourcePorts port 0 not allowed");
   1487         _lastError = kPortInvalid;
   1488         return -1;
   1489     }
   1490 
   1491     CriticalSectionScoped cs(_crit);
   1492 
   1493     CloseSendSockets();
   1494 
   1495     if(_mgr == NULL)
   1496     {
   1497         return -1;
   1498     }
   1499 
   1500     _srcPort = rtpPort;
   1501     if(rtcpPort == 0)
   1502     {
   1503         _srcPortRTCP = rtpPort+1;
   1504     } else
   1505     {
   1506         _srcPortRTCP = rtcpPort;
   1507     }
   1508     _useSetSockOpt =false;
   1509     _tos=0;
   1510     _pcp=0;
   1511 
   1512     _ptrSendRtpSocket = _socket_creator->CreateSocket(_id, _mgr, NULL, NULL,
   1513                                         IpV6Enabled(), false);
   1514     _ptrSendRtcpSocket = _socket_creator->CreateSocket(_id, _mgr, NULL, NULL,
   1515                                          IpV6Enabled(), false);
   1516 
   1517     ErrorCode retVal = BindRTPSendSocket();
   1518     if(retVal != kNoSocketError)
   1519     {
   1520         _lastError = retVal;
   1521         return -1;
   1522     }
   1523     retVal = BindRTCPSendSocket();
   1524     if(retVal != kNoSocketError)
   1525     {
   1526         _lastError = retVal;
   1527         return -1;
   1528     }
   1529     return 0;
   1530 }
   1531 
   1532 int32_t UdpTransportImpl::SourcePorts(uint16_t& rtpPort,
   1533                                       uint16_t& rtcpPort) const
   1534 {
   1535     CriticalSectionScoped cs(_crit);
   1536 
   1537     rtpPort  = (_srcPort != 0) ? _srcPort : _localPort;
   1538     rtcpPort = (_srcPortRTCP != 0) ? _srcPortRTCP : _localPortRTCP;
   1539     return 0;
   1540 }
   1541 
   1542 
   1543 #ifdef _WIN32
   1544 int32_t UdpTransportImpl::StartReceiving(uint32_t numberOfSocketBuffers)
   1545 #else
   1546 int32_t UdpTransportImpl::StartReceiving(uint32_t /*numberOfSocketBuffers*/)
   1547 #endif
   1548 {
   1549     CriticalSectionScoped cs(_crit);
   1550     if(_receiving)
   1551     {
   1552         return 0;
   1553     }
   1554     if(_ptrRtpSocket)
   1555     {
   1556 #ifdef _WIN32
   1557         if(!_ptrRtpSocket->StartReceiving(numberOfSocketBuffers))
   1558 #else
   1559         if(!_ptrRtpSocket->StartReceiving())
   1560 #endif
   1561         {
   1562             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1563                          "Failed to start receive on RTP socket");
   1564             _lastError = kStartReceiveError;
   1565             return -1;
   1566         }
   1567     }
   1568     if(_ptrRtcpSocket)
   1569     {
   1570         if(!_ptrRtcpSocket->StartReceiving())
   1571         {
   1572             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1573                          "Failed to start receive on RTCP socket");
   1574             _lastError = kStartReceiveError;
   1575             return -1;
   1576         }
   1577     }
   1578     if( _ptrRtpSocket == NULL &&
   1579         _ptrRtcpSocket == NULL)
   1580     {
   1581         WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1582                      "Failed to StartReceiving, no socket initialized");
   1583         _lastError = kStartReceiveError;
   1584         return -1;
   1585     }
   1586     _receiving = true;
   1587     return 0;
   1588 }
   1589 
   1590 bool UdpTransportImpl::Receiving() const
   1591 {
   1592    return _receiving;
   1593 }
   1594 
   1595 int32_t UdpTransportImpl::StopReceiving()
   1596 {
   1597 
   1598     CriticalSectionScoped cs(_crit);
   1599 
   1600     _receiving = false;
   1601 
   1602     if (_ptrRtpSocket)
   1603     {
   1604         if (!_ptrRtpSocket->StopReceiving())
   1605         {
   1606             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1607                          "Failed to stop receiving on RTP socket");
   1608             _lastError = kStopReceiveError;
   1609             return -1;
   1610         }
   1611     }
   1612     if (_ptrRtcpSocket)
   1613     {
   1614         if (!_ptrRtcpSocket->StopReceiving())
   1615         {
   1616             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1617                          "Failed to stop receiving on RTCP socket");
   1618             _lastError = kStopReceiveError;
   1619             return -1;
   1620         }
   1621     }
   1622     return 0;
   1623 }
   1624 
   1625 int32_t UdpTransportImpl::InitializeSendSockets(
   1626     const char* ipaddr,
   1627     const uint16_t rtpPort,
   1628     const uint16_t rtcpPort)
   1629 {
   1630     {
   1631         CriticalSectionScoped cs(_crit);
   1632         _destPort = rtpPort;
   1633         if(rtcpPort == 0)
   1634         {
   1635             _destPortRTCP = _destPort+1;
   1636         } else
   1637         {
   1638             _destPortRTCP = rtcpPort;
   1639         }
   1640 
   1641         if(ipaddr == NULL)
   1642         {
   1643             if (!IsIpAddressValid(_destIP, IpV6Enabled()))
   1644             {
   1645                 _destPort = 0;
   1646                 _destPortRTCP = 0;
   1647                 _lastError = kIpAddressInvalid;
   1648                 return -1;
   1649             }
   1650         } else
   1651         {
   1652             if (IsIpAddressValid(ipaddr, IpV6Enabled()))
   1653             {
   1654                 strncpy(
   1655                     _destIP,
   1656                     ipaddr,
   1657                     IpV6Enabled() ? kIpAddressVersion6Length :
   1658                     kIpAddressVersion4Length);
   1659             } else {
   1660                 _destPort = 0;
   1661                 _destPortRTCP = 0;
   1662                 _lastError = kIpAddressInvalid;
   1663                 return -1;
   1664             }
   1665         }
   1666         BuildRemoteRTPAddr();
   1667         BuildRemoteRTCPAddr();
   1668     }
   1669 
   1670     if (_ipV6Enabled)
   1671     {
   1672         if (_qos)
   1673         {
   1674             WEBRTC_TRACE(
   1675                 kTraceWarning,
   1676                 kTraceTransport,
   1677                 _id,
   1678                 "QOS is enabled but will be ignored since IPv6 is enabled");
   1679         }
   1680     }else
   1681     {
   1682         // TODO (grunell): Multicast support is experimantal.
   1683 
   1684         // Put the first digit of the remote address in val.
   1685         int32_t val = ntohl(_remoteRTPAddr._sockaddr_in.sin_addr)>> 24;
   1686 
   1687         if((val > 223) && (val < 240))
   1688         {
   1689             // Multicast address.
   1690             CriticalSectionScoped cs(_crit);
   1691 
   1692             UdpSocketWrapper* rtpSock = (_ptrSendRtpSocket ?
   1693                                          _ptrSendRtpSocket : _ptrRtpSocket);
   1694             if (!rtpSock || !rtpSock->ValidHandle())
   1695             {
   1696                 _lastError = kSocketInvalid;
   1697                 return -1;
   1698             }
   1699             UdpSocketWrapper* rtcpSock = (_ptrSendRtcpSocket ?
   1700                                           _ptrSendRtcpSocket : _ptrRtcpSocket);
   1701             if (!rtcpSock || !rtcpSock->ValidHandle())
   1702             {
   1703                 _lastError = kSocketInvalid;
   1704                 return -1;
   1705             }
   1706 
   1707             // Set Time To Live to same region
   1708             int32_t iOptVal = 64;
   1709             if (!rtpSock->SetSockopt(IPPROTO_IP, IP_MULTICAST_TTL,
   1710                                      (int8_t*)&iOptVal,
   1711                                      sizeof (int32_t)))
   1712             {
   1713                 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1714                              "setsockopt for multicast error on RTP socket");
   1715                 _ptrRtpSocket->CloseBlocking();
   1716                 _ptrRtpSocket = NULL;
   1717                 _lastError = kMulticastAddressInvalid;
   1718                 return -1;
   1719             }
   1720             if (!rtcpSock->SetSockopt(IPPROTO_IP, IP_MULTICAST_TTL,
   1721                                       (int8_t*)&iOptVal,
   1722                                       sizeof (int32_t)))
   1723             {
   1724                 WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1725                              "setsockopt for multicast error on RTCP socket");
   1726                 _ptrRtpSocket->CloseBlocking();
   1727                 _ptrRtpSocket = NULL;
   1728                 _lastError = kMulticastAddressInvalid;
   1729                 return -1;
   1730             }
   1731         }
   1732     }
   1733     return 0;
   1734 }
   1735 
   1736 void UdpTransportImpl::BuildSockaddrIn(uint16_t portnr,
   1737                                        const char* ip,
   1738                                        SocketAddress& remoteAddr) const
   1739 {
   1740     if(_ipV6Enabled)
   1741     {
   1742 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1743         remoteAddr.sin_length = 0;
   1744         remoteAddr.sin_family = PF_INET6;
   1745 #else
   1746         remoteAddr._sockaddr_storage.sin_family = PF_INET6;
   1747 #endif
   1748         remoteAddr._sockaddr_in6.sin6_port = Htons(portnr);
   1749         InetPresentationToNumeric(AF_INET6, ip,
   1750                                   &remoteAddr._sockaddr_in6.sin6_addr);
   1751         remoteAddr._sockaddr_in6.sin6_flowinfo=0;
   1752         remoteAddr._sockaddr_in6.sin6_scope_id=0;
   1753     } else
   1754     {
   1755 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   1756         remoteAddr.sin_length = 0;
   1757         remoteAddr.sin_family = PF_INET;
   1758 #else
   1759         remoteAddr._sockaddr_storage.sin_family = PF_INET;
   1760 #endif
   1761         remoteAddr._sockaddr_in.sin_port = Htons(portnr);
   1762         remoteAddr._sockaddr_in.sin_addr= InetAddrIPV4(
   1763             const_cast<char*>(ip));
   1764     }
   1765 }
   1766 
   1767 int32_t UdpTransportImpl::SendRaw(const int8_t *data,
   1768                                   size_t length,
   1769                                   int32_t isRTCP,
   1770                                   uint16_t portnr,
   1771                                   const char* ip)
   1772 {
   1773     CriticalSectionScoped cs(_crit);
   1774     if(isRTCP)
   1775     {
   1776         UdpSocketWrapper* rtcpSock = NULL;
   1777         if(_ptrSendRtcpSocket)
   1778         {
   1779             rtcpSock = _ptrSendRtcpSocket;
   1780         } else if(_ptrRtcpSocket)
   1781         {
   1782             rtcpSock = _ptrRtcpSocket;
   1783         } else
   1784         {
   1785             return -1;
   1786         }
   1787         if(portnr == 0 && ip == NULL)
   1788         {
   1789             return rtcpSock->SendTo(data,length,_remoteRTCPAddr);
   1790 
   1791         } else if(portnr != 0 && ip != NULL)
   1792         {
   1793             SocketAddress remoteAddr;
   1794             BuildSockaddrIn(portnr, ip, remoteAddr);
   1795             return rtcpSock->SendTo(data,length,remoteAddr);
   1796         } else if(ip != NULL)
   1797         {
   1798             SocketAddress remoteAddr;
   1799             BuildSockaddrIn(_destPortRTCP, ip, remoteAddr);
   1800             return rtcpSock->SendTo(data,length,remoteAddr);
   1801         } else
   1802         {
   1803             SocketAddress remoteAddr;
   1804             BuildSockaddrIn(portnr, _destIP, remoteAddr);
   1805             return rtcpSock->SendTo(data,length,remoteAddr);
   1806         }
   1807     } else {
   1808         UdpSocketWrapper* rtpSock = NULL;
   1809         if(_ptrSendRtpSocket)
   1810         {
   1811             rtpSock = _ptrSendRtpSocket;
   1812 
   1813         } else if(_ptrRtpSocket)
   1814         {
   1815             rtpSock = _ptrRtpSocket;
   1816         } else
   1817         {
   1818             return -1;
   1819         }
   1820         if(portnr == 0 && ip == NULL)
   1821         {
   1822             return rtpSock->SendTo(data,length,_remoteRTPAddr);
   1823 
   1824         } else if(portnr != 0 && ip != NULL)
   1825         {
   1826             SocketAddress remoteAddr;
   1827             BuildSockaddrIn(portnr, ip, remoteAddr);
   1828             return rtpSock->SendTo(data,length,remoteAddr);
   1829         } else if(ip != NULL)
   1830         {
   1831             SocketAddress remoteAddr;
   1832             BuildSockaddrIn(_destPort, ip, remoteAddr);
   1833             return rtpSock->SendTo(data,length,remoteAddr);
   1834         } else
   1835         {
   1836             SocketAddress remoteAddr;
   1837             BuildSockaddrIn(portnr, _destIP, remoteAddr);
   1838             return rtpSock->SendTo(data,length,remoteAddr);
   1839         }
   1840     }
   1841 }
   1842 
   1843 int32_t UdpTransportImpl::SendRTPPacketTo(const int8_t* data,
   1844                                           size_t length,
   1845                                           const SocketAddress& to)
   1846 {
   1847     CriticalSectionScoped cs(_crit);
   1848     if(_ptrSendRtpSocket)
   1849     {
   1850         return _ptrSendRtpSocket->SendTo(data,length,to);
   1851 
   1852     } else if(_ptrRtpSocket)
   1853     {
   1854         return _ptrRtpSocket->SendTo(data,length,to);
   1855     }
   1856     return -1;
   1857 }
   1858 
   1859 int32_t UdpTransportImpl::SendRTCPPacketTo(const int8_t* data,
   1860                                            size_t length,
   1861                                            const SocketAddress& to)
   1862 {
   1863 
   1864     CriticalSectionScoped cs(_crit);
   1865 
   1866     if(_ptrSendRtcpSocket)
   1867     {
   1868         return _ptrSendRtcpSocket->SendTo(data,length,to);
   1869 
   1870     } else if(_ptrRtcpSocket)
   1871     {
   1872         return _ptrRtcpSocket->SendTo(data,length,to);
   1873     }
   1874     return -1;
   1875 }
   1876 
   1877 int32_t UdpTransportImpl::SendRTPPacketTo(const int8_t* data,
   1878                                           size_t length,
   1879                                           const uint16_t rtpPort)
   1880 {
   1881     CriticalSectionScoped cs(_crit);
   1882     // Use the current SocketAdress but update it with rtpPort.
   1883     SocketAddress to;
   1884     memcpy(&to, &_remoteRTPAddr, sizeof(SocketAddress));
   1885 
   1886     if(_ipV6Enabled)
   1887     {
   1888         to._sockaddr_in6.sin6_port = Htons(rtpPort);
   1889     } else
   1890     {
   1891         to._sockaddr_in.sin_port = Htons(rtpPort);
   1892     }
   1893 
   1894     if(_ptrSendRtpSocket)
   1895     {
   1896         return _ptrSendRtpSocket->SendTo(data,length,to);
   1897 
   1898     } else if(_ptrRtpSocket)
   1899     {
   1900         return _ptrRtpSocket->SendTo(data,length,to);
   1901     }
   1902     return -1;
   1903 }
   1904 
   1905 int32_t UdpTransportImpl::SendRTCPPacketTo(const int8_t* data,
   1906                                            size_t length,
   1907                                            const uint16_t rtcpPort)
   1908 {
   1909     CriticalSectionScoped cs(_crit);
   1910 
   1911     // Use the current SocketAdress but update it with rtcpPort.
   1912     SocketAddress to;
   1913     memcpy(&to, &_remoteRTCPAddr, sizeof(SocketAddress));
   1914 
   1915     if(_ipV6Enabled)
   1916     {
   1917         to._sockaddr_in6.sin6_port = Htons(rtcpPort);
   1918     } else
   1919     {
   1920         to._sockaddr_in.sin_port = Htons(rtcpPort);
   1921     }
   1922 
   1923     if(_ptrSendRtcpSocket)
   1924     {
   1925         return _ptrSendRtcpSocket->SendTo(data,length,to);
   1926 
   1927     } else if(_ptrRtcpSocket)
   1928     {
   1929         return _ptrRtcpSocket->SendTo(data,length,to);
   1930     }
   1931     return -1;
   1932 }
   1933 
   1934 bool UdpTransportImpl::SendRtp(const uint8_t* data,
   1935                                size_t length,
   1936                                const PacketOptions& packet_options) {
   1937     WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, "%s", __FUNCTION__);
   1938 
   1939     CriticalSectionScoped cs(_crit);
   1940 
   1941     if(_destIP[0] == 0)
   1942     {
   1943         return false;
   1944     }
   1945     if(_destPort == 0)
   1946     {
   1947         return false;
   1948     }
   1949 
   1950     // Create socket if it hasn't been set up already.
   1951     // TODO (hellner): why not fail here instead. Sockets not being initialized
   1952     //                 indicates that there is a problem somewhere.
   1953     if( _ptrSendRtpSocket == NULL &&
   1954         _ptrRtpSocket == NULL)
   1955     {
   1956         WEBRTC_TRACE(
   1957             kTraceStateInfo,
   1958             kTraceTransport,
   1959             _id,
   1960             "Creating RTP socket since no receive or source socket is\
   1961  configured");
   1962 
   1963         _ptrRtpSocket = _socket_creator->CreateSocket(_id, _mgr, this,
   1964                                         IncomingRTPCallback,
   1965                                         IpV6Enabled(), false);
   1966 
   1967         // Don't bind to a specific IP address.
   1968         if(! IpV6Enabled())
   1969         {
   1970             strncpy(_localIP, "0.0.0.0",16);
   1971         } else
   1972         {
   1973             strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000",
   1974                     kIpAddressVersion6Length);
   1975         }
   1976         _localPort = _destPort;
   1977 
   1978         ErrorCode retVal = BindLocalRTPSocket();
   1979         if(retVal != kNoSocketError)
   1980         {
   1981             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1982                          "SendPacket() failed to bind RTP socket");
   1983             _lastError = retVal;
   1984             CloseReceiveSockets();
   1985             return false;
   1986         }
   1987     }
   1988 
   1989     if(_ptrSendRtpSocket)
   1990     {
   1991         return _ptrSendRtpSocket->SendTo((const int8_t*)data, length,
   1992                                          _remoteRTPAddr) >= 0;
   1993 
   1994     } else if(_ptrRtpSocket)
   1995     {
   1996         return _ptrRtpSocket->SendTo((const int8_t*)data, length,
   1997                                      _remoteRTPAddr) >= 0;
   1998     }
   1999     return false;
   2000 }
   2001 
   2002 bool UdpTransportImpl::SendRtcp(const uint8_t* data, size_t length) {
   2003     CriticalSectionScoped cs(_crit);
   2004     if(_destIP[0] == 0)
   2005     {
   2006         return false;
   2007     }
   2008     if(_destPortRTCP == 0)
   2009     {
   2010         return false;
   2011     }
   2012 
   2013     // Create socket if it hasn't been set up already.
   2014     // TODO (hellner): why not fail here instead. Sockets not being initialized
   2015     //                 indicates that there is a problem somewhere.
   2016     if( _ptrSendRtcpSocket == NULL &&
   2017         _ptrRtcpSocket == NULL)
   2018     {
   2019         WEBRTC_TRACE(
   2020             kTraceStateInfo,
   2021             kTraceTransport,
   2022             _id,
   2023             "Creating RTCP socket since no receive or source socket is\
   2024  configured");
   2025 
   2026         _ptrRtcpSocket = _socket_creator->CreateSocket(_id, _mgr, this,
   2027                                          IncomingRTCPCallback,
   2028                                          IpV6Enabled(), false);
   2029 
   2030         // Don't bind to a specific IP address.
   2031         if(! IpV6Enabled())
   2032         {
   2033             strncpy(_localIP, "0.0.0.0",16);
   2034         } else
   2035         {
   2036             strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000",
   2037                     kIpAddressVersion6Length);
   2038         }
   2039         _localPortRTCP = _destPortRTCP;
   2040 
   2041         ErrorCode retVal = BindLocalRTCPSocket();
   2042         if(retVal != kNoSocketError)
   2043         {
   2044             _lastError = retVal;
   2045             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   2046                          "SendRtcp() failed to bind RTCP socket");
   2047             CloseReceiveSockets();
   2048             return false;
   2049         }
   2050     }
   2051 
   2052     if(_ptrSendRtcpSocket)
   2053     {
   2054         return _ptrSendRtcpSocket->SendTo((const int8_t*)data, length,
   2055                                           _remoteRTCPAddr) >= 0;
   2056     } else if(_ptrRtcpSocket)
   2057     {
   2058         return _ptrRtcpSocket->SendTo((const int8_t*)data, length,
   2059                                       _remoteRTCPAddr) >= 0;
   2060     }
   2061     return false;
   2062 }
   2063 
   2064 int32_t UdpTransportImpl::SetSendIP(const char* ipaddr)
   2065 {
   2066     if(!IsIpAddressValid(ipaddr,IpV6Enabled()))
   2067     {
   2068         return kIpAddressInvalid;
   2069     }
   2070     CriticalSectionScoped cs(_crit);
   2071     strncpy(_destIP, ipaddr,kIpAddressVersion6Length);
   2072     BuildRemoteRTPAddr();
   2073     BuildRemoteRTCPAddr();
   2074     return 0;
   2075 }
   2076 
   2077 int32_t UdpTransportImpl::SetSendPorts(uint16_t rtpPort, uint16_t rtcpPort)
   2078 {
   2079     CriticalSectionScoped cs(_crit);
   2080     _destPort = rtpPort;
   2081     if(rtcpPort == 0)
   2082     {
   2083         _destPortRTCP = _destPort+1;
   2084     } else
   2085     {
   2086         _destPortRTCP = rtcpPort;
   2087     }
   2088     BuildRemoteRTPAddr();
   2089     BuildRemoteRTCPAddr();
   2090     return 0;
   2091 }
   2092 
   2093 void UdpTransportImpl::IncomingRTPCallback(CallbackObj obj,
   2094                                            const int8_t* rtpPacket,
   2095                                            size_t rtpPacketLength,
   2096                                            const SocketAddress* from)
   2097 {
   2098     if (rtpPacket && rtpPacketLength > 0)
   2099     {
   2100         UdpTransportImpl* socketTransport = (UdpTransportImpl*) obj;
   2101         socketTransport->IncomingRTPFunction(rtpPacket, rtpPacketLength, from);
   2102     }
   2103 }
   2104 
   2105 void UdpTransportImpl::IncomingRTCPCallback(CallbackObj obj,
   2106                                             const int8_t* rtcpPacket,
   2107                                             size_t rtcpPacketLength,
   2108                                             const SocketAddress* from)
   2109 {
   2110     if (rtcpPacket && rtcpPacketLength > 0)
   2111     {
   2112         UdpTransportImpl* socketTransport = (UdpTransportImpl*) obj;
   2113         socketTransport->IncomingRTCPFunction(rtcpPacket, rtcpPacketLength,
   2114                                               from);
   2115     }
   2116 }
   2117 
   2118 void UdpTransportImpl::IncomingRTPFunction(const int8_t* rtpPacket,
   2119                                            size_t rtpPacketLength,
   2120                                            const SocketAddress* fromSocket)
   2121 {
   2122     char ipAddress[kIpAddressVersion6Length];
   2123     uint32_t ipAddressLength = kIpAddressVersion6Length;
   2124     uint16_t portNr = 0;
   2125 
   2126     {
   2127         CriticalSectionScoped cs(_critFilter);
   2128         if (FilterIPAddress(fromSocket) == false)
   2129         {
   2130             // Packet should be filtered out. Drop it.
   2131             WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2132                          "Incoming RTP packet blocked by IP filter");
   2133             return;
   2134         }
   2135 
   2136         if (IPAddressCached(*fromSocket, ipAddress, ipAddressLength, portNr) <
   2137             0)
   2138         {
   2139             WEBRTC_TRACE(
   2140                 kTraceError,
   2141                 kTraceTransport,
   2142                 _id,
   2143                 "UdpTransportImpl::IncomingRTPFunction - Cannot get sender\
   2144  information");
   2145         }else
   2146         {
   2147             // Make sure ipAddress is null terminated.
   2148             ipAddress[kIpAddressVersion6Length - 1] = 0;
   2149             strncpy(_fromIP, ipAddress, kIpAddressVersion6Length - 1);
   2150         }
   2151 
   2152         // Filter based on port.
   2153         if (_rtpFilterPort != 0 &&
   2154             _rtpFilterPort != portNr)
   2155         {
   2156             // Drop packet.
   2157             memset(_fromIP, 0, sizeof(_fromIP));
   2158             WEBRTC_TRACE(
   2159                 kTraceStream,
   2160                 kTraceTransport,
   2161                 _id,
   2162                 "Incoming RTP packet blocked by filter incoming from port:%d\
   2163  allowed port:%d",
   2164                 portNr,
   2165                 _rtpFilterPort);
   2166             return;
   2167         }
   2168         _fromPort = portNr;
   2169     }
   2170 
   2171     CriticalSectionScoped cs(_critPacketCallback);
   2172     if (_packetCallback)
   2173     {
   2174         WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2175             "Incoming RTP packet from ip:%s port:%d", ipAddress, portNr);
   2176         _packetCallback->IncomingRTPPacket(rtpPacket, rtpPacketLength,
   2177                                            ipAddress, portNr);
   2178     }
   2179 }
   2180 
   2181 void UdpTransportImpl::IncomingRTCPFunction(const int8_t* rtcpPacket,
   2182                                             size_t rtcpPacketLength,
   2183                                             const SocketAddress* fromSocket)
   2184 {
   2185     char ipAddress[kIpAddressVersion6Length];
   2186     uint32_t ipAddressLength = kIpAddressVersion6Length;
   2187     uint16_t portNr = 0;
   2188 
   2189     {
   2190         CriticalSectionScoped cs(_critFilter);
   2191         if (FilterIPAddress(fromSocket) == false)
   2192         {
   2193             // Packet should be filtered out. Drop it.
   2194             WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2195                          "Incoming RTCP packet blocked by IP filter");
   2196             return;
   2197         }
   2198         if (IPAddress(*fromSocket, ipAddress, ipAddressLength, portNr) < 0)
   2199         {
   2200             WEBRTC_TRACE(
   2201                 kTraceError,
   2202                 kTraceTransport,
   2203                 _id,
   2204                 "UdpTransportImpl::IncomingRTCPFunction - Cannot get sender\
   2205  information");
   2206         }else {
   2207             // Make sure ipAddress is null terminated.
   2208             ipAddress[kIpAddressVersion6Length - 1] = 0;
   2209             strncpy(_fromIP, ipAddress, kIpAddressVersion6Length - 1);
   2210         }
   2211 
   2212         // Filter based on port.
   2213         if (_rtcpFilterPort != 0 &&
   2214             _rtcpFilterPort != portNr)
   2215         {
   2216             // Drop packet.
   2217             WEBRTC_TRACE(
   2218                 kTraceStream,
   2219                 kTraceTransport,
   2220                 _id,
   2221                 "Incoming RTCP packet blocked by filter incoming from port:%d\
   2222  allowed port:%d",
   2223                 portNr,
   2224                 _rtpFilterPort);
   2225             return;
   2226         }
   2227         _fromPortRTCP = portNr;
   2228     }
   2229 
   2230     CriticalSectionScoped cs(_critPacketCallback);
   2231     if (_packetCallback)
   2232     {
   2233         WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2234                      "Incoming RTCP packet from ip:%s port:%d", ipAddress,
   2235                      portNr);
   2236         _packetCallback->IncomingRTCPPacket(rtcpPacket, rtcpPacketLength,
   2237                                             ipAddress, portNr);
   2238     }
   2239 }
   2240 
   2241 bool UdpTransportImpl::FilterIPAddress(const SocketAddress* fromAddress)
   2242 {
   2243     if(fromAddress->_sockaddr_storage.sin_family == AF_INET)
   2244     {
   2245         if (_filterIPAddress._sockaddr_storage.sin_family == AF_INET)
   2246         {
   2247             // IP is stored in sin_addr.
   2248             if (_filterIPAddress._sockaddr_in.sin_addr != 0 &&
   2249                 (_filterIPAddress._sockaddr_in.sin_addr !=
   2250                  fromAddress->_sockaddr_in.sin_addr))
   2251             {
   2252                 return false;
   2253             }
   2254         }
   2255     }
   2256     else if(fromAddress->_sockaddr_storage.sin_family == AF_INET6)
   2257     {
   2258         if (_filterIPAddress._sockaddr_storage.sin_family == AF_INET6)
   2259         {
   2260             // IP is stored in sin_6addr.
   2261             for (int32_t i = 0; i < 4; i++)
   2262             {
   2263                 if (_filterIPAddress._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i] != 0 &&
   2264                     _filterIPAddress._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i] != fromAddress->_sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i])
   2265                 {
   2266                     return false;
   2267                 }
   2268             }
   2269         }
   2270     }
   2271     else
   2272     {
   2273       WEBRTC_TRACE(
   2274                 kTraceError,
   2275                 kTraceTransport,
   2276                 _id,
   2277                 "UdpTransportImpl::FilterIPAddress() unknown address family");
   2278         return false;
   2279     }
   2280     return true;
   2281 }
   2282 
   2283 void UdpTransportImpl::CloseReceiveSockets()
   2284 {
   2285     if(_ptrRtpSocket)
   2286     {
   2287         _ptrRtpSocket->CloseBlocking();
   2288         _ptrRtpSocket = NULL;
   2289     }
   2290     if(_ptrRtcpSocket)
   2291     {
   2292         _ptrRtcpSocket->CloseBlocking();
   2293         _ptrRtcpSocket = NULL;
   2294     }
   2295     _receiving = false;
   2296 }
   2297 
   2298 void UdpTransportImpl::CloseSendSockets()
   2299 {
   2300     if(_ptrSendRtpSocket)
   2301     {
   2302         _ptrSendRtpSocket->CloseBlocking();
   2303         _ptrSendRtpSocket = 0;
   2304     }
   2305     if(_ptrSendRtcpSocket)
   2306     {
   2307         _ptrSendRtcpSocket->CloseBlocking();
   2308         _ptrSendRtcpSocket = 0;
   2309     }
   2310 }
   2311 
   2312 uint16_t UdpTransport::Htons(const uint16_t port)
   2313 {
   2314     return htons(port);
   2315 }
   2316 
   2317 uint32_t UdpTransport::Htonl(const uint32_t a)
   2318 {
   2319     return htonl(a);
   2320 }
   2321 
   2322 uint32_t UdpTransport::InetAddrIPV4(const char* ip)
   2323 {
   2324     return ::inet_addr(ip);
   2325 }
   2326 
   2327 int32_t UdpTransport::InetPresentationToNumeric(int32_t af,
   2328                                                 const char* src,
   2329                                                 void* dst)
   2330 {
   2331 #if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
   2332     const int32_t result = inet_pton(af, src, dst);
   2333     return result > 0 ? 0 : -1;
   2334 
   2335 #elif defined(_WIN32)
   2336     SocketAddress temp;
   2337     int length=sizeof(SocketAddress);
   2338 
   2339     if(af == AF_INET)
   2340     {
   2341         int32_t result = WSAStringToAddressA(
   2342             (const LPSTR)src,
   2343             af,
   2344             0,
   2345             reinterpret_cast<struct sockaddr*>(&temp),
   2346             &length);
   2347         if(result != 0)
   2348         {
   2349             return -1;
   2350         }
   2351         memcpy(dst,&(temp._sockaddr_in.sin_addr),
   2352                sizeof(temp._sockaddr_in.sin_addr));
   2353         return 0;
   2354     }
   2355     else if(af == AF_INET6)
   2356     {
   2357         int32_t result = WSAStringToAddressA(
   2358             (const LPSTR)src,
   2359             af,
   2360             0,
   2361             reinterpret_cast<struct sockaddr*>(&temp),
   2362             &length);
   2363         if(result !=0)
   2364         {
   2365             return -1;
   2366         }
   2367         memcpy(dst,&(temp._sockaddr_in6.sin6_addr),
   2368                sizeof(temp._sockaddr_in6.sin6_addr));
   2369         return 0;
   2370 
   2371     }else
   2372     {
   2373         return -1;
   2374     }
   2375 #else
   2376     return -1;
   2377 #endif
   2378 }
   2379 
   2380 int32_t UdpTransport::LocalHostAddressIPV6(char n_localIP[16])
   2381 {
   2382 
   2383 #if defined(_WIN32)
   2384     struct addrinfo *result = NULL;
   2385     struct addrinfo *ptr = NULL;
   2386     struct addrinfo hints;
   2387 
   2388     ZeroMemory(&hints, sizeof(hints));
   2389     hints.ai_family = AF_INET6;
   2390 
   2391     char szHostName[256] = "";
   2392     if(::gethostname(szHostName, sizeof(szHostName) - 1))
   2393     {
   2394         WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, "gethostname failed");
   2395         return -1;
   2396     }
   2397 
   2398     DWORD dwRetval = getaddrinfo(szHostName, NULL, &hints, &result);
   2399     if ( dwRetval != 0 )
   2400     {
   2401         WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
   2402                      "getaddrinfo failed, error:%d", dwRetval);
   2403         return -1;
   2404     }
   2405     for(ptr=result; ptr != NULL ;ptr=ptr->ai_next)
   2406     {
   2407         switch (ptr->ai_family)
   2408         {
   2409             case AF_INET6:
   2410                 {
   2411                     for(int i = 0; i< 16; i++)
   2412                     {
   2413                         n_localIP[i] = (*(SocketAddress*)ptr->ai_addr).
   2414                             _sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u8[i];
   2415                     }
   2416                     bool islocalIP = true;
   2417 
   2418                     for(int n = 0; n< 15; n++)
   2419                     {
   2420                         if(n_localIP[n] != 0)
   2421                         {
   2422                             islocalIP = false;
   2423                             break;
   2424                         }
   2425                     }
   2426 
   2427                     if(islocalIP && n_localIP[15] != 1)
   2428                     {
   2429                         islocalIP = false;
   2430                     }
   2431 
   2432                     if(islocalIP && ptr->ai_next)
   2433                     {
   2434                         continue;
   2435                     }
   2436                     if(n_localIP[0] == 0xfe &&
   2437                        n_localIP[1] == 0x80 && ptr->ai_next)
   2438                     {
   2439                         continue;
   2440                     }
   2441                     freeaddrinfo(result);
   2442                 }
   2443                 return 0;
   2444             default:
   2445                 break;
   2446         };
   2447     }
   2448     freeaddrinfo(result);
   2449     WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
   2450                  "getaddrinfo failed to find address");
   2451     return -1;
   2452 
   2453 #elif defined(WEBRTC_MAC)
   2454     struct ifaddrs* ptrIfAddrs = NULL;
   2455     struct ifaddrs* ptrIfAddrsStart = NULL;
   2456 
   2457     getifaddrs(&ptrIfAddrsStart);
   2458     ptrIfAddrs = ptrIfAddrsStart;
   2459     while(ptrIfAddrs)
   2460     {
   2461         if(ptrIfAddrs->ifa_addr->sa_family == AF_INET6)
   2462         {
   2463             const struct sockaddr_in6* sock_in6 =
   2464                 reinterpret_cast<struct sockaddr_in6*>(ptrIfAddrs->ifa_addr);
   2465             const struct in6_addr* sin6_addr = &sock_in6->sin6_addr;
   2466 
   2467             if (IN6_IS_ADDR_LOOPBACK(sin6_addr) ||
   2468                 IN6_IS_ADDR_LINKLOCAL(sin6_addr)) {
   2469                 ptrIfAddrs = ptrIfAddrs->ifa_next;
   2470                 continue;
   2471             }
   2472             memcpy(n_localIP, sin6_addr->s6_addr, sizeof(sin6_addr->s6_addr));
   2473             freeifaddrs(ptrIfAddrsStart);
   2474             return 0;
   2475         }
   2476         ptrIfAddrs = ptrIfAddrs->ifa_next;
   2477     }
   2478     freeifaddrs(ptrIfAddrsStart);
   2479     return -1;
   2480 #elif defined(WEBRTC_ANDROID)
   2481     return -1;
   2482 #else // WEBRTC_LINUX
   2483     struct
   2484     {
   2485         struct nlmsghdr n;
   2486         struct ifaddrmsg r;
   2487     } req;
   2488 
   2489     struct rtattr* rta = NULL;
   2490     int status;
   2491     char buf[16384]; // = 16 * 1024 (16 kB)
   2492     struct nlmsghdr* nlmp;
   2493     struct ifaddrmsg* rtmp;
   2494     struct rtattr* rtatp;
   2495     int rtattrlen;
   2496     struct in6_addr* in6p;
   2497 
   2498     int fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
   2499     if (fd == -1)
   2500     {
   2501         return -1;
   2502     }
   2503 
   2504     // RTM_GETADDR is used to fetch the ip address from the kernel interface
   2505     // table. Populate the msg structure (req) the size of the message buffer
   2506     // is specified to netlinkmessage header, and flags values are set as
   2507     // NLM_F_ROOT | NLM_F_REQUEST.
   2508     // The request flag must be set for all messages requesting the data from
   2509     // kernel. The root flag is used to notify the kernel to return the full
   2510     // tabel. Another flag (not used) is NLM_F_MATCH. This is used to get only
   2511     // specified entries in the table. At the time of writing this program this
   2512     // flag is not implemented in kernel
   2513 
   2514     memset(&req, 0, sizeof(req));
   2515     req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
   2516     req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
   2517     req.n.nlmsg_type = RTM_GETADDR;
   2518     req.r.ifa_family = AF_INET6;
   2519 
   2520     // Fill up all the attributes for the rtnetlink header.
   2521     // The lenght is very important. 16 signifies the ipv6 address.
   2522     rta = (struct rtattr*)(((char*)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
   2523     rta->rta_len = RTA_LENGTH(16);
   2524 
   2525     status = send(fd, &req, req.n.nlmsg_len, 0);
   2526     if (status < 0)
   2527     {
   2528         close(fd);
   2529         return -1;
   2530     }
   2531     status = recv(fd, buf, sizeof(buf), 0);
   2532     if (status < 0)
   2533     {
   2534         close(fd);
   2535         return -1;
   2536     }
   2537     if(status == 0)
   2538     {
   2539         close(fd);
   2540         return -1;
   2541     }
   2542     close(fd);
   2543 
   2544     // The message is stored in buff. Parse the message to get the requested
   2545     // data.
   2546     {
   2547         nlmp = (struct nlmsghdr*)buf;
   2548         int len = nlmp->nlmsg_len;
   2549         int req_len = len - sizeof(*nlmp);
   2550 
   2551         if (req_len < 0 || len > status)
   2552         {
   2553             return -1;
   2554         }
   2555         if (!NLMSG_OK_NO_WARNING(nlmp, status))
   2556         {
   2557             return -1;
   2558         }
   2559         rtmp = (struct ifaddrmsg*)NLMSG_DATA(nlmp);
   2560         rtatp = (struct rtattr*)IFA_RTA(rtmp);
   2561 
   2562         rtattrlen = IFA_PAYLOAD(nlmp);
   2563 
   2564         for (; RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen))
   2565         {
   2566 
   2567             // Here we hit the fist chunk of the message. Time to validate the
   2568             // type. For more info on the different types see
   2569             // "man(7) rtnetlink" The table below is taken from man pages.
   2570             // Attributes
   2571             // rta_type        value type             description
   2572             // -------------------------------------------------------------
   2573             // IFA_UNSPEC      -                      unspecified.
   2574             // IFA_ADDRESS     raw protocol address   interface address
   2575             // IFA_LOCAL       raw protocol address   local address
   2576             // IFA_LABEL       asciiz string          name of the interface
   2577             // IFA_BROADCAST   raw protocol address   broadcast address.
   2578             // IFA_ANYCAST     raw protocol address   anycast address
   2579             // IFA_CACHEINFO   struct ifa_cacheinfo   Address information.
   2580 
   2581             if(rtatp->rta_type == IFA_ADDRESS)
   2582             {
   2583                 bool islocalIP = true;
   2584                 in6p = (struct in6_addr*)RTA_DATA(rtatp);
   2585                 for(int n = 0; n< 15; n++)
   2586                 {
   2587                     if(in6p->s6_addr[n] != 0)
   2588                     {
   2589                         islocalIP = false;
   2590                         break;
   2591                     }
   2592                 }
   2593                 if(islocalIP && in6p->s6_addr[15] != 1)
   2594                 {
   2595                     islocalIP = false;
   2596                 }
   2597                 if(!islocalIP)
   2598                 {
   2599                     for(int i = 0; i< 16; i++)
   2600                     {
   2601                         n_localIP[i] = in6p->s6_addr[i];
   2602                     }
   2603                     if(n_localIP[0] == static_cast<char> (0xfe)
   2604                        && n_localIP[1] == static_cast<char>(0x80) )
   2605                     {
   2606                         // Auto configured IP.
   2607                         continue;
   2608                     }
   2609                     break;
   2610                 }
   2611             }
   2612         }
   2613     }
   2614     return 0;
   2615 #endif
   2616 }
   2617 
   2618 int32_t UdpTransport::LocalHostAddress(uint32_t& localIP)
   2619 {
   2620  #if defined(_WIN32)
   2621     hostent* localHost;
   2622     localHost = gethostbyname( "" );
   2623     if(localHost)
   2624     {
   2625         if(localHost->h_addrtype != AF_INET)
   2626         {
   2627             WEBRTC_TRACE(
   2628                 kTraceError,
   2629                 kTraceTransport,
   2630                 -1,
   2631                 "LocalHostAddress can only get local IP for IP Version 4");
   2632             return -1;
   2633         }
   2634         localIP= Htonl(
   2635             (*(struct in_addr *)localHost->h_addr_list[0]).S_un.S_addr);
   2636         return 0;
   2637     }
   2638     else
   2639     {
   2640         int32_t error = WSAGetLastError();
   2641         WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
   2642                      "gethostbyname failed, error:%d", error);
   2643         return -1;
   2644     }
   2645 #elif (defined(WEBRTC_MAC))
   2646     char localname[255];
   2647     if (gethostname(localname, 255) != -1)
   2648     {
   2649         hostent* localHost;
   2650         localHost = gethostbyname(localname);
   2651         if(localHost)
   2652         {
   2653             if(localHost->h_addrtype != AF_INET)
   2654             {
   2655                 WEBRTC_TRACE(
   2656                     kTraceError,
   2657                     kTraceTransport,
   2658                     -1,
   2659                     "LocalHostAddress can only get local IP for IP Version 4");
   2660                 return -1;
   2661             }
   2662             localIP = Htonl((*(struct in_addr*)*localHost->h_addr_list).s_addr);
   2663             return 0;
   2664         }
   2665     }
   2666     WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, "gethostname failed");
   2667     return -1;
   2668 #else // WEBRTC_LINUX
   2669     int sockfd, size  = 1;
   2670     struct ifreq* ifr;
   2671     struct ifconf ifc;
   2672 
   2673     if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
   2674     {
   2675       return -1;
   2676     }
   2677     ifc.ifc_len = IFRSIZE;
   2678     ifc.ifc_req = NULL;
   2679     do
   2680     {
   2681         ++size;
   2682         // Buffer size needed is unknown. Try increasing it until no overflow
   2683         // occurs.
   2684         if (NULL == (ifc.ifc_req = (ifreq*)realloc(ifc.ifc_req, IFRSIZE))) {
   2685           fprintf(stderr, "Out of memory.\n");
   2686           exit(EXIT_FAILURE);
   2687         }
   2688         ifc.ifc_len = IFRSIZE;
   2689         if (ioctl(sockfd, SIOCGIFCONF, &ifc))
   2690         {
   2691             free(ifc.ifc_req);
   2692             close(sockfd);
   2693             return -1;
   2694         }
   2695     } while  (IFRSIZE <= ifc.ifc_len);
   2696 
   2697     ifr = ifc.ifc_req;
   2698     for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr)
   2699     {
   2700         if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data)
   2701         {
   2702           continue;  // duplicate, skip it
   2703         }
   2704         if (ioctl(sockfd, SIOCGIFFLAGS, ifr))
   2705         {
   2706           continue;  // failed to get flags, skip it
   2707         }
   2708         if(strncmp(ifr->ifr_name, "lo",3) == 0)
   2709         {
   2710             continue;
   2711         }else
   2712         {
   2713             struct sockaddr* saddr = &(ifr->ifr_addr);
   2714             SocketAddress* socket_addess = reinterpret_cast<SocketAddress*>(
   2715                 saddr);
   2716             localIP = Htonl(socket_addess->_sockaddr_in.sin_addr);
   2717             close(sockfd);
   2718             free(ifc.ifc_req);
   2719             return 0;
   2720         }
   2721     }
   2722     free(ifc.ifc_req);
   2723     close(sockfd);
   2724     return -1;
   2725 #endif
   2726 }
   2727 
   2728 int32_t UdpTransport::IPAddress(const SocketAddress& address,
   2729                                 char* ip,
   2730                                 uint32_t& ipSize,
   2731                                 uint16_t& sourcePort)
   2732 {
   2733  #if defined(_WIN32)
   2734     DWORD dwIPSize = ipSize;
   2735     int32_t returnvalue = WSAAddressToStringA((LPSOCKADDR)(&address),
   2736                                          sizeof(SocketAddress),
   2737                                          NULL,
   2738                                          ip,
   2739                                          &dwIPSize);
   2740     if(returnvalue == -1)
   2741     {
   2742         return -1;
   2743     }
   2744 
   2745     uint16_t source_port = 0;
   2746     if(address._sockaddr_storage.sin_family == AF_INET)
   2747     {
   2748         // Parse IP assuming format "a.b.c.d:port".
   2749         char* ipEnd = strchr(ip,':');
   2750         if(ipEnd != NULL)
   2751         {
   2752             *ipEnd = '\0';
   2753         }
   2754         ipSize = (int32_t)strlen(ip);
   2755         if(ipSize == 0)
   2756         {
   2757             return -1;
   2758         }
   2759         source_port = address._sockaddr_in.sin_port;
   2760     }
   2761     else
   2762     {
   2763         // Parse IP assuming format "[address]:port".
   2764         char* ipEnd = strchr(ip,']');
   2765         if(ipEnd != NULL)
   2766         {
   2767           // Calculate length
   2768             int32_t adrSize = int32_t(ipEnd - ip) - 1;
   2769             memmove(ip, &ip[1], adrSize);   // Remove '['
   2770             *(ipEnd - 1) = '\0';
   2771         }
   2772         ipSize = (int32_t)strlen(ip);
   2773         if(ipSize == 0)
   2774         {
   2775             return -1;
   2776         }
   2777 
   2778         source_port = address._sockaddr_in6.sin6_port;
   2779     }
   2780     // Convert port number to network byte order.
   2781     sourcePort = htons(source_port);
   2782     return 0;
   2783 
   2784  #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
   2785     int32_t ipFamily = address._sockaddr_storage.sin_family;
   2786     const void* ptrNumericIP = NULL;
   2787 
   2788     if(ipFamily == AF_INET)
   2789     {
   2790         ptrNumericIP = &(address._sockaddr_in.sin_addr);
   2791     }
   2792     else if(ipFamily == AF_INET6)
   2793     {
   2794         ptrNumericIP = &(address._sockaddr_in6.sin6_addr);
   2795     }
   2796     else
   2797     {
   2798         return -1;
   2799     }
   2800     if(inet_ntop(ipFamily, ptrNumericIP, ip, ipSize) == NULL)
   2801     {
   2802         return -1;
   2803     }
   2804     uint16_t source_port;
   2805     if(ipFamily == AF_INET)
   2806     {
   2807         source_port = address._sockaddr_in.sin_port;
   2808     } else
   2809     {
   2810         source_port = address._sockaddr_in6.sin6_port;
   2811     }
   2812     // Convert port number to network byte order.
   2813     sourcePort = htons(source_port);
   2814     return 0;
   2815  #else
   2816     return -1;
   2817  #endif
   2818 }
   2819 
   2820 bool UdpTransport::IsIpAddressValid(const char* ipadr, const bool ipV6)
   2821 {
   2822     if(ipV6)
   2823     {
   2824         int32_t len = (int32_t)strlen(ipadr);
   2825         if( len>39 || len == 0)
   2826         {
   2827             return false;
   2828         }
   2829 
   2830         int32_t i;
   2831         int32_t colonPos[7] = {0,0,0,0,0,0,0};
   2832         int32_t lastColonPos = -2;
   2833         int32_t nColons = 0;
   2834         int32_t nDubbleColons = 0;
   2835         int32_t nDots = 0;
   2836         int32_t error = 0;
   2837         char c;
   2838         for(i = 0; i < len ; i++)
   2839         {
   2840             c=ipadr[i];
   2841             if(isxdigit(c))
   2842                 ;
   2843             else if(c == ':')
   2844             {
   2845                 if(nColons < 7)
   2846                     colonPos[nColons] = i;
   2847                 if((i-lastColonPos)==1)
   2848                     nDubbleColons++;
   2849                 lastColonPos=i;
   2850                 if(nDots != 0)
   2851                 {
   2852                     error = 1;
   2853                 }
   2854                 nColons++;
   2855             }
   2856             else if(c == '.')
   2857             {
   2858                 nDots++;
   2859             }
   2860             else
   2861             {
   2862                 error = 1;
   2863             }
   2864 
   2865         }
   2866         if(error)
   2867         {
   2868             return false;
   2869         }
   2870         if(nDubbleColons > 1)
   2871         {
   2872             return false;
   2873         }
   2874         if(nColons > 7 || nColons < 2)
   2875         {
   2876             return false;
   2877         }
   2878         if(!(nDots == 3 || nDots == 0))
   2879         {
   2880             return false;
   2881         }
   2882         lastColonPos = -1;
   2883         int32_t charsBeforeColon = 0;
   2884         for(i = 0; i < nColons; i++)
   2885         {
   2886             charsBeforeColon=colonPos[i]-lastColonPos-1;
   2887             if(charsBeforeColon > 4)
   2888             {
   2889                 return false;
   2890             }
   2891             lastColonPos=colonPos[i];
   2892         }
   2893         int32_t lengthAfterLastColon = len - lastColonPos - 1;
   2894         if(nDots == 0)
   2895         {
   2896             if(lengthAfterLastColon > 4)
   2897                 return false;
   2898         }
   2899         if(nDots == 3 && lengthAfterLastColon > 0)
   2900         {
   2901             return IsIpAddressValid((ipadr+lastColonPos+1),false);
   2902         }
   2903 
   2904     }
   2905     else
   2906     {
   2907         int32_t len = (int32_t)strlen(ipadr);
   2908         if((len>15)||(len==0))
   2909         {
   2910             return false;
   2911         }
   2912 
   2913         // IPv4 should be [0-255].[0-255].[0-255].[0-255]
   2914         int32_t i;
   2915         int32_t nDots = 0;
   2916         int32_t iDotPos[4] = {0,0,0,0};
   2917 
   2918         for (i = 0; (i < len) && (nDots < 4); i++)
   2919         {
   2920             if (ipadr[i] == (char)'.')
   2921             {
   2922                 // Store index of dots and count number of dots.
   2923                 iDotPos[nDots++] = i;
   2924             }
   2925         }
   2926 
   2927         bool allUnder256 = false;
   2928         // TODO (hellner): while loop seems to be abused here to get
   2929         // label like functionality. Fix later to avoid introducing bugs now.
   2930 
   2931         // Check that all numbers are smaller than 256.
   2932         do
   2933         {
   2934             if (nDots != 3 )
   2935             {
   2936                 break;
   2937             }
   2938 
   2939             if (iDotPos[0] <= 3)
   2940             {
   2941                 char nr[4];
   2942                 memset(nr,0,4);
   2943                 strncpy(nr,&ipadr[0],iDotPos[0]);
   2944                 int32_t num = atoi(nr);
   2945                 if (num > 255)
   2946                 {
   2947                     break;
   2948                 }
   2949             } else {
   2950                 break;
   2951             }
   2952 
   2953             if (iDotPos[1] - iDotPos[0] <= 4)
   2954             {
   2955                 char nr[4];
   2956                 memset(nr,0,4);
   2957                 strncpy(nr,&ipadr[iDotPos[0]+1], iDotPos[1] - iDotPos[0] - 1);
   2958                 int32_t num = atoi(nr);
   2959                 if (num > 255)
   2960                     break;
   2961             } else {
   2962                 break;
   2963             }
   2964 
   2965             if (iDotPos[2] - iDotPos[1] <= 4)
   2966             {
   2967                 char nr[4];
   2968                 memset(nr,0,4);
   2969                 strncpy(nr,&ipadr[iDotPos[1]+1], iDotPos[1] - iDotPos[0] - 1);
   2970                 int32_t num = atoi(nr);
   2971                 if (num > 255)
   2972                     break;
   2973 
   2974                 memset(nr,0,4);
   2975                 strncpy(nr,&ipadr[iDotPos[2]+1], len - iDotPos[2] -1);
   2976                 num = atoi(nr);
   2977                 if (num > 255)
   2978                     break;
   2979                 else
   2980                     allUnder256 = true;
   2981             } else
   2982                 break;
   2983         } while(false);
   2984 
   2985         if (nDots != 3 || !allUnder256)
   2986         {
   2987             return false;
   2988         }
   2989     }
   2990     return true;
   2991 }
   2992 
   2993 }  // namespace test
   2994 }  // namespace webrtc
   2995