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
66namespace webrtc {
67namespace test {
68
69class 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.
85UdpTransport* 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.
96void UdpTransport::Destroy(UdpTransport* module)
97{
98    if(module)
99    {
100        delete module;
101        UdpSocketManager::Return();
102    }
103}
104
105UdpTransportImpl::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
169UdpTransportImpl::~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
183UdpTransport::ErrorCode UdpTransportImpl::LastError() const
184{
185    return _lastError;
186}
187
188bool SameAddress(const SocketAddress& address1, const SocketAddress& address2)
189{
190    return (memcmp(&address1,&address2,sizeof(address1)) == 0);
191}
192
193void 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
206int32_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
234int32_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
362int32_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
386int32_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
400int32_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
417int32_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
427int32_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
440int32_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
665int32_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
717int32_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
727int32_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
923int32_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
932int32_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
1028int32_t UdpTransportImpl::PCP(int32_t& PCP) const
1029{
1030    CriticalSectionScoped cs(_crit);
1031    PCP = _pcp;
1032    return 0;
1033}
1034
1035bool UdpTransportImpl::SetSockOptUsed()
1036{
1037    return _useSetSockOpt;
1038}
1039
1040int32_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
1056int32_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
1077int32_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
1121int32_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
1130bool 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
1144bool UdpTransportImpl::ReceiveSocketsInitialized() const
1145{
1146    if(_ptrRtpSocket)
1147    {
1148        return true;
1149    }
1150    return false;
1151}
1152
1153bool UdpTransportImpl::SourcePortsInitialized() const
1154{
1155    if(_ptrSendRtpSocket)
1156    {
1157        return true;
1158    }
1159    return false;
1160}
1161
1162bool UdpTransportImpl::IpV6Enabled() const
1163{
1164    WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, "%s", __FUNCTION__);
1165    return _ipV6Enabled;
1166}
1167
1168void 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
1197void 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
1227UdpTransportImpl::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
1282UdpTransportImpl::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
1333UdpTransportImpl::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
1407UdpTransportImpl::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
1479int32_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
1532int32_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
1544int32_t UdpTransportImpl::StartReceiving(uint32_t numberOfSocketBuffers)
1545#else
1546int32_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
1590bool UdpTransportImpl::Receiving() const
1591{
1592   return _receiving;
1593}
1594
1595int32_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
1625int32_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
1736void 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
1767int32_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
1843int32_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
1859int32_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
1877int32_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
1905int32_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
1934int 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
2001int 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
2066int32_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
2079int32_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
2095void 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
2107void 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
2120void 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
2183void 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
2243bool 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
2285void 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
2300void 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
2314uint16_t UdpTransport::Htons(const uint16_t port)
2315{
2316    return htons(port);
2317}
2318
2319uint32_t UdpTransport::Htonl(const uint32_t a)
2320{
2321    return htonl(a);
2322}
2323
2324uint32_t UdpTransport::InetAddrIPV4(const char* ip)
2325{
2326    return ::inet_addr(ip);
2327}
2328
2329int32_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
2382int32_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
2620int32_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
2730int32_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
2822bool 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