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