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/interface/critical_section_wrapper.h"
     49 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
     50 #include "webrtc/system_wrappers/interface/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   virtual 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                                   uint32_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                                           uint32_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                                            uint32_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                                           uint32_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                                            uint32_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 int UdpTransportImpl::SendPacket(int /*channel*/, const void* data, int length)
   1935 {
   1936     WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, "%s", __FUNCTION__);
   1937 
   1938     CriticalSectionScoped cs(_crit);
   1939 
   1940     if(_destIP[0] == 0)
   1941     {
   1942         return -1;
   1943     }
   1944     if(_destPort == 0)
   1945     {
   1946         return -1;
   1947     }
   1948 
   1949     // Create socket if it hasn't been set up already.
   1950     // TODO (hellner): why not fail here instead. Sockets not being initialized
   1951     //                 indicates that there is a problem somewhere.
   1952     if( _ptrSendRtpSocket == NULL &&
   1953         _ptrRtpSocket == NULL)
   1954     {
   1955         WEBRTC_TRACE(
   1956             kTraceStateInfo,
   1957             kTraceTransport,
   1958             _id,
   1959             "Creating RTP socket since no receive or source socket is\
   1960  configured");
   1961 
   1962         _ptrRtpSocket = _socket_creator->CreateSocket(_id, _mgr, this,
   1963                                         IncomingRTPCallback,
   1964                                         IpV6Enabled(), false);
   1965 
   1966         // Don't bind to a specific IP address.
   1967         if(! IpV6Enabled())
   1968         {
   1969             strncpy(_localIP, "0.0.0.0",16);
   1970         } else
   1971         {
   1972             strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000",
   1973                     kIpAddressVersion6Length);
   1974         }
   1975         _localPort = _destPort;
   1976 
   1977         ErrorCode retVal = BindLocalRTPSocket();
   1978         if(retVal != kNoSocketError)
   1979         {
   1980             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   1981                          "SendPacket() failed to bind RTP socket");
   1982             _lastError = retVal;
   1983             CloseReceiveSockets();
   1984             return -1;
   1985         }
   1986     }
   1987 
   1988     if(_ptrSendRtpSocket)
   1989     {
   1990         return _ptrSendRtpSocket->SendTo((const int8_t*)data, length,
   1991                                          _remoteRTPAddr);
   1992 
   1993     } else if(_ptrRtpSocket)
   1994     {
   1995         return _ptrRtpSocket->SendTo((const int8_t*)data, length,
   1996                                      _remoteRTPAddr);
   1997     }
   1998     return -1;
   1999 }
   2000 
   2001 int UdpTransportImpl::SendRTCPPacket(int /*channel*/, const void* data,
   2002                                      int length)
   2003 {
   2004 
   2005     CriticalSectionScoped cs(_crit);
   2006     if(_destIP[0] == 0)
   2007     {
   2008         return -1;
   2009     }
   2010     if(_destPortRTCP == 0)
   2011     {
   2012         return -1;
   2013     }
   2014 
   2015     // Create socket if it hasn't been set up already.
   2016     // TODO (hellner): why not fail here instead. Sockets not being initialized
   2017     //                 indicates that there is a problem somewhere.
   2018     if( _ptrSendRtcpSocket == NULL &&
   2019         _ptrRtcpSocket == NULL)
   2020     {
   2021         WEBRTC_TRACE(
   2022             kTraceStateInfo,
   2023             kTraceTransport,
   2024             _id,
   2025             "Creating RTCP socket since no receive or source socket is\
   2026  configured");
   2027 
   2028         _ptrRtcpSocket = _socket_creator->CreateSocket(_id, _mgr, this,
   2029                                          IncomingRTCPCallback,
   2030                                          IpV6Enabled(), false);
   2031 
   2032         // Don't bind to a specific IP address.
   2033         if(! IpV6Enabled())
   2034         {
   2035             strncpy(_localIP, "0.0.0.0",16);
   2036         } else
   2037         {
   2038             strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000",
   2039                     kIpAddressVersion6Length);
   2040         }
   2041         _localPortRTCP = _destPortRTCP;
   2042 
   2043         ErrorCode retVal = BindLocalRTCPSocket();
   2044         if(retVal != kNoSocketError)
   2045         {
   2046             _lastError = retVal;
   2047             WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
   2048                          "SendRTCPPacket() failed to bind RTCP socket");
   2049             CloseReceiveSockets();
   2050             return -1;
   2051         }
   2052     }
   2053 
   2054     if(_ptrSendRtcpSocket)
   2055     {
   2056         return _ptrSendRtcpSocket->SendTo((const int8_t*)data, length,
   2057                                           _remoteRTCPAddr);
   2058     } else if(_ptrRtcpSocket)
   2059     {
   2060         return _ptrRtcpSocket->SendTo((const int8_t*)data, length,
   2061                                       _remoteRTCPAddr);
   2062     }
   2063     return -1;
   2064 }
   2065 
   2066 int32_t UdpTransportImpl::SetSendIP(const char* ipaddr)
   2067 {
   2068     if(!IsIpAddressValid(ipaddr,IpV6Enabled()))
   2069     {
   2070         return kIpAddressInvalid;
   2071     }
   2072     CriticalSectionScoped cs(_crit);
   2073     strncpy(_destIP, ipaddr,kIpAddressVersion6Length);
   2074     BuildRemoteRTPAddr();
   2075     BuildRemoteRTCPAddr();
   2076     return 0;
   2077 }
   2078 
   2079 int32_t UdpTransportImpl::SetSendPorts(uint16_t rtpPort, uint16_t rtcpPort)
   2080 {
   2081     CriticalSectionScoped cs(_crit);
   2082     _destPort = rtpPort;
   2083     if(rtcpPort == 0)
   2084     {
   2085         _destPortRTCP = _destPort+1;
   2086     } else
   2087     {
   2088         _destPortRTCP = rtcpPort;
   2089     }
   2090     BuildRemoteRTPAddr();
   2091     BuildRemoteRTCPAddr();
   2092     return 0;
   2093 }
   2094 
   2095 void UdpTransportImpl::IncomingRTPCallback(CallbackObj obj,
   2096                                            const int8_t* rtpPacket,
   2097                                            int32_t rtpPacketLength,
   2098                                            const SocketAddress* from)
   2099 {
   2100     if (rtpPacket && rtpPacketLength > 0)
   2101     {
   2102         UdpTransportImpl* socketTransport = (UdpTransportImpl*) obj;
   2103         socketTransport->IncomingRTPFunction(rtpPacket, rtpPacketLength, from);
   2104     }
   2105 }
   2106 
   2107 void UdpTransportImpl::IncomingRTCPCallback(CallbackObj obj,
   2108                                             const int8_t* rtcpPacket,
   2109                                             int32_t rtcpPacketLength,
   2110                                             const SocketAddress* from)
   2111 {
   2112     if (rtcpPacket && rtcpPacketLength > 0)
   2113     {
   2114         UdpTransportImpl* socketTransport = (UdpTransportImpl*) obj;
   2115         socketTransport->IncomingRTCPFunction(rtcpPacket, rtcpPacketLength,
   2116                                               from);
   2117     }
   2118 }
   2119 
   2120 void UdpTransportImpl::IncomingRTPFunction(const int8_t* rtpPacket,
   2121                                            int32_t rtpPacketLength,
   2122                                            const SocketAddress* fromSocket)
   2123 {
   2124     char ipAddress[kIpAddressVersion6Length];
   2125     uint32_t ipAddressLength = kIpAddressVersion6Length;
   2126     uint16_t portNr = 0;
   2127 
   2128     {
   2129         CriticalSectionScoped cs(_critFilter);
   2130         if (FilterIPAddress(fromSocket) == false)
   2131         {
   2132             // Packet should be filtered out. Drop it.
   2133             WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2134                          "Incoming RTP packet blocked by IP filter");
   2135             return;
   2136         }
   2137 
   2138         if (IPAddressCached(*fromSocket, ipAddress, ipAddressLength, portNr) <
   2139             0)
   2140         {
   2141             WEBRTC_TRACE(
   2142                 kTraceError,
   2143                 kTraceTransport,
   2144                 _id,
   2145                 "UdpTransportImpl::IncomingRTPFunction - Cannot get sender\
   2146  information");
   2147         }else
   2148         {
   2149             // Make sure ipAddress is null terminated.
   2150             ipAddress[kIpAddressVersion6Length - 1] = 0;
   2151             strncpy(_fromIP, ipAddress, kIpAddressVersion6Length - 1);
   2152         }
   2153 
   2154         // Filter based on port.
   2155         if (_rtpFilterPort != 0 &&
   2156             _rtpFilterPort != portNr)
   2157         {
   2158             // Drop packet.
   2159             memset(_fromIP, 0, sizeof(_fromIP));
   2160             WEBRTC_TRACE(
   2161                 kTraceStream,
   2162                 kTraceTransport,
   2163                 _id,
   2164                 "Incoming RTP packet blocked by filter incoming from port:%d\
   2165  allowed port:%d",
   2166                 portNr,
   2167                 _rtpFilterPort);
   2168             return;
   2169         }
   2170         _fromPort = portNr;
   2171     }
   2172 
   2173     CriticalSectionScoped cs(_critPacketCallback);
   2174     if (_packetCallback)
   2175     {
   2176         WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2177             "Incoming RTP packet from ip:%s port:%d", ipAddress, portNr);
   2178         _packetCallback->IncomingRTPPacket(rtpPacket, rtpPacketLength,
   2179                                            ipAddress, portNr);
   2180     }
   2181 }
   2182 
   2183 void UdpTransportImpl::IncomingRTCPFunction(const int8_t* rtcpPacket,
   2184                                             int32_t rtcpPacketLength,
   2185                                             const SocketAddress* fromSocket)
   2186 {
   2187     char ipAddress[kIpAddressVersion6Length];
   2188     uint32_t ipAddressLength = kIpAddressVersion6Length;
   2189     uint16_t portNr = 0;
   2190 
   2191     {
   2192         CriticalSectionScoped cs(_critFilter);
   2193         if (FilterIPAddress(fromSocket) == false)
   2194         {
   2195             // Packet should be filtered out. Drop it.
   2196             WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2197                          "Incoming RTCP packet blocked by IP filter");
   2198             return;
   2199         }
   2200         if (IPAddress(*fromSocket, ipAddress, ipAddressLength, portNr) < 0)
   2201         {
   2202             WEBRTC_TRACE(
   2203                 kTraceError,
   2204                 kTraceTransport,
   2205                 _id,
   2206                 "UdpTransportImpl::IncomingRTCPFunction - Cannot get sender\
   2207  information");
   2208         }else {
   2209             // Make sure ipAddress is null terminated.
   2210             ipAddress[kIpAddressVersion6Length - 1] = 0;
   2211             strncpy(_fromIP, ipAddress, kIpAddressVersion6Length - 1);
   2212         }
   2213 
   2214         // Filter based on port.
   2215         if (_rtcpFilterPort != 0 &&
   2216             _rtcpFilterPort != portNr)
   2217         {
   2218             // Drop packet.
   2219             WEBRTC_TRACE(
   2220                 kTraceStream,
   2221                 kTraceTransport,
   2222                 _id,
   2223                 "Incoming RTCP packet blocked by filter incoming from port:%d\
   2224  allowed port:%d",
   2225                 portNr,
   2226                 _rtpFilterPort);
   2227             return;
   2228         }
   2229         _fromPortRTCP = portNr;
   2230     }
   2231 
   2232     CriticalSectionScoped cs(_critPacketCallback);
   2233     if (_packetCallback)
   2234     {
   2235         WEBRTC_TRACE(kTraceStream, kTraceTransport, _id,
   2236                      "Incoming RTCP packet from ip:%s port:%d", ipAddress,
   2237                      portNr);
   2238         _packetCallback->IncomingRTCPPacket(rtcpPacket, rtcpPacketLength,
   2239                                             ipAddress, portNr);
   2240     }
   2241 }
   2242 
   2243 bool UdpTransportImpl::FilterIPAddress(const SocketAddress* fromAddress)
   2244 {
   2245     if(fromAddress->_sockaddr_storage.sin_family == AF_INET)
   2246     {
   2247         if (_filterIPAddress._sockaddr_storage.sin_family == AF_INET)
   2248         {
   2249             // IP is stored in sin_addr.
   2250             if (_filterIPAddress._sockaddr_in.sin_addr != 0 &&
   2251                 (_filterIPAddress._sockaddr_in.sin_addr !=
   2252                  fromAddress->_sockaddr_in.sin_addr))
   2253             {
   2254                 return false;
   2255             }
   2256         }
   2257     }
   2258     else if(fromAddress->_sockaddr_storage.sin_family == AF_INET6)
   2259     {
   2260         if (_filterIPAddress._sockaddr_storage.sin_family == AF_INET6)
   2261         {
   2262             // IP is stored in sin_6addr.
   2263             for (int32_t i = 0; i < 4; i++)
   2264             {
   2265                 if (_filterIPAddress._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i] != 0 &&
   2266                     _filterIPAddress._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i] != fromAddress->_sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i])
   2267                 {
   2268                     return false;
   2269                 }
   2270             }
   2271         }
   2272     }
   2273     else
   2274     {
   2275       WEBRTC_TRACE(
   2276                 kTraceError,
   2277                 kTraceTransport,
   2278                 _id,
   2279                 "UdpTransportImpl::FilterIPAddress() unknown address family");
   2280         return false;
   2281     }
   2282     return true;
   2283 }
   2284 
   2285 void UdpTransportImpl::CloseReceiveSockets()
   2286 {
   2287     if(_ptrRtpSocket)
   2288     {
   2289         _ptrRtpSocket->CloseBlocking();
   2290         _ptrRtpSocket = NULL;
   2291     }
   2292     if(_ptrRtcpSocket)
   2293     {
   2294         _ptrRtcpSocket->CloseBlocking();
   2295         _ptrRtcpSocket = NULL;
   2296     }
   2297     _receiving = false;
   2298 }
   2299 
   2300 void UdpTransportImpl::CloseSendSockets()
   2301 {
   2302     if(_ptrSendRtpSocket)
   2303     {
   2304         _ptrSendRtpSocket->CloseBlocking();
   2305         _ptrSendRtpSocket = 0;
   2306     }
   2307     if(_ptrSendRtcpSocket)
   2308     {
   2309         _ptrSendRtcpSocket->CloseBlocking();
   2310         _ptrSendRtcpSocket = 0;
   2311     }
   2312 }
   2313 
   2314 uint16_t UdpTransport::Htons(const uint16_t port)
   2315 {
   2316     return htons(port);
   2317 }
   2318 
   2319 uint32_t UdpTransport::Htonl(const uint32_t a)
   2320 {
   2321     return htonl(a);
   2322 }
   2323 
   2324 uint32_t UdpTransport::InetAddrIPV4(const char* ip)
   2325 {
   2326     return ::inet_addr(ip);
   2327 }
   2328 
   2329 int32_t UdpTransport::InetPresentationToNumeric(int32_t af,
   2330                                                 const char* src,
   2331                                                 void* dst)
   2332 {
   2333 #if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
   2334     const int32_t result = inet_pton(af, src, dst);
   2335     return result > 0 ? 0 : -1;
   2336 
   2337 #elif defined(_WIN32)
   2338     SocketAddress temp;
   2339     int length=sizeof(SocketAddress);
   2340 
   2341     if(af == AF_INET)
   2342     {
   2343         int32_t result = WSAStringToAddressA(
   2344             (const LPSTR)src,
   2345             af,
   2346             0,
   2347             reinterpret_cast<struct sockaddr*>(&temp),
   2348             &length);
   2349         if(result != 0)
   2350         {
   2351             return -1;
   2352         }
   2353         memcpy(dst,&(temp._sockaddr_in.sin_addr),
   2354                sizeof(temp._sockaddr_in.sin_addr));
   2355         return 0;
   2356     }
   2357     else if(af == AF_INET6)
   2358     {
   2359         int32_t result = WSAStringToAddressA(
   2360             (const LPSTR)src,
   2361             af,
   2362             0,
   2363             reinterpret_cast<struct sockaddr*>(&temp),
   2364             &length);
   2365         if(result !=0)
   2366         {
   2367             return -1;
   2368         }
   2369         memcpy(dst,&(temp._sockaddr_in6.sin6_addr),
   2370                sizeof(temp._sockaddr_in6.sin6_addr));
   2371         return 0;
   2372 
   2373     }else
   2374     {
   2375         return -1;
   2376     }
   2377 #else
   2378     return -1;
   2379 #endif
   2380 }
   2381 
   2382 int32_t UdpTransport::LocalHostAddressIPV6(char n_localIP[16])
   2383 {
   2384 
   2385 #if defined(_WIN32)
   2386     struct addrinfo *result = NULL;
   2387     struct addrinfo *ptr = NULL;
   2388     struct addrinfo hints;
   2389 
   2390     ZeroMemory(&hints, sizeof(hints));
   2391     hints.ai_family = AF_INET6;
   2392 
   2393     char szHostName[256] = "";
   2394     if(::gethostname(szHostName, sizeof(szHostName) - 1))
   2395     {
   2396         WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, "gethostname failed");
   2397         return -1;
   2398     }
   2399 
   2400     DWORD dwRetval = getaddrinfo(szHostName, NULL, &hints, &result);
   2401     if ( dwRetval != 0 )
   2402     {
   2403         WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
   2404                      "getaddrinfo failed, error:%d", dwRetval);
   2405         return -1;
   2406     }
   2407     for(ptr=result; ptr != NULL ;ptr=ptr->ai_next)
   2408     {
   2409         switch (ptr->ai_family)
   2410         {
   2411             case AF_INET6:
   2412                 {
   2413                     for(int i = 0; i< 16; i++)
   2414                     {
   2415                         n_localIP[i] = (*(SocketAddress*)ptr->ai_addr).
   2416                             _sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u8[i];
   2417                     }
   2418                     bool islocalIP = true;
   2419 
   2420                     for(int n = 0; n< 15; n++)
   2421                     {
   2422                         if(n_localIP[n] != 0)
   2423                         {
   2424                             islocalIP = false;
   2425                             break;
   2426                         }
   2427                     }
   2428 
   2429                     if(islocalIP && n_localIP[15] != 1)
   2430                     {
   2431                         islocalIP = false;
   2432                     }
   2433 
   2434                     if(islocalIP && ptr->ai_next)
   2435                     {
   2436                         continue;
   2437                     }
   2438                     if(n_localIP[0] == 0xfe &&
   2439                        n_localIP[1] == 0x80 && ptr->ai_next)
   2440                     {
   2441                         continue;
   2442                     }
   2443                     freeaddrinfo(result);
   2444                 }
   2445                 return 0;
   2446             default:
   2447                 break;
   2448         };
   2449     }
   2450     freeaddrinfo(result);
   2451     WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
   2452                  "getaddrinfo failed to find address");
   2453     return -1;
   2454 
   2455 #elif defined(WEBRTC_MAC)
   2456     struct ifaddrs* ptrIfAddrs = NULL;
   2457     struct ifaddrs* ptrIfAddrsStart = NULL;
   2458 
   2459     getifaddrs(&ptrIfAddrsStart);
   2460     ptrIfAddrs = ptrIfAddrsStart;
   2461     while(ptrIfAddrs)
   2462     {
   2463         if(ptrIfAddrs->ifa_addr->sa_family == AF_INET6)
   2464         {
   2465             const struct sockaddr_in6* sock_in6 =
   2466                 reinterpret_cast<struct sockaddr_in6*>(ptrIfAddrs->ifa_addr);
   2467             const struct in6_addr* sin6_addr = &sock_in6->sin6_addr;
   2468 
   2469             if (IN6_IS_ADDR_LOOPBACK(sin6_addr) ||
   2470                 IN6_IS_ADDR_LINKLOCAL(sin6_addr)) {
   2471                 ptrIfAddrs = ptrIfAddrs->ifa_next;
   2472                 continue;
   2473             }
   2474             memcpy(n_localIP, sin6_addr->s6_addr, sizeof(sin6_addr->s6_addr));
   2475             freeifaddrs(ptrIfAddrsStart);
   2476             return 0;
   2477         }
   2478         ptrIfAddrs = ptrIfAddrs->ifa_next;
   2479     }
   2480     freeifaddrs(ptrIfAddrsStart);
   2481     return -1;
   2482 #elif defined(WEBRTC_ANDROID)
   2483     return -1;
   2484 #else // WEBRTC_LINUX
   2485     struct
   2486     {
   2487         struct nlmsghdr n;
   2488         struct ifaddrmsg r;
   2489     } req;
   2490 
   2491     struct rtattr* rta = NULL;
   2492     int status;
   2493     char buf[16384]; // = 16 * 1024 (16 kB)
   2494     struct nlmsghdr* nlmp;
   2495     struct ifaddrmsg* rtmp;
   2496     struct rtattr* rtatp;
   2497     int rtattrlen;
   2498     struct in6_addr* in6p;
   2499 
   2500     int fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
   2501     if (fd == -1)
   2502     {
   2503         return -1;
   2504     }
   2505 
   2506     // RTM_GETADDR is used to fetch the ip address from the kernel interface
   2507     // table. Populate the msg structure (req) the size of the message buffer
   2508     // is specified to netlinkmessage header, and flags values are set as
   2509     // NLM_F_ROOT | NLM_F_REQUEST.
   2510     // The request flag must be set for all messages requesting the data from
   2511     // kernel. The root flag is used to notify the kernel to return the full
   2512     // tabel. Another flag (not used) is NLM_F_MATCH. This is used to get only
   2513     // specified entries in the table. At the time of writing this program this
   2514     // flag is not implemented in kernel
   2515 
   2516     memset(&req, 0, sizeof(req));
   2517     req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
   2518     req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
   2519     req.n.nlmsg_type = RTM_GETADDR;
   2520     req.r.ifa_family = AF_INET6;
   2521 
   2522     // Fill up all the attributes for the rtnetlink header.
   2523     // The lenght is very important. 16 signifies the ipv6 address.
   2524     rta = (struct rtattr*)(((char*)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
   2525     rta->rta_len = RTA_LENGTH(16);
   2526 
   2527     status = send(fd, &req, req.n.nlmsg_len, 0);
   2528     if (status < 0)
   2529     {
   2530         close(fd);
   2531         return -1;
   2532     }
   2533     status = recv(fd, buf, sizeof(buf), 0);
   2534     if (status < 0)
   2535     {
   2536         close(fd);
   2537         return -1;
   2538     }
   2539     if(status == 0)
   2540     {
   2541         close(fd);
   2542         return -1;
   2543     }
   2544     close(fd);
   2545 
   2546     // The message is stored in buff. Parse the message to get the requested
   2547     // data.
   2548     {
   2549         nlmp = (struct nlmsghdr*)buf;
   2550         int len = nlmp->nlmsg_len;
   2551         int req_len = len - sizeof(*nlmp);
   2552 
   2553         if (req_len < 0 || len > status)
   2554         {
   2555             return -1;
   2556         }
   2557         if (!NLMSG_OK_NO_WARNING(nlmp, status))
   2558         {
   2559             return -1;
   2560         }
   2561         rtmp = (struct ifaddrmsg*)NLMSG_DATA(nlmp);
   2562         rtatp = (struct rtattr*)IFA_RTA(rtmp);
   2563 
   2564         rtattrlen = IFA_PAYLOAD(nlmp);
   2565 
   2566         for (; RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen))
   2567         {
   2568 
   2569             // Here we hit the fist chunk of the message. Time to validate the
   2570             // type. For more info on the different types see
   2571             // "man(7) rtnetlink" The table below is taken from man pages.
   2572             // Attributes
   2573             // rta_type        value type             description
   2574             // -------------------------------------------------------------
   2575             // IFA_UNSPEC      -                      unspecified.
   2576             // IFA_ADDRESS     raw protocol address   interface address
   2577             // IFA_LOCAL       raw protocol address   local address
   2578             // IFA_LABEL       asciiz string          name of the interface
   2579             // IFA_BROADCAST   raw protocol address   broadcast address.
   2580             // IFA_ANYCAST     raw protocol address   anycast address
   2581             // IFA_CACHEINFO   struct ifa_cacheinfo   Address information.
   2582 
   2583             if(rtatp->rta_type == IFA_ADDRESS)
   2584             {
   2585                 bool islocalIP = true;
   2586                 in6p = (struct in6_addr*)RTA_DATA(rtatp);
   2587                 for(int n = 0; n< 15; n++)
   2588                 {
   2589                     if(in6p->s6_addr[n] != 0)
   2590                     {
   2591                         islocalIP = false;
   2592                         break;
   2593                     }
   2594                 }
   2595                 if(islocalIP && in6p->s6_addr[15] != 1)
   2596                 {
   2597                     islocalIP = false;
   2598                 }
   2599                 if(!islocalIP)
   2600                 {
   2601                     for(int i = 0; i< 16; i++)
   2602                     {
   2603                         n_localIP[i] = in6p->s6_addr[i];
   2604                     }
   2605                     if(n_localIP[0] == static_cast<char> (0xfe)
   2606                        && n_localIP[1] == static_cast<char>(0x80) )
   2607                     {
   2608                         // Auto configured IP.
   2609                         continue;
   2610                     }
   2611                     break;
   2612                 }
   2613             }
   2614         }
   2615     }
   2616     return 0;
   2617 #endif
   2618 }
   2619 
   2620 int32_t UdpTransport::LocalHostAddress(uint32_t& localIP)
   2621 {
   2622  #if defined(_WIN32)
   2623     hostent* localHost;
   2624     localHost = gethostbyname( "" );
   2625     if(localHost)
   2626     {
   2627         if(localHost->h_addrtype != AF_INET)
   2628         {
   2629             WEBRTC_TRACE(
   2630                 kTraceError,
   2631                 kTraceTransport,
   2632                 -1,
   2633                 "LocalHostAddress can only get local IP for IP Version 4");
   2634             return -1;
   2635         }
   2636         localIP= Htonl(
   2637             (*(struct in_addr *)localHost->h_addr_list[0]).S_un.S_addr);
   2638         return 0;
   2639     }
   2640     else
   2641     {
   2642         int32_t error = WSAGetLastError();
   2643         WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
   2644                      "gethostbyname failed, error:%d", error);
   2645         return -1;
   2646     }
   2647 #elif (defined(WEBRTC_MAC))
   2648     char localname[255];
   2649     if (gethostname(localname, 255) != -1)
   2650     {
   2651         hostent* localHost;
   2652         localHost = gethostbyname(localname);
   2653         if(localHost)
   2654         {
   2655             if(localHost->h_addrtype != AF_INET)
   2656             {
   2657                 WEBRTC_TRACE(
   2658                     kTraceError,
   2659                     kTraceTransport,
   2660                     -1,
   2661                     "LocalHostAddress can only get local IP for IP Version 4");
   2662                 return -1;
   2663             }
   2664             localIP = Htonl((*(struct in_addr*)*localHost->h_addr_list).s_addr);
   2665             return 0;
   2666         }
   2667     }
   2668     WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, "gethostname failed");
   2669     return -1;
   2670 #else // WEBRTC_LINUX
   2671     int sockfd, size  = 1;
   2672     struct ifreq* ifr;
   2673     struct ifconf ifc;
   2674 
   2675     if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
   2676     {
   2677       return -1;
   2678     }
   2679     ifc.ifc_len = IFRSIZE;
   2680     ifc.ifc_req = NULL;
   2681     do
   2682     {
   2683         ++size;
   2684         // Buffer size needed is unknown. Try increasing it until no overflow
   2685         // occurs.
   2686         if (NULL == (ifc.ifc_req = (ifreq*)realloc(ifc.ifc_req, IFRSIZE))) {
   2687           fprintf(stderr, "Out of memory.\n");
   2688           exit(EXIT_FAILURE);
   2689         }
   2690         ifc.ifc_len = IFRSIZE;
   2691         if (ioctl(sockfd, SIOCGIFCONF, &ifc))
   2692         {
   2693             free(ifc.ifc_req);
   2694             close(sockfd);
   2695             return -1;
   2696         }
   2697     } while  (IFRSIZE <= ifc.ifc_len);
   2698 
   2699     ifr = ifc.ifc_req;
   2700     for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr)
   2701     {
   2702         if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data)
   2703         {
   2704           continue;  // duplicate, skip it
   2705         }
   2706         if (ioctl(sockfd, SIOCGIFFLAGS, ifr))
   2707         {
   2708           continue;  // failed to get flags, skip it
   2709         }
   2710         if(strncmp(ifr->ifr_name, "lo",3) == 0)
   2711         {
   2712             continue;
   2713         }else
   2714         {
   2715             struct sockaddr* saddr = &(ifr->ifr_addr);
   2716             SocketAddress* socket_addess = reinterpret_cast<SocketAddress*>(
   2717                 saddr);
   2718             localIP = Htonl(socket_addess->_sockaddr_in.sin_addr);
   2719             close(sockfd);
   2720             free(ifc.ifc_req);
   2721             return 0;
   2722         }
   2723     }
   2724     free(ifc.ifc_req);
   2725     close(sockfd);
   2726     return -1;
   2727 #endif
   2728 }
   2729 
   2730 int32_t UdpTransport::IPAddress(const SocketAddress& address,
   2731                                 char* ip,
   2732                                 uint32_t& ipSize,
   2733                                 uint16_t& sourcePort)
   2734 {
   2735  #if defined(_WIN32)
   2736     DWORD dwIPSize = ipSize;
   2737     int32_t returnvalue = WSAAddressToStringA((LPSOCKADDR)(&address),
   2738                                          sizeof(SocketAddress),
   2739                                          NULL,
   2740                                          ip,
   2741                                          &dwIPSize);
   2742     if(returnvalue == -1)
   2743     {
   2744         return -1;
   2745     }
   2746 
   2747     uint16_t source_port = 0;
   2748     if(address._sockaddr_storage.sin_family == AF_INET)
   2749     {
   2750         // Parse IP assuming format "a.b.c.d:port".
   2751         char* ipEnd = strchr(ip,':');
   2752         if(ipEnd != NULL)
   2753         {
   2754             *ipEnd = '\0';
   2755         }
   2756         ipSize = (int32_t)strlen(ip);
   2757         if(ipSize == 0)
   2758         {
   2759             return -1;
   2760         }
   2761         source_port = address._sockaddr_in.sin_port;
   2762     }
   2763     else
   2764     {
   2765         // Parse IP assuming format "[address]:port".
   2766         char* ipEnd = strchr(ip,']');
   2767         if(ipEnd != NULL)
   2768         {
   2769           // Calculate length
   2770             int32_t adrSize = int32_t(ipEnd - ip) - 1;
   2771             memmove(ip, &ip[1], adrSize);   // Remove '['
   2772             *(ipEnd - 1) = '\0';
   2773         }
   2774         ipSize = (int32_t)strlen(ip);
   2775         if(ipSize == 0)
   2776         {
   2777             return -1;
   2778         }
   2779 
   2780         source_port = address._sockaddr_in6.sin6_port;
   2781     }
   2782     // Convert port number to network byte order.
   2783     sourcePort = htons(source_port);
   2784     return 0;
   2785 
   2786  #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
   2787     int32_t ipFamily = address._sockaddr_storage.sin_family;
   2788     const void* ptrNumericIP = NULL;
   2789 
   2790     if(ipFamily == AF_INET)
   2791     {
   2792         ptrNumericIP = &(address._sockaddr_in.sin_addr);
   2793     }
   2794     else if(ipFamily == AF_INET6)
   2795     {
   2796         ptrNumericIP = &(address._sockaddr_in6.sin6_addr);
   2797     }
   2798     else
   2799     {
   2800         return -1;
   2801     }
   2802     if(inet_ntop(ipFamily, ptrNumericIP, ip, ipSize) == NULL)
   2803     {
   2804         return -1;
   2805     }
   2806     uint16_t source_port;
   2807     if(ipFamily == AF_INET)
   2808     {
   2809         source_port = address._sockaddr_in.sin_port;
   2810     } else
   2811     {
   2812         source_port = address._sockaddr_in6.sin6_port;
   2813     }
   2814     // Convert port number to network byte order.
   2815     sourcePort = htons(source_port);
   2816     return 0;
   2817  #else
   2818     return -1;
   2819  #endif
   2820 }
   2821 
   2822 bool UdpTransport::IsIpAddressValid(const char* ipadr, const bool ipV6)
   2823 {
   2824     if(ipV6)
   2825     {
   2826         int32_t len = (int32_t)strlen(ipadr);
   2827         if( len>39 || len == 0)
   2828         {
   2829             return false;
   2830         }
   2831 
   2832         int32_t i;
   2833         int32_t colonPos[7] = {0,0,0,0,0,0,0};
   2834         int32_t lastColonPos = -2;
   2835         int32_t nColons = 0;
   2836         int32_t nDubbleColons = 0;
   2837         int32_t nDots = 0;
   2838         int32_t error = 0;
   2839         char c;
   2840         for(i = 0; i < len ; i++)
   2841         {
   2842             c=ipadr[i];
   2843             if(isxdigit(c))
   2844                 ;
   2845             else if(c == ':')
   2846             {
   2847                 if(nColons < 7)
   2848                     colonPos[nColons] = i;
   2849                 if((i-lastColonPos)==1)
   2850                     nDubbleColons++;
   2851                 lastColonPos=i;
   2852                 if(nDots != 0)
   2853                 {
   2854                     error = 1;
   2855                 }
   2856                 nColons++;
   2857             }
   2858             else if(c == '.')
   2859             {
   2860                 nDots++;
   2861             }
   2862             else
   2863             {
   2864                 error = 1;
   2865             }
   2866 
   2867         }
   2868         if(error)
   2869         {
   2870             return false;
   2871         }
   2872         if(nDubbleColons > 1)
   2873         {
   2874             return false;
   2875         }
   2876         if(nColons > 7 || nColons < 2)
   2877         {
   2878             return false;
   2879         }
   2880         if(!(nDots == 3 || nDots == 0))
   2881         {
   2882             return false;
   2883         }
   2884         lastColonPos = -1;
   2885         int32_t charsBeforeColon = 0;
   2886         for(i = 0; i < nColons; i++)
   2887         {
   2888             charsBeforeColon=colonPos[i]-lastColonPos-1;
   2889             if(charsBeforeColon > 4)
   2890             {
   2891                 return false;
   2892             }
   2893             lastColonPos=colonPos[i];
   2894         }
   2895         int32_t lengthAfterLastColon = len - lastColonPos - 1;
   2896         if(nDots == 0)
   2897         {
   2898             if(lengthAfterLastColon > 4)
   2899                 return false;
   2900         }
   2901         if(nDots == 3 && lengthAfterLastColon > 0)
   2902         {
   2903             return IsIpAddressValid((ipadr+lastColonPos+1),false);
   2904         }
   2905 
   2906     }
   2907     else
   2908     {
   2909         int32_t len = (int32_t)strlen(ipadr);
   2910         if((len>15)||(len==0))
   2911         {
   2912             return false;
   2913         }
   2914 
   2915         // IPv4 should be [0-255].[0-255].[0-255].[0-255]
   2916         int32_t i;
   2917         int32_t nDots = 0;
   2918         int32_t iDotPos[4] = {0,0,0,0};
   2919 
   2920         for (i = 0; (i < len) && (nDots < 4); i++)
   2921         {
   2922             if (ipadr[i] == (char)'.')
   2923             {
   2924                 // Store index of dots and count number of dots.
   2925                 iDotPos[nDots++] = i;
   2926             }
   2927         }
   2928 
   2929         bool allUnder256 = false;
   2930         // TODO (hellner): while loop seems to be abused here to get
   2931         // label like functionality. Fix later to avoid introducing bugs now.
   2932 
   2933         // Check that all numbers are smaller than 256.
   2934         do
   2935         {
   2936             if (nDots != 3 )
   2937             {
   2938                 break;
   2939             }
   2940 
   2941             if (iDotPos[0] <= 3)
   2942             {
   2943                 char nr[4];
   2944                 memset(nr,0,4);
   2945                 strncpy(nr,&ipadr[0],iDotPos[0]);
   2946                 int32_t num = atoi(nr);
   2947                 if (num > 255)
   2948                 {
   2949                     break;
   2950                 }
   2951             } else {
   2952                 break;
   2953             }
   2954 
   2955             if (iDotPos[1] - iDotPos[0] <= 4)
   2956             {
   2957                 char nr[4];
   2958                 memset(nr,0,4);
   2959                 strncpy(nr,&ipadr[iDotPos[0]+1], iDotPos[1] - iDotPos[0] - 1);
   2960                 int32_t num = atoi(nr);
   2961                 if (num > 255)
   2962                     break;
   2963             } else {
   2964                 break;
   2965             }
   2966 
   2967             if (iDotPos[2] - iDotPos[1] <= 4)
   2968             {
   2969                 char nr[4];
   2970                 memset(nr,0,4);
   2971                 strncpy(nr,&ipadr[iDotPos[1]+1], iDotPos[1] - iDotPos[0] - 1);
   2972                 int32_t num = atoi(nr);
   2973                 if (num > 255)
   2974                     break;
   2975 
   2976                 memset(nr,0,4);
   2977                 strncpy(nr,&ipadr[iDotPos[2]+1], len - iDotPos[2] -1);
   2978                 num = atoi(nr);
   2979                 if (num > 255)
   2980                     break;
   2981                 else
   2982                     allUnder256 = true;
   2983             } else
   2984                 break;
   2985         } while(false);
   2986 
   2987         if (nDots != 3 || !allUnder256)
   2988         {
   2989             return false;
   2990         }
   2991     }
   2992     return true;
   2993 }
   2994 
   2995 }  // namespace test
   2996 }  // namespace webrtc
   2997