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