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