Index: webrtc/voice_engine/test/channel_transport/udp_transport_impl.cc |
diff --git a/webrtc/voice_engine/test/channel_transport/udp_transport_impl.cc b/webrtc/voice_engine/test/channel_transport/udp_transport_impl.cc |
deleted file mode 100644 |
index e265c1e84c3aeea6bf09d74f46309e9b5ac3e7f2..0000000000000000000000000000000000000000 |
--- a/webrtc/voice_engine/test/channel_transport/udp_transport_impl.cc |
+++ /dev/null |
@@ -1,3005 +0,0 @@ |
-/* |
- * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
- * |
- * Use of this source code is governed by a BSD-style license |
- * that can be found in the LICENSE file in the root of the source |
- * tree. An additional intellectual property rights grant can be found |
- * in the file PATENTS. All contributing project authors may |
- * be found in the AUTHORS file in the root of the source tree. |
- */ |
- |
-#include "webrtc/voice_engine/test/channel_transport/udp_transport_impl.h" |
- |
-#include <stdio.h> |
-#include <stdlib.h> |
-#include <string.h> |
-#include <time.h> |
- |
-#if defined(_WIN32) |
-#include <winsock2.h> |
-#include <ws2tcpip.h> |
-#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
-#include <arpa/inet.h> |
-#include <ctype.h> |
-#include <fcntl.h> |
-#include <net/if.h> |
-#include <netdb.h> |
-#include <netinet/in.h> |
-#include <stdlib.h> |
-#include <sys/ioctl.h> |
-#include <sys/socket.h> |
-#include <sys/time.h> |
-#include <unistd.h> |
-#ifndef WEBRTC_IOS |
-#include <net/if_arp.h> |
-#endif |
-#endif // defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
- |
-#if defined(WEBRTC_MAC) |
-#include <ifaddrs.h> |
-#include <machine/types.h> |
-#endif |
-#if defined(WEBRTC_LINUX) |
-#include <linux/netlink.h> |
-#include <linux/rtnetlink.h> |
-#endif |
- |
-#include "webrtc/common_types.h" |
-#include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
-#include "webrtc/system_wrappers/include/rw_lock_wrapper.h" |
-#include "webrtc/system_wrappers/include/trace.h" |
-#include "webrtc/voice_engine/test/channel_transport/udp_socket_manager_wrapper.h" |
-#include "webrtc/typedefs.h" |
- |
-#if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
-#define GetLastError() errno |
- |
-#define IFRSIZE ((int)(size * sizeof (struct ifreq))) |
- |
-#define NLMSG_OK_NO_WARNING(nlh,len) \ |
- ((len) >= (int)sizeof(struct nlmsghdr) && \ |
- (int)(nlh)->nlmsg_len >= (int)sizeof(struct nlmsghdr) && \ |
- (int)(nlh)->nlmsg_len <= (len)) |
- |
-#endif // defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
- |
-namespace webrtc { |
-namespace test { |
- |
-class SocketFactory : public UdpTransportImpl::SocketFactoryInterface { |
- public: |
- UdpSocketWrapper* CreateSocket(const int32_t id, |
- UdpSocketManager* mgr, |
- CallbackObj obj, |
- IncomingSocketCallback cb, |
- bool ipV6Enable, |
- bool disableGQOS) override { |
- return UdpSocketWrapper::CreateSocket(id, mgr, obj, cb, ipV6Enable, |
- disableGQOS); |
- } |
-}; |
- |
-// Creates an UdpTransport using the definition of SocketFactory above, |
-// and passes (creating if needed) a pointer to the static singleton |
-// UdpSocketManager. |
-UdpTransport* UdpTransport::Create(const int32_t id, |
- uint8_t& numSocketThreads) |
-{ |
- return new UdpTransportImpl(id, |
- new SocketFactory(), |
- UdpSocketManager::Create(id, numSocketThreads)); |
-} |
- |
-// Deletes the UdpTransport and decrements the refcount of the |
-// static singleton UdpSocketManager, possibly destroying it. |
-// Should only be used on UdpTransports that are created using Create. |
-void UdpTransport::Destroy(UdpTransport* module) |
-{ |
- if(module) |
- { |
- delete module; |
- UdpSocketManager::Return(); |
- } |
-} |
- |
-UdpTransportImpl::UdpTransportImpl(const int32_t id, |
- SocketFactoryInterface* maker, |
- UdpSocketManager* socket_manager) |
- : _id(id), |
- _socket_creator(maker), |
- _crit(CriticalSectionWrapper::CreateCriticalSection()), |
- _critFilter(CriticalSectionWrapper::CreateCriticalSection()), |
- _critPacketCallback(CriticalSectionWrapper::CreateCriticalSection()), |
- _mgr(socket_manager), |
- _lastError(kNoSocketError), |
- _destPort(0), |
- _destPortRTCP(0), |
- _localPort(0), |
- _localPortRTCP(0), |
- _srcPort(0), |
- _srcPortRTCP(0), |
- _fromPort(0), |
- _fromPortRTCP(0), |
- _fromIP(), |
- _destIP(), |
- _localIP(), |
- _localMulticastIP(), |
- _ptrRtpSocket(NULL), |
- _ptrRtcpSocket(NULL), |
- _ptrSendRtpSocket(NULL), |
- _ptrSendRtcpSocket(NULL), |
- _remoteRTPAddr(), |
- _remoteRTCPAddr(), |
- _localRTPAddr(), |
- _localRTCPAddr(), |
- _tos(0), |
- _receiving(false), |
- _useSetSockOpt(false), |
- _qos(false), |
- _pcp(0), |
- _ipV6Enabled(false), |
- _serviceType(0), |
- _overrideDSCP(0), |
- _maxBitrate(0), |
- _cachLock(RWLockWrapper::CreateRWLock()), |
- _previousAddress(), |
- _previousIP(), |
- _previousIPSize(0), |
- _previousSourcePort(0), |
- _filterIPAddress(), |
- _rtpFilterPort(0), |
- _rtcpFilterPort(0), |
- _packetCallback(0) |
-{ |
- memset(&_remoteRTPAddr, 0, sizeof(_remoteRTPAddr)); |
- memset(&_remoteRTCPAddr, 0, sizeof(_remoteRTCPAddr)); |
- memset(&_localRTPAddr, 0, sizeof(_localRTPAddr)); |
- memset(&_localRTCPAddr, 0, sizeof(_localRTCPAddr)); |
- |
- memset(_fromIP, 0, sizeof(_fromIP)); |
- memset(_destIP, 0, sizeof(_destIP)); |
- memset(_localIP, 0, sizeof(_localIP)); |
- memset(_localMulticastIP, 0, sizeof(_localMulticastIP)); |
- |
- memset(&_filterIPAddress, 0, sizeof(_filterIPAddress)); |
- |
- WEBRTC_TRACE(kTraceMemory, kTraceTransport, id, "%s created", __FUNCTION__); |
-} |
- |
-UdpTransportImpl::~UdpTransportImpl() |
-{ |
- CloseSendSockets(); |
- CloseReceiveSockets(); |
- delete _crit; |
- delete _critFilter; |
- delete _critPacketCallback; |
- delete _cachLock; |
- delete _socket_creator; |
- |
- WEBRTC_TRACE(kTraceMemory, kTraceTransport, _id, "%s deleted", |
- __FUNCTION__); |
-} |
- |
-UdpTransport::ErrorCode UdpTransportImpl::LastError() const |
-{ |
- return _lastError; |
-} |
- |
-bool SameAddress(const SocketAddress& address1, const SocketAddress& address2) |
-{ |
- return (memcmp(&address1,&address2,sizeof(address1)) == 0); |
-} |
- |
-void UdpTransportImpl::GetCachedAddress(char* ip, |
- uint32_t& ipSize, |
- uint16_t& sourcePort) |
-{ |
- const uint32_t originalIPSize = ipSize; |
- // If the incoming string is too small, fill it as much as there is room |
- // for. Make sure that there is room for the '\0' character. |
- ipSize = (ipSize - 1 < _previousIPSize) ? ipSize - 1 : _previousIPSize; |
- memcpy(ip,_previousIP,sizeof(int8_t)*(ipSize + 1)); |
- ip[originalIPSize - 1] = '\0'; |
- sourcePort = _previousSourcePort; |
-} |
- |
-int32_t UdpTransportImpl::IPAddressCached(const SocketAddress& address, |
- char* ip, |
- uint32_t& ipSize, |
- uint16_t& sourcePort) |
-{ |
- { |
- ReadLockScoped rl(*_cachLock); |
- // Check if the old address can be re-used (is the same). |
- if(SameAddress(address,_previousAddress)) |
- { |
- GetCachedAddress(ip,ipSize,sourcePort); |
- return 0; |
- } |
- } |
- // Get the new address and store it. |
- WriteLockScoped wl(*_cachLock); |
- ipSize = kIpAddressVersion6Length; |
- if(IPAddress(address,_previousIP,ipSize,_previousSourcePort) != 0) |
- { |
- return -1; |
- } |
- _previousIPSize = ipSize; |
- memcpy(&_previousAddress, &address, sizeof(address)); |
- // Address has been cached at this point. |
- GetCachedAddress(ip,ipSize,sourcePort); |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::InitializeReceiveSockets( |
- UdpTransportData* const packetCallback, |
- const uint16_t portnr, |
- const char* ip, |
- const char* multicastIpAddr, |
- const uint16_t rtcpPort) |
-{ |
- { |
- CriticalSectionScoped cs(_critPacketCallback); |
- _packetCallback = packetCallback; |
- |
- if(packetCallback == NULL) |
- { |
- WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id, |
- "Closing down receive sockets"); |
- return 0; |
- } |
- } |
- |
- CriticalSectionScoped cs(_crit); |
- CloseReceiveSockets(); |
- |
- if(portnr == 0) |
- { |
- // TODO (hellner): why not just fail here? |
- if(_destPort == 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "InitializeReceiveSockets port 0 not allowed"); |
- _lastError = kPortInvalid; |
- return -1; |
- } |
- _localPort = _destPort; |
- } else { |
- _localPort = portnr; |
- } |
- if(rtcpPort) |
- { |
- _localPortRTCP = rtcpPort; |
- }else { |
- _localPortRTCP = _localPort + 1; |
- WEBRTC_TRACE( |
- kTraceStateInfo, |
- kTraceTransport, |
- _id, |
- "InitializeReceiveSockets RTCP port not configured using RTP\ |
- port+1=%d", |
- _localPortRTCP); |
- } |
- |
- if(ip) |
- { |
- if(IsIpAddressValid(ip,IpV6Enabled())) |
- { |
- strncpy(_localIP, ip,kIpAddressVersion6Length); |
- } else |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "InitializeReceiveSockets invalid IP address"); |
- _lastError = kIpAddressInvalid; |
- return -1; |
- } |
- }else |
- { |
- // Don't bind to a specific IP address. |
- if(! IpV6Enabled()) |
- { |
- strncpy(_localIP, "0.0.0.0",16); |
- } else |
- { |
- strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000", |
- kIpAddressVersion6Length); |
- } |
- } |
- if(multicastIpAddr && !IpV6Enabled()) |
- { |
- if(IsIpAddressValid(multicastIpAddr,IpV6Enabled())) |
- { |
- strncpy(_localMulticastIP, multicastIpAddr, |
- kIpAddressVersion6Length); |
- } else |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "InitializeReceiveSockets invalid IP address"); |
- _lastError = kIpAddressInvalid; |
- return -1; |
- } |
- } |
- if(_mgr == NULL) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "InitializeReceiveSockets no socket manager"); |
- return -1; |
- } |
- |
- _useSetSockOpt=false; |
- _tos=0; |
- _pcp=0; |
- |
- _ptrRtpSocket = _socket_creator->CreateSocket(_id, _mgr, this, |
- IncomingRTPCallback, |
- IpV6Enabled(), false); |
- |
- _ptrRtcpSocket = _socket_creator->CreateSocket(_id, _mgr, this, |
- IncomingRTCPCallback, |
- IpV6Enabled(), false); |
- |
- ErrorCode retVal = BindLocalRTPSocket(); |
- if(retVal != kNoSocketError) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "InitializeReceiveSockets faild to bind RTP socket"); |
- _lastError = retVal; |
- CloseReceiveSockets(); |
- return -1; |
- } |
- retVal = BindLocalRTCPSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "InitializeReceiveSockets faild to bind RTCP socket"); |
- CloseReceiveSockets(); |
- return -1; |
- } |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::ReceiveSocketInformation( |
- char ipAddr[kIpAddressVersion6Length], |
- uint16_t& rtpPort, |
- uint16_t& rtcpPort, |
- char multicastIpAddr[kIpAddressVersion6Length]) const |
-{ |
- CriticalSectionScoped cs(_crit); |
- rtpPort = _localPort; |
- rtcpPort = _localPortRTCP; |
- if (ipAddr) |
- { |
- strncpy(ipAddr, _localIP, IpV6Enabled() ? |
- UdpTransport::kIpAddressVersion6Length : |
- UdpTransport::kIpAddressVersion4Length); |
- } |
- if (multicastIpAddr) |
- { |
- strncpy(multicastIpAddr, _localMulticastIP, IpV6Enabled() ? |
- UdpTransport::kIpAddressVersion6Length : |
- UdpTransport::kIpAddressVersion4Length); |
- } |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::SendSocketInformation( |
- char ipAddr[kIpAddressVersion6Length], |
- uint16_t& rtpPort, |
- uint16_t& rtcpPort) const |
-{ |
- CriticalSectionScoped cs(_crit); |
- rtpPort = _destPort; |
- rtcpPort = _destPortRTCP; |
- strncpy(ipAddr, _destIP, IpV6Enabled() ? |
- UdpTransport::kIpAddressVersion6Length : |
- UdpTransport::kIpAddressVersion4Length); |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::RemoteSocketInformation( |
- char ipAddr[kIpAddressVersion6Length], |
- uint16_t& rtpPort, |
- uint16_t& rtcpPort) const |
-{ |
- CriticalSectionScoped cs(_crit); |
- rtpPort = _fromPort; |
- rtcpPort = _fromPortRTCP; |
- if(ipAddr) |
- { |
- strncpy(ipAddr, _fromIP, IpV6Enabled() ? |
- kIpAddressVersion6Length : |
- kIpAddressVersion4Length); |
- } |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::FilterPorts( |
- uint16_t& rtpFilterPort, |
- uint16_t& rtcpFilterPort) const |
-{ |
- CriticalSectionScoped cs(_critFilter); |
- rtpFilterPort = _rtpFilterPort; |
- rtcpFilterPort = _rtcpFilterPort; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::SetQoS(bool QoS, int32_t serviceType, |
- uint32_t maxBitrate, |
- int32_t overrideDSCP, bool audio) |
-{ |
- if(QoS) |
- { |
- return EnableQoS(serviceType, audio, maxBitrate, overrideDSCP); |
- }else |
- { |
- return DisableQoS(); |
- } |
-} |
- |
-int32_t UdpTransportImpl::EnableQoS(int32_t serviceType, |
- bool audio, uint32_t maxBitrate, |
- int32_t overrideDSCP) |
-{ |
- if (_ipV6Enabled) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "QOS is enabled but will be ignored since IPv6 is enabled"); |
- _lastError = kQosError; |
- return -1; |
- } |
- if (_tos) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "TOS already enabled, can't use TOS and QoS at the same time"); |
- _lastError = kQosError; |
- return -1; |
- } |
- if (_pcp) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "PCP already enabled, can't use PCP and QoS at the same time"); |
- _lastError = kQosError; |
- return -1; |
- } |
- if(_destPort == 0) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "QOS is enabled but not started since we have not yet configured\ |
- the send destination"); |
- return -1; |
- } |
- if(_qos) |
- { |
- if(_overrideDSCP == 0 && overrideDSCP != 0) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "QOS is already enabled and overrideDSCP differs, not allowed"); |
- return -1; |
- } |
- } |
- CriticalSectionScoped cs(_crit); |
- |
- UdpSocketWrapper* rtpSock = _ptrSendRtpSocket ? |
- _ptrSendRtpSocket : |
- _ptrRtpSocket; |
- if (!rtpSock || !rtpSock->ValidHandle()) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "QOS is enabled but not started since we have not yet created the\ |
- RTP socket"); |
- return -1; |
- } |
- UdpSocketWrapper* rtcpSock = _ptrSendRtcpSocket ? |
- _ptrSendRtcpSocket : |
- _ptrRtcpSocket; |
- if (!rtcpSock || !rtcpSock->ValidHandle()) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "QOS is enabled but not started since we have not yet created the\ |
- RTCP socket"); |
- return -1; |
- } |
- |
- // Minimum packet size in bytes for which the requested quality of service |
- // will be provided. The smallest RTP header is 12 byte. |
- const int32_t min_policed_size = 12; |
- // Max SDU, maximum packet size permitted or used in the traffic flow, in |
- // bytes. |
- const int32_t max_sdu_size = 1500; |
- |
- // Enable QoS for RTP sockets. |
- if(maxBitrate) |
- { |
- // Note: 1 kbit is 125 bytes. |
- // Token Rate is typically set to the average bit rate from peak to |
- // peak. |
- // Bucket size is normally set to the largest average frame size. |
- if(audio) |
- { |
- WEBRTC_TRACE(kTraceStateInfo, |
- kTraceTransport, |
- _id, |
- "Enable QOS for audio with max bitrate:%d", |
- maxBitrate); |
- |
- const int32_t token_rate = maxBitrate*125; |
- // The largest audio packets are 60ms frames. This is a fraction |
- // more than 16 packets/second. These 16 frames are sent, at max, |
- // at a bitrate of maxBitrate*125 -> 1 frame is maxBitrate*125/16 ~ |
- // maxBitrate * 8. |
- const int32_t bucket_size = maxBitrate * 8; |
- const int32_t peek_bandwith = maxBitrate * 125; |
- if (!rtpSock->SetQos(serviceType, token_rate, bucket_size, |
- peek_bandwith, min_policed_size, |
- max_sdu_size, _remoteRTPAddr, overrideDSCP)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "QOS failed on the RTP socket"); |
- _lastError = kQosError; |
- return -1; |
- } |
- }else |
- { |
- WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id, |
- "Enable QOS for video with max bitrate:%d", |
- maxBitrate); |
- |
- // Allow for a token rate that is twice that of the maximum bitrate |
- // (in bytes). |
- const int32_t token_rate = maxBitrate*250; |
- // largest average frame size (key frame size). Assuming that a |
- // keyframe is 25% of the bitrate during the second its sent |
- // Assume that a key frame is 25% of the bitrate the second that it |
- // is sent. The largest frame size is then maxBitrate* 125 * 0.25 ~ |
- // 31. |
- const int32_t bucket_size = maxBitrate*31; |
- const int32_t peek_bandwith = maxBitrate*125; |
- if (!rtpSock->SetQos(serviceType, token_rate, bucket_size, |
- peek_bandwith, min_policed_size, max_sdu_size, |
- _remoteRTPAddr, overrideDSCP)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "QOS failed on the RTP socket"); |
- _lastError = kQosError; |
- return -1; |
- } |
- } |
- } else if(audio) |
- { |
- // No max bitrate set. Audio. |
- WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id, |
- "Enable QOS for audio with default max bitrate"); |
- |
- // Let max bitrate be 240kbit/s. |
- const int32_t token_rate = 30000; |
- const int32_t bucket_size = 2000; |
- const int32_t peek_bandwith = 30000; |
- if (!rtpSock->SetQos(serviceType, token_rate, bucket_size, |
- peek_bandwith, min_policed_size, max_sdu_size, |
- _remoteRTPAddr, overrideDSCP)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "QOS failed on the RTP socket"); |
- _lastError = kQosError; |
- return -1; |
- } |
- }else |
- { |
- // No max bitrate set. Video. |
- WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, _id, |
- "Enable QOS for video with default max bitrate"); |
- |
- // Let max bitrate be 10mbit/s. |
- const int32_t token_rate = 128000*10; |
- const int32_t bucket_size = 32000; |
- const int32_t peek_bandwith = 256000; |
- if (!rtpSock->SetQos(serviceType, token_rate, bucket_size, |
- peek_bandwith, min_policed_size, max_sdu_size, |
- _remoteRTPAddr, overrideDSCP)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "QOS failed on the RTP socket"); |
- _lastError = kQosError; |
- return -1; |
- } |
- } |
- |
- // Enable QoS for RTCP sockets. |
- // TODO (hellner): shouldn't RTCP be based on 5% of the maximum bandwidth? |
- if(audio) |
- { |
- const int32_t token_rate = 200; |
- const int32_t bucket_size = 200; |
- const int32_t peek_bandwith = 400; |
- if (!rtcpSock->SetQos(serviceType, token_rate, bucket_size, |
- peek_bandwith, min_policed_size, max_sdu_size, |
- _remoteRTCPAddr, overrideDSCP)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "QOS failed on the RTCP socket"); |
- _lastError = kQosError; |
- } |
- }else |
- { |
- const int32_t token_rate = 5000; |
- const int32_t bucket_size = 100; |
- const int32_t peek_bandwith = 10000; |
- if (!rtcpSock->SetQos(serviceType, token_rate, bucket_size, |
- peek_bandwith, min_policed_size, max_sdu_size, |
- _remoteRTCPAddr, _overrideDSCP)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "QOS failed on the RTCP socket"); |
- _lastError = kQosError; |
- } |
- } |
- _qos = true; |
- _serviceType = serviceType; |
- _maxBitrate = maxBitrate; |
- _overrideDSCP = overrideDSCP; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::DisableQoS() |
-{ |
- if(_qos == false) |
- { |
- return 0; |
- } |
- CriticalSectionScoped cs(_crit); |
- |
- UdpSocketWrapper* rtpSock = (_ptrSendRtpSocket ? |
- _ptrSendRtpSocket : _ptrRtpSocket); |
- if (!rtpSock || !rtpSock->ValidHandle()) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "QOS is enabled but not started since we have not yet created the\ |
- RTP socket"); |
- return -1; |
- } |
- UdpSocketWrapper* rtcpSock = (_ptrSendRtcpSocket ? |
- _ptrSendRtcpSocket : _ptrRtcpSocket); |
- if (!rtcpSock || !rtcpSock->ValidHandle()) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "QOS is enabled but not started since we have not yet created the\ |
- RTCP socket"); |
- return -1; |
- } |
- |
- const int32_t service_type = 0; // = SERVICETYPE_NOTRAFFIC |
- const int32_t not_specified = -1; |
- if (!rtpSock->SetQos(service_type, not_specified, not_specified, |
- not_specified, not_specified, not_specified, |
- _remoteRTPAddr, _overrideDSCP)) |
- { |
- _lastError = kQosError; |
- return -1; |
- } |
- if (!rtcpSock->SetQos(service_type, not_specified, not_specified, |
- not_specified, not_specified, not_specified, |
- _remoteRTCPAddr,_overrideDSCP)) |
- { |
- _lastError = kQosError; |
- } |
- _qos = false; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::QoS(bool& QoS, int32_t& serviceType, |
- int32_t& overrideDSCP) const |
-{ |
- CriticalSectionScoped cs(_crit); |
- QoS = _qos; |
- serviceType = _serviceType; |
- overrideDSCP = _overrideDSCP; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::SetToS(int32_t DSCP, bool useSetSockOpt) |
-{ |
- if (_qos) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "QoS already enabled"); |
- _lastError = kQosError; |
- return -1; |
- } |
- if (DSCP < 0 || DSCP > 63) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "Invalid DSCP"); |
- _lastError = kTosInvalid; |
- return -1; |
- } |
- if(_tos) |
- { |
- if(useSetSockOpt != _useSetSockOpt) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "Can't switch SetSockOpt method without disabling TOS first"); |
- _lastError = kTosInvalid; |
- return -1; |
- } |
- } |
- CriticalSectionScoped cs(_crit); |
- UdpSocketWrapper* rtpSock = NULL; |
- UdpSocketWrapper* rtcpSock = NULL; |
- if(_ptrSendRtpSocket) |
- { |
- rtpSock = _ptrSendRtpSocket; |
- }else |
- { |
- rtpSock = _ptrRtpSocket; |
- } |
- if (rtpSock == NULL) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- if(!rtpSock->ValidHandle()) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- if(_ptrSendRtcpSocket) |
- { |
- rtcpSock = _ptrSendRtcpSocket; |
- }else |
- { |
- rtcpSock = _ptrRtcpSocket; |
- } |
- if (rtcpSock == NULL) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- if(!rtcpSock->ValidHandle()) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- |
- if (useSetSockOpt) |
- { |
-#ifdef _WIN32 |
- OSVERSIONINFO OsVersion; |
- OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
- GetVersionEx(&OsVersion); |
- // Disable QoS before setting ToS on Windows XP. This is done by closing |
- // and re-opening the sockets. |
- // TODO (hellner): why not just fail here and force the user to |
- // re-initialize sockets? Doing this may trick the user |
- // into thinking that the sockets are in a state which |
- // they aren't. |
- if (OsVersion.dwMajorVersion == 5 && |
- OsVersion.dwMinorVersion == 1) |
- { |
- if(!_useSetSockOpt) |
- { |
- if(_ptrSendRtpSocket) |
- { |
- CloseSendSockets(); |
- _ptrSendRtpSocket = |
- _socket_creator->CreateSocket(_id, _mgr, NULL, |
- NULL, IpV6Enabled(), |
- true); |
- _ptrSendRtcpSocket = |
- _socket_creator->CreateSocket(_id, _mgr, NULL, |
- NULL, IpV6Enabled(), |
- true); |
- rtpSock=_ptrSendRtpSocket; |
- rtcpSock=_ptrSendRtcpSocket; |
- ErrorCode retVal = BindRTPSendSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- return -1; |
- } |
- retVal = BindRTCPSendSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- return -1; |
- } |
- } |
- else |
- { |
- bool receiving=_receiving; |
- uint32_t noOfReceiveBuffers = 0; |
- if(receiving) |
- { |
- noOfReceiveBuffers=_ptrRtpSocket->ReceiveBuffers(); |
- if(StopReceiving()!=0) |
- { |
- return -1; |
- } |
- } |
- CloseReceiveSockets(); |
- _ptrRtpSocket = _socket_creator->CreateSocket( |
- _id, _mgr, this, IncomingRTPCallback, IpV6Enabled(), |
- true); |
- _ptrRtcpSocket = _socket_creator->CreateSocket( |
- _id, _mgr, this, IncomingRTCPCallback, IpV6Enabled(), |
- true); |
- rtpSock=_ptrRtpSocket; |
- rtcpSock=_ptrRtcpSocket; |
- ErrorCode retVal = BindLocalRTPSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- return -1; |
- } |
- retVal = BindLocalRTCPSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- return -1; |
- } |
- if(receiving) |
- { |
- if(StartReceiving(noOfReceiveBuffers) != |
- kNoSocketError) |
- { |
- return -1; |
- } |
- } |
- } |
- } |
- } |
-#endif // #ifdef _WIN32 |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "Setting TOS using SetSockopt"); |
- int32_t TOSShifted = DSCP << 2; |
- if (!rtpSock->SetSockopt(IPPROTO_IP, IP_TOS, |
- (int8_t*) &TOSShifted, 4)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not SetSockopt tos value on RTP socket"); |
- _lastError = kTosInvalid; |
- return -1; |
- } |
- if (!rtcpSock->SetSockopt(IPPROTO_IP, IP_TOS, |
- (int8_t*) &TOSShifted, 4)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not sSetSockopt tos value on RTCP socket"); |
- _lastError = kTosInvalid; |
- return -1; |
- } |
- } else |
- { |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
- "Setting TOS NOT using SetSockopt"); |
- if (rtpSock->SetTOS(DSCP) != 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not set tos value on RTP socket"); |
- _lastError = kTosError; |
- return -1; |
- } |
- if (rtcpSock->SetTOS(DSCP) != 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not set tos value on RTCP socket"); |
- _lastError = kTosError; |
- return -1; |
- } |
- } |
- _useSetSockOpt = useSetSockOpt; |
- _tos = DSCP; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::ToS(int32_t& DSCP, |
- bool& useSetSockOpt) const |
-{ |
- CriticalSectionScoped cs(_crit); |
- DSCP = _tos; |
- useSetSockOpt = _useSetSockOpt; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::SetPCP(int32_t PCP) |
-{ |
- |
- if (_qos) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "QoS already enabled"); |
- _lastError = kQosError; |
- return -1; |
- } |
- if ((PCP < 0) || (PCP > 7)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "Invalid PCP"); |
- _lastError = kPcpError; |
- return -1; |
- } |
- |
- CriticalSectionScoped cs(_crit); |
- UdpSocketWrapper* rtpSock = NULL; |
- UdpSocketWrapper* rtcpSock = NULL; |
- if(_ptrSendRtpSocket) |
- { |
- rtpSock = _ptrSendRtpSocket; |
- }else |
- { |
- rtpSock = _ptrRtpSocket; |
- } |
- if (rtpSock == NULL) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- if(!rtpSock->ValidHandle()) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- if(_ptrSendRtcpSocket) |
- { |
- rtcpSock = _ptrSendRtcpSocket; |
- }else |
- { |
- rtcpSock = _ptrRtcpSocket; |
- } |
- if (rtcpSock == NULL) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- if(!rtcpSock->ValidHandle()) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- |
-#if defined(_WIN32) |
- if (rtpSock->SetPCP(PCP) != 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not set PCP value on RTP socket"); |
- _lastError = kPcpError; |
- return -1; |
- } |
- if (rtcpSock->SetPCP(PCP) != 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not set PCP value on RTCP socket"); |
- _lastError = kPcpError; |
- return -1; |
- } |
- |
-#elif defined(WEBRTC_LINUX) |
- if (!rtpSock->SetSockopt(SOL_SOCKET, SO_PRIORITY, (int8_t*) &PCP, |
- sizeof(PCP))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not SetSockopt PCP value on RTP socket"); |
- _lastError = kPcpError; |
- return -1; |
- } |
- if (!rtcpSock->SetSockopt(SOL_SOCKET, SO_PRIORITY, (int8_t*) &PCP, |
- sizeof(PCP))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Could not SetSockopt PCP value on RTCP socket"); |
- _lastError = kPcpError; |
- return -1; |
- } |
-#else |
- // Not supported on other platforms (WEBRTC_MAC) |
- _lastError = kPcpError; |
- return -1; |
-#endif |
- _pcp = PCP; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::PCP(int32_t& PCP) const |
-{ |
- CriticalSectionScoped cs(_crit); |
- PCP = _pcp; |
- return 0; |
-} |
- |
-bool UdpTransportImpl::SetSockOptUsed() |
-{ |
- return _useSetSockOpt; |
-} |
- |
-int32_t UdpTransportImpl::EnableIpV6() { |
- |
- CriticalSectionScoped cs(_crit); |
- const bool initialized = (_ptrSendRtpSocket || _ptrRtpSocket); |
- |
- if (_ipV6Enabled) { |
- return 0; |
- } |
- if (initialized) { |
- _lastError = kIpVersion6Error; |
- return -1; |
- } |
- _ipV6Enabled = true; |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::FilterIP( |
- char filterIPAddress[kIpAddressVersion6Length]) const |
-{ |
- |
- if(filterIPAddress == NULL) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "FilterIP: Invalid argument"); |
- return -1; |
- } |
- if(_filterIPAddress._sockaddr_storage.sin_family == 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "No Filter configured"); |
- return -1; |
- } |
- CriticalSectionScoped cs(_critFilter); |
- uint32_t ipSize = kIpAddressVersion6Length; |
- uint16_t sourcePort; |
- return IPAddress(_filterIPAddress, filterIPAddress, ipSize, sourcePort); |
-} |
- |
-int32_t UdpTransportImpl::SetFilterIP( |
- const char filterIPAddress[kIpAddressVersion6Length]) |
-{ |
- if(filterIPAddress == NULL) |
- { |
- memset(&_filterIPAddress, 0, sizeof(_filterIPAddress)); |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, "Filter IP reset"); |
- return 0; |
- } |
- CriticalSectionScoped cs(_critFilter); |
- if (_ipV6Enabled) |
- { |
- _filterIPAddress._sockaddr_storage.sin_family = AF_INET6; |
- |
- if (InetPresentationToNumeric( |
- AF_INET6, |
- filterIPAddress, |
- &_filterIPAddress._sockaddr_in6.sin6_addr) < 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, "Failed to set\ |
- filter IP for IPv6"); |
- _lastError = FILTER_ERROR; |
- return -1; |
- } |
- } |
- else |
- { |
- _filterIPAddress._sockaddr_storage.sin_family = AF_INET; |
- |
- if(InetPresentationToNumeric( |
- AF_INET, |
- filterIPAddress, |
- &_filterIPAddress._sockaddr_in.sin_addr) < 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Failed to set filter IP for IPv4"); |
- _lastError = FILTER_ERROR; |
- return -1; |
- } |
- } |
- WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, "Filter IP set"); |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::SetFilterPorts(uint16_t rtpFilterPort, |
- uint16_t rtcpFilterPort) |
-{ |
- CriticalSectionScoped cs(_critFilter); |
- _rtpFilterPort = rtpFilterPort; |
- _rtcpFilterPort = rtcpFilterPort; |
- return 0; |
-} |
- |
-bool UdpTransportImpl::SendSocketsInitialized() const |
-{ |
- CriticalSectionScoped cs(_crit); |
- if(_ptrSendRtpSocket) |
- { |
- return true; |
- } |
- if(_destPort !=0) |
- { |
- return true; |
- } |
- return false; |
-} |
- |
-bool UdpTransportImpl::ReceiveSocketsInitialized() const |
-{ |
- if(_ptrRtpSocket) |
- { |
- return true; |
- } |
- return false; |
-} |
- |
-bool UdpTransportImpl::SourcePortsInitialized() const |
-{ |
- if(_ptrSendRtpSocket) |
- { |
- return true; |
- } |
- return false; |
-} |
- |
-bool UdpTransportImpl::IpV6Enabled() const |
-{ |
- WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, "%s", __FUNCTION__); |
- return _ipV6Enabled; |
-} |
- |
-void UdpTransportImpl::BuildRemoteRTPAddr() |
-{ |
- if(_ipV6Enabled) |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _remoteRTPAddr.sin_length = 0; |
- _remoteRTPAddr.sin_family = PF_INET6; |
-#else |
- _remoteRTPAddr._sockaddr_storage.sin_family = PF_INET6; |
-#endif |
- |
- _remoteRTPAddr._sockaddr_in6.sin6_flowinfo=0; |
- _remoteRTPAddr._sockaddr_in6.sin6_scope_id=0; |
- _remoteRTPAddr._sockaddr_in6.sin6_port = Htons(_destPort); |
- InetPresentationToNumeric(AF_INET6,_destIP, |
- &_remoteRTPAddr._sockaddr_in6.sin6_addr); |
- } else |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _remoteRTPAddr.sin_length = 0; |
- _remoteRTPAddr.sin_family = PF_INET; |
-#else |
- _remoteRTPAddr._sockaddr_storage.sin_family = PF_INET; |
-#endif |
- _remoteRTPAddr._sockaddr_in.sin_port = Htons(_destPort); |
- _remoteRTPAddr._sockaddr_in.sin_addr = InetAddrIPV4(_destIP); |
- } |
-} |
- |
-void UdpTransportImpl::BuildRemoteRTCPAddr() |
-{ |
- if(_ipV6Enabled) |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _remoteRTCPAddr.sin_length = 0; |
- _remoteRTCPAddr.sin_family = PF_INET6; |
-#else |
- _remoteRTCPAddr._sockaddr_storage.sin_family = PF_INET6; |
-#endif |
- |
- _remoteRTCPAddr._sockaddr_in6.sin6_flowinfo=0; |
- _remoteRTCPAddr._sockaddr_in6.sin6_scope_id=0; |
- _remoteRTCPAddr._sockaddr_in6.sin6_port = Htons(_destPortRTCP); |
- InetPresentationToNumeric(AF_INET6,_destIP, |
- &_remoteRTCPAddr._sockaddr_in6.sin6_addr); |
- |
- } else |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _remoteRTCPAddr.sin_length = 0; |
- _remoteRTCPAddr.sin_family = PF_INET; |
-#else |
- _remoteRTCPAddr._sockaddr_storage.sin_family = PF_INET; |
-#endif |
- _remoteRTCPAddr._sockaddr_in.sin_port = Htons(_destPortRTCP); |
- _remoteRTCPAddr._sockaddr_in.sin_addr= InetAddrIPV4(_destIP); |
- } |
-} |
- |
-UdpTransportImpl::ErrorCode UdpTransportImpl::BindRTPSendSocket() |
-{ |
- if(!_ptrSendRtpSocket) |
- { |
- return kSocketInvalid; |
- } |
- if(!_ptrSendRtpSocket->ValidHandle()) |
- { |
- return kIpAddressInvalid; |
- } |
- if(_ipV6Enabled) |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _localRTPAddr.sin_length = 0; |
- _localRTPAddr.sin_family = PF_INET6; |
-#else |
- _localRTPAddr._sockaddr_storage.sin_family = PF_INET6; |
-#endif |
- _localRTPAddr._sockaddr_in6.sin6_flowinfo=0; |
- _localRTPAddr._sockaddr_in6.sin6_scope_id=0; |
- _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[0] = |
- 0; // = INADDR_ANY |
- _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[1] = |
- 0; |
- _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[2] = |
- 0; |
- _localRTPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[3] = |
- 0; |
- _localRTPAddr._sockaddr_in6.sin6_port = Htons(_srcPort); |
- if(_ptrSendRtpSocket->Bind(_localRTPAddr) == false) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _srcPort); |
- return kFailedToBindPort; |
- } |
- |
- } else { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _localRTPAddr.sin_length = 0; |
- _localRTPAddr.sin_family = PF_INET; |
-#else |
- _localRTPAddr._sockaddr_storage.sin_family = PF_INET; |
-#endif |
- _localRTPAddr._sockaddr_in.sin_addr = 0; |
- _localRTPAddr._sockaddr_in.sin_port = Htons(_srcPort); |
- if(_ptrSendRtpSocket->Bind(_localRTPAddr) == false) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _srcPort); |
- return kFailedToBindPort; |
- } |
- } |
- return kNoSocketError; |
-} |
- |
-UdpTransportImpl::ErrorCode UdpTransportImpl::BindRTCPSendSocket() |
-{ |
- if(!_ptrSendRtcpSocket) |
- { |
- return kSocketInvalid; |
- } |
- |
- if(_ipV6Enabled) |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _localRTCPAddr.sin_length = 0; |
- _localRTCPAddr.sin_family = PF_INET6; |
-#else |
- _localRTCPAddr._sockaddr_storage.sin_family = PF_INET6; |
-#endif |
- _localRTCPAddr._sockaddr_in6.sin6_flowinfo=0; |
- _localRTCPAddr._sockaddr_in6.sin6_scope_id=0; |
- _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[0] = |
- 0; // = INADDR_ANY |
- _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[1] = |
- 0; |
- _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[2] = |
- 0; |
- _localRTCPAddr._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[3] = |
- 0; |
- _localRTCPAddr._sockaddr_in6.sin6_port = Htons(_srcPortRTCP); |
- if(_ptrSendRtcpSocket->Bind(_localRTCPAddr) == false) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _srcPortRTCP); |
- return kFailedToBindPort; |
- } |
- } else { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- _localRTCPAddr.sin_length = 0; |
- _localRTCPAddr.sin_family = PF_INET; |
-#else |
- _localRTCPAddr._sockaddr_storage.sin_family = PF_INET; |
-#endif |
- _localRTCPAddr._sockaddr_in.sin_addr= 0; |
- _localRTCPAddr._sockaddr_in.sin_port = Htons(_srcPortRTCP); |
- if(_ptrSendRtcpSocket->Bind(_localRTCPAddr) == false) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _srcPortRTCP); |
- return kFailedToBindPort; |
- } |
- } |
- return kNoSocketError; |
-} |
- |
-UdpTransportImpl::ErrorCode UdpTransportImpl::BindLocalRTPSocket() |
-{ |
- if(!_ptrRtpSocket) |
- { |
- return kSocketInvalid; |
- } |
- if(!IpV6Enabled()) |
- { |
- SocketAddress recAddr; |
- memset(&recAddr, 0, sizeof(SocketAddress)); |
- recAddr._sockaddr_storage.sin_family = AF_INET; |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- recAddr.sin_length = 0; |
- recAddr.sin_family = PF_INET; |
-#else |
- recAddr._sockaddr_storage.sin_family = PF_INET; |
-#endif |
- recAddr._sockaddr_in.sin_addr = InetAddrIPV4(_localIP); |
- recAddr._sockaddr_in.sin_port = Htons(_localPort); |
- |
- if (!_ptrRtpSocket->Bind(recAddr)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _localPort); |
- return kFailedToBindPort; |
- } |
- } |
- else |
- { |
- SocketAddress stLclName; |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- stLclName.sin_lenght = 0; |
- stLclName.sin_family = PF_INET6; |
-#else |
- stLclName._sockaddr_storage.sin_family = PF_INET6; |
-#endif |
- InetPresentationToNumeric(AF_INET6,_localIP, |
- &stLclName._sockaddr_in6.sin6_addr); |
- stLclName._sockaddr_in6.sin6_port = Htons(_localPort); |
- stLclName._sockaddr_in6.sin6_flowinfo = 0; |
- stLclName._sockaddr_in6.sin6_scope_id = 0; |
- |
- if (!_ptrRtpSocket->Bind(stLclName)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _localPort); |
- return kFailedToBindPort; |
- } |
- } |
- |
- if(_localMulticastIP[0] != 0) |
- { |
- // Join the multicast group from which to receive datagrams. |
- struct ip_mreq mreq; |
- mreq.imr_multiaddr.s_addr = InetAddrIPV4(_localMulticastIP); |
- mreq.imr_interface.s_addr = INADDR_ANY; |
- |
- if (!_ptrRtpSocket->SetSockopt(IPPROTO_IP,IP_ADD_MEMBERSHIP, |
- (int8_t*)&mreq,sizeof (mreq))) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "setsockopt() for multicast failed, not closing socket"); |
- }else |
- { |
- WEBRTC_TRACE(kTraceInfo, kTraceTransport, _id, |
- "multicast group successfully joined"); |
- } |
- } |
- return kNoSocketError; |
-} |
- |
-UdpTransportImpl::ErrorCode UdpTransportImpl::BindLocalRTCPSocket() |
-{ |
- if(!_ptrRtcpSocket) |
- { |
- return kSocketInvalid; |
- } |
- if(! IpV6Enabled()) |
- { |
- SocketAddress recAddr; |
- memset(&recAddr, 0, sizeof(SocketAddress)); |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- recAddr.sin_length = 0; |
- recAddr.sin_family = AF_INET; |
-#else |
- recAddr._sockaddr_storage.sin_family = AF_INET; |
-#endif |
- recAddr._sockaddr_in.sin_addr = InetAddrIPV4(_localIP); |
- recAddr._sockaddr_in.sin_port = Htons(_localPortRTCP); |
- |
- if (!_ptrRtcpSocket->Bind(recAddr)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _localPortRTCP); |
- return kFailedToBindPort; |
- } |
- } |
- else |
- { |
- SocketAddress stLclName; |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- stLclName.sin_length = 0; |
- stLclName.sin_family = PF_INET6; |
-#else |
- stLclName._sockaddr_storage.sin_family = PF_INET6; |
-#endif |
- stLclName._sockaddr_in6.sin6_flowinfo = 0; |
- stLclName._sockaddr_in6.sin6_scope_id = 0; |
- stLclName._sockaddr_in6.sin6_port = Htons(_localPortRTCP); |
- |
- InetPresentationToNumeric(AF_INET6,_localIP, |
- &stLclName._sockaddr_in6.sin6_addr); |
- if (!_ptrRtcpSocket->Bind(stLclName)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, _id, |
- "Failed to bind to port:%d ", _localPortRTCP); |
- return kFailedToBindPort; |
- } |
- } |
- if(_localMulticastIP[0] != 0) |
- { |
- // Join the multicast group from which to receive datagrams. |
- struct ip_mreq mreq; |
- mreq.imr_multiaddr.s_addr = InetAddrIPV4(_localMulticastIP); |
- mreq.imr_interface.s_addr = INADDR_ANY; |
- |
- if (!_ptrRtcpSocket->SetSockopt(IPPROTO_IP,IP_ADD_MEMBERSHIP, |
- (int8_t*)&mreq,sizeof (mreq))) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "setsockopt() for multicast failed, not closing socket"); |
- }else |
- { |
- WEBRTC_TRACE(kTraceInfo, kTraceTransport, _id, |
- "multicast group successfully joined"); |
- } |
- } |
- return kNoSocketError; |
-} |
- |
-int32_t UdpTransportImpl::InitializeSourcePorts(uint16_t rtpPort, |
- uint16_t rtcpPort) |
-{ |
- |
- if(rtpPort == 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "InitializeSourcePorts port 0 not allowed"); |
- _lastError = kPortInvalid; |
- return -1; |
- } |
- |
- CriticalSectionScoped cs(_crit); |
- |
- CloseSendSockets(); |
- |
- if(_mgr == NULL) |
- { |
- return -1; |
- } |
- |
- _srcPort = rtpPort; |
- if(rtcpPort == 0) |
- { |
- _srcPortRTCP = rtpPort+1; |
- } else |
- { |
- _srcPortRTCP = rtcpPort; |
- } |
- _useSetSockOpt =false; |
- _tos=0; |
- _pcp=0; |
- |
- _ptrSendRtpSocket = _socket_creator->CreateSocket(_id, _mgr, NULL, NULL, |
- IpV6Enabled(), false); |
- _ptrSendRtcpSocket = _socket_creator->CreateSocket(_id, _mgr, NULL, NULL, |
- IpV6Enabled(), false); |
- |
- ErrorCode retVal = BindRTPSendSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- return -1; |
- } |
- retVal = BindRTCPSendSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- return -1; |
- } |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::SourcePorts(uint16_t& rtpPort, |
- uint16_t& rtcpPort) const |
-{ |
- CriticalSectionScoped cs(_crit); |
- |
- rtpPort = (_srcPort != 0) ? _srcPort : _localPort; |
- rtcpPort = (_srcPortRTCP != 0) ? _srcPortRTCP : _localPortRTCP; |
- return 0; |
-} |
- |
- |
-#ifdef _WIN32 |
-int32_t UdpTransportImpl::StartReceiving(uint32_t numberOfSocketBuffers) |
-#else |
-int32_t UdpTransportImpl::StartReceiving(uint32_t /*numberOfSocketBuffers*/) |
-#endif |
-{ |
- CriticalSectionScoped cs(_crit); |
- if(_receiving) |
- { |
- return 0; |
- } |
- if(_ptrRtpSocket) |
- { |
-#ifdef _WIN32 |
- if(!_ptrRtpSocket->StartReceiving(numberOfSocketBuffers)) |
-#else |
- if(!_ptrRtpSocket->StartReceiving()) |
-#endif |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Failed to start receive on RTP socket"); |
- _lastError = kStartReceiveError; |
- return -1; |
- } |
- } |
- if(_ptrRtcpSocket) |
- { |
- if(!_ptrRtcpSocket->StartReceiving()) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Failed to start receive on RTCP socket"); |
- _lastError = kStartReceiveError; |
- return -1; |
- } |
- } |
- if( _ptrRtpSocket == NULL && |
- _ptrRtcpSocket == NULL) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Failed to StartReceiving, no socket initialized"); |
- _lastError = kStartReceiveError; |
- return -1; |
- } |
- _receiving = true; |
- return 0; |
-} |
- |
-bool UdpTransportImpl::Receiving() const |
-{ |
- return _receiving; |
-} |
- |
-int32_t UdpTransportImpl::StopReceiving() |
-{ |
- |
- CriticalSectionScoped cs(_crit); |
- |
- _receiving = false; |
- |
- if (_ptrRtpSocket) |
- { |
- if (!_ptrRtpSocket->StopReceiving()) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Failed to stop receiving on RTP socket"); |
- _lastError = kStopReceiveError; |
- return -1; |
- } |
- } |
- if (_ptrRtcpSocket) |
- { |
- if (!_ptrRtcpSocket->StopReceiving()) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "Failed to stop receiving on RTCP socket"); |
- _lastError = kStopReceiveError; |
- return -1; |
- } |
- } |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::InitializeSendSockets( |
- const char* ipaddr, |
- const uint16_t rtpPort, |
- const uint16_t rtcpPort) |
-{ |
- { |
- CriticalSectionScoped cs(_crit); |
- _destPort = rtpPort; |
- if(rtcpPort == 0) |
- { |
- _destPortRTCP = _destPort+1; |
- } else |
- { |
- _destPortRTCP = rtcpPort; |
- } |
- |
- if(ipaddr == NULL) |
- { |
- if (!IsIpAddressValid(_destIP, IpV6Enabled())) |
- { |
- _destPort = 0; |
- _destPortRTCP = 0; |
- _lastError = kIpAddressInvalid; |
- return -1; |
- } |
- } else |
- { |
- if (IsIpAddressValid(ipaddr, IpV6Enabled())) |
- { |
- strncpy( |
- _destIP, |
- ipaddr, |
- IpV6Enabled() ? kIpAddressVersion6Length : |
- kIpAddressVersion4Length); |
- } else { |
- _destPort = 0; |
- _destPortRTCP = 0; |
- _lastError = kIpAddressInvalid; |
- return -1; |
- } |
- } |
- BuildRemoteRTPAddr(); |
- BuildRemoteRTCPAddr(); |
- } |
- |
- if (_ipV6Enabled) |
- { |
- if (_qos) |
- { |
- WEBRTC_TRACE( |
- kTraceWarning, |
- kTraceTransport, |
- _id, |
- "QOS is enabled but will be ignored since IPv6 is enabled"); |
- } |
- }else |
- { |
- // TODO (grunell): Multicast support is experimantal. |
- |
- // Put the first digit of the remote address in val. |
- int32_t val = ntohl(_remoteRTPAddr._sockaddr_in.sin_addr)>> 24; |
- |
- if((val > 223) && (val < 240)) |
- { |
- // Multicast address. |
- CriticalSectionScoped cs(_crit); |
- |
- UdpSocketWrapper* rtpSock = (_ptrSendRtpSocket ? |
- _ptrSendRtpSocket : _ptrRtpSocket); |
- if (!rtpSock || !rtpSock->ValidHandle()) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- UdpSocketWrapper* rtcpSock = (_ptrSendRtcpSocket ? |
- _ptrSendRtcpSocket : _ptrRtcpSocket); |
- if (!rtcpSock || !rtcpSock->ValidHandle()) |
- { |
- _lastError = kSocketInvalid; |
- return -1; |
- } |
- |
- // Set Time To Live to same region |
- int32_t iOptVal = 64; |
- if (!rtpSock->SetSockopt(IPPROTO_IP, IP_MULTICAST_TTL, |
- (int8_t*)&iOptVal, |
- sizeof (int32_t))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "setsockopt for multicast error on RTP socket"); |
- _ptrRtpSocket->CloseBlocking(); |
- _ptrRtpSocket = NULL; |
- _lastError = kMulticastAddressInvalid; |
- return -1; |
- } |
- if (!rtcpSock->SetSockopt(IPPROTO_IP, IP_MULTICAST_TTL, |
- (int8_t*)&iOptVal, |
- sizeof (int32_t))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "setsockopt for multicast error on RTCP socket"); |
- _ptrRtpSocket->CloseBlocking(); |
- _ptrRtpSocket = NULL; |
- _lastError = kMulticastAddressInvalid; |
- return -1; |
- } |
- } |
- } |
- return 0; |
-} |
- |
-void UdpTransportImpl::BuildSockaddrIn(uint16_t portnr, |
- const char* ip, |
- SocketAddress& remoteAddr) const |
-{ |
- if(_ipV6Enabled) |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- remoteAddr.sin_length = 0; |
- remoteAddr.sin_family = PF_INET6; |
-#else |
- remoteAddr._sockaddr_storage.sin_family = PF_INET6; |
-#endif |
- remoteAddr._sockaddr_in6.sin6_port = Htons(portnr); |
- InetPresentationToNumeric(AF_INET6, ip, |
- &remoteAddr._sockaddr_in6.sin6_addr); |
- remoteAddr._sockaddr_in6.sin6_flowinfo=0; |
- remoteAddr._sockaddr_in6.sin6_scope_id=0; |
- } else |
- { |
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
- remoteAddr.sin_length = 0; |
- remoteAddr.sin_family = PF_INET; |
-#else |
- remoteAddr._sockaddr_storage.sin_family = PF_INET; |
-#endif |
- remoteAddr._sockaddr_in.sin_port = Htons(portnr); |
- remoteAddr._sockaddr_in.sin_addr= InetAddrIPV4( |
- const_cast<char*>(ip)); |
- } |
-} |
- |
-int32_t UdpTransportImpl::SendRaw(const int8_t *data, |
- size_t length, |
- int32_t isRTCP, |
- uint16_t portnr, |
- const char* ip) |
-{ |
- CriticalSectionScoped cs(_crit); |
- if(isRTCP) |
- { |
- UdpSocketWrapper* rtcpSock = NULL; |
- if(_ptrSendRtcpSocket) |
- { |
- rtcpSock = _ptrSendRtcpSocket; |
- } else if(_ptrRtcpSocket) |
- { |
- rtcpSock = _ptrRtcpSocket; |
- } else |
- { |
- return -1; |
- } |
- if(portnr == 0 && ip == NULL) |
- { |
- return rtcpSock->SendTo(data,length,_remoteRTCPAddr); |
- |
- } else if(portnr != 0 && ip != NULL) |
- { |
- SocketAddress remoteAddr; |
- BuildSockaddrIn(portnr, ip, remoteAddr); |
- return rtcpSock->SendTo(data,length,remoteAddr); |
- } else if(ip != NULL) |
- { |
- SocketAddress remoteAddr; |
- BuildSockaddrIn(_destPortRTCP, ip, remoteAddr); |
- return rtcpSock->SendTo(data,length,remoteAddr); |
- } else |
- { |
- SocketAddress remoteAddr; |
- BuildSockaddrIn(portnr, _destIP, remoteAddr); |
- return rtcpSock->SendTo(data,length,remoteAddr); |
- } |
- } else { |
- UdpSocketWrapper* rtpSock = NULL; |
- if(_ptrSendRtpSocket) |
- { |
- rtpSock = _ptrSendRtpSocket; |
- |
- } else if(_ptrRtpSocket) |
- { |
- rtpSock = _ptrRtpSocket; |
- } else |
- { |
- return -1; |
- } |
- if(portnr == 0 && ip == NULL) |
- { |
- return rtpSock->SendTo(data,length,_remoteRTPAddr); |
- |
- } else if(portnr != 0 && ip != NULL) |
- { |
- SocketAddress remoteAddr; |
- BuildSockaddrIn(portnr, ip, remoteAddr); |
- return rtpSock->SendTo(data,length,remoteAddr); |
- } else if(ip != NULL) |
- { |
- SocketAddress remoteAddr; |
- BuildSockaddrIn(_destPort, ip, remoteAddr); |
- return rtpSock->SendTo(data,length,remoteAddr); |
- } else |
- { |
- SocketAddress remoteAddr; |
- BuildSockaddrIn(portnr, _destIP, remoteAddr); |
- return rtpSock->SendTo(data,length,remoteAddr); |
- } |
- } |
-} |
- |
-int32_t UdpTransportImpl::SendRTPPacketTo(const int8_t* data, |
- size_t length, |
- const SocketAddress& to) |
-{ |
- CriticalSectionScoped cs(_crit); |
- if(_ptrSendRtpSocket) |
- { |
- return _ptrSendRtpSocket->SendTo(data,length,to); |
- |
- } else if(_ptrRtpSocket) |
- { |
- return _ptrRtpSocket->SendTo(data,length,to); |
- } |
- return -1; |
-} |
- |
-int32_t UdpTransportImpl::SendRTCPPacketTo(const int8_t* data, |
- size_t length, |
- const SocketAddress& to) |
-{ |
- |
- CriticalSectionScoped cs(_crit); |
- |
- if(_ptrSendRtcpSocket) |
- { |
- return _ptrSendRtcpSocket->SendTo(data,length,to); |
- |
- } else if(_ptrRtcpSocket) |
- { |
- return _ptrRtcpSocket->SendTo(data,length,to); |
- } |
- return -1; |
-} |
- |
-int32_t UdpTransportImpl::SendRTPPacketTo(const int8_t* data, |
- size_t length, |
- const uint16_t rtpPort) |
-{ |
- CriticalSectionScoped cs(_crit); |
- // Use the current SocketAdress but update it with rtpPort. |
- SocketAddress to; |
- memcpy(&to, &_remoteRTPAddr, sizeof(SocketAddress)); |
- |
- if(_ipV6Enabled) |
- { |
- to._sockaddr_in6.sin6_port = Htons(rtpPort); |
- } else |
- { |
- to._sockaddr_in.sin_port = Htons(rtpPort); |
- } |
- |
- if(_ptrSendRtpSocket) |
- { |
- return _ptrSendRtpSocket->SendTo(data,length,to); |
- |
- } else if(_ptrRtpSocket) |
- { |
- return _ptrRtpSocket->SendTo(data,length,to); |
- } |
- return -1; |
-} |
- |
-int32_t UdpTransportImpl::SendRTCPPacketTo(const int8_t* data, |
- size_t length, |
- const uint16_t rtcpPort) |
-{ |
- CriticalSectionScoped cs(_crit); |
- |
- // Use the current SocketAdress but update it with rtcpPort. |
- SocketAddress to; |
- memcpy(&to, &_remoteRTCPAddr, sizeof(SocketAddress)); |
- |
- if(_ipV6Enabled) |
- { |
- to._sockaddr_in6.sin6_port = Htons(rtcpPort); |
- } else |
- { |
- to._sockaddr_in.sin_port = Htons(rtcpPort); |
- } |
- |
- if(_ptrSendRtcpSocket) |
- { |
- return _ptrSendRtcpSocket->SendTo(data,length,to); |
- |
- } else if(_ptrRtcpSocket) |
- { |
- return _ptrRtcpSocket->SendTo(data,length,to); |
- } |
- return -1; |
-} |
- |
-bool UdpTransportImpl::SendRtp(const uint8_t* data, |
- size_t length, |
- const PacketOptions& packet_options) { |
- WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, "%s", __FUNCTION__); |
- |
- CriticalSectionScoped cs(_crit); |
- |
- if(_destIP[0] == 0) |
- { |
- return false; |
- } |
- if(_destPort == 0) |
- { |
- return false; |
- } |
- |
- // Create socket if it hasn't been set up already. |
- // TODO (hellner): why not fail here instead. Sockets not being initialized |
- // indicates that there is a problem somewhere. |
- if( _ptrSendRtpSocket == NULL && |
- _ptrRtpSocket == NULL) |
- { |
- WEBRTC_TRACE( |
- kTraceStateInfo, |
- kTraceTransport, |
- _id, |
- "Creating RTP socket since no receive or source socket is\ |
- configured"); |
- |
- _ptrRtpSocket = _socket_creator->CreateSocket(_id, _mgr, this, |
- IncomingRTPCallback, |
- IpV6Enabled(), false); |
- |
- // Don't bind to a specific IP address. |
- if(! IpV6Enabled()) |
- { |
- strncpy(_localIP, "0.0.0.0",16); |
- } else |
- { |
- strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000", |
- kIpAddressVersion6Length); |
- } |
- _localPort = _destPort; |
- |
- ErrorCode retVal = BindLocalRTPSocket(); |
- if(retVal != kNoSocketError) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "SendPacket() failed to bind RTP socket"); |
- _lastError = retVal; |
- CloseReceiveSockets(); |
- return false; |
- } |
- } |
- |
- if(_ptrSendRtpSocket) |
- { |
- return _ptrSendRtpSocket->SendTo((const int8_t*)data, length, |
- _remoteRTPAddr) >= 0; |
- |
- } else if(_ptrRtpSocket) |
- { |
- return _ptrRtpSocket->SendTo((const int8_t*)data, length, |
- _remoteRTPAddr) >= 0; |
- } |
- return false; |
-} |
- |
-bool UdpTransportImpl::SendRtcp(const uint8_t* data, size_t length) { |
- CriticalSectionScoped cs(_crit); |
- if(_destIP[0] == 0) |
- { |
- return false; |
- } |
- if(_destPortRTCP == 0) |
- { |
- return false; |
- } |
- |
- // Create socket if it hasn't been set up already. |
- // TODO (hellner): why not fail here instead. Sockets not being initialized |
- // indicates that there is a problem somewhere. |
- if( _ptrSendRtcpSocket == NULL && |
- _ptrRtcpSocket == NULL) |
- { |
- WEBRTC_TRACE( |
- kTraceStateInfo, |
- kTraceTransport, |
- _id, |
- "Creating RTCP socket since no receive or source socket is\ |
- configured"); |
- |
- _ptrRtcpSocket = _socket_creator->CreateSocket(_id, _mgr, this, |
- IncomingRTCPCallback, |
- IpV6Enabled(), false); |
- |
- // Don't bind to a specific IP address. |
- if(! IpV6Enabled()) |
- { |
- strncpy(_localIP, "0.0.0.0",16); |
- } else |
- { |
- strncpy(_localIP, "0000:0000:0000:0000:0000:0000:0000:0000", |
- kIpAddressVersion6Length); |
- } |
- _localPortRTCP = _destPortRTCP; |
- |
- ErrorCode retVal = BindLocalRTCPSocket(); |
- if(retVal != kNoSocketError) |
- { |
- _lastError = retVal; |
- WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
- "SendRtcp() failed to bind RTCP socket"); |
- CloseReceiveSockets(); |
- return false; |
- } |
- } |
- |
- if(_ptrSendRtcpSocket) |
- { |
- return _ptrSendRtcpSocket->SendTo((const int8_t*)data, length, |
- _remoteRTCPAddr) >= 0; |
- } else if(_ptrRtcpSocket) |
- { |
- return _ptrRtcpSocket->SendTo((const int8_t*)data, length, |
- _remoteRTCPAddr) >= 0; |
- } |
- return false; |
-} |
- |
-int32_t UdpTransportImpl::SetSendIP(const char* ipaddr) |
-{ |
- if(!IsIpAddressValid(ipaddr,IpV6Enabled())) |
- { |
- return kIpAddressInvalid; |
- } |
- CriticalSectionScoped cs(_crit); |
- strncpy(_destIP, ipaddr,kIpAddressVersion6Length); |
- BuildRemoteRTPAddr(); |
- BuildRemoteRTCPAddr(); |
- return 0; |
-} |
- |
-int32_t UdpTransportImpl::SetSendPorts(uint16_t rtpPort, uint16_t rtcpPort) |
-{ |
- CriticalSectionScoped cs(_crit); |
- _destPort = rtpPort; |
- if(rtcpPort == 0) |
- { |
- _destPortRTCP = _destPort+1; |
- } else |
- { |
- _destPortRTCP = rtcpPort; |
- } |
- BuildRemoteRTPAddr(); |
- BuildRemoteRTCPAddr(); |
- return 0; |
-} |
- |
-void UdpTransportImpl::IncomingRTPCallback(CallbackObj obj, |
- const int8_t* rtpPacket, |
- size_t rtpPacketLength, |
- const SocketAddress* from) |
-{ |
- if (rtpPacket && rtpPacketLength > 0) |
- { |
- UdpTransportImpl* socketTransport = (UdpTransportImpl*) obj; |
- socketTransport->IncomingRTPFunction(rtpPacket, rtpPacketLength, from); |
- } |
-} |
- |
-void UdpTransportImpl::IncomingRTCPCallback(CallbackObj obj, |
- const int8_t* rtcpPacket, |
- size_t rtcpPacketLength, |
- const SocketAddress* from) |
-{ |
- if (rtcpPacket && rtcpPacketLength > 0) |
- { |
- UdpTransportImpl* socketTransport = (UdpTransportImpl*) obj; |
- socketTransport->IncomingRTCPFunction(rtcpPacket, rtcpPacketLength, |
- from); |
- } |
-} |
- |
-void UdpTransportImpl::IncomingRTPFunction(const int8_t* rtpPacket, |
- size_t rtpPacketLength, |
- const SocketAddress* fromSocket) |
-{ |
- char ipAddress[kIpAddressVersion6Length]; |
- uint32_t ipAddressLength = kIpAddressVersion6Length; |
- uint16_t portNr = 0; |
- |
- { |
- CriticalSectionScoped cs(_critFilter); |
- if (FilterIPAddress(fromSocket) == false) |
- { |
- // Packet should be filtered out. Drop it. |
- WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, |
- "Incoming RTP packet blocked by IP filter"); |
- return; |
- } |
- |
- if (IPAddressCached(*fromSocket, ipAddress, ipAddressLength, portNr) < |
- 0) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpTransportImpl::IncomingRTPFunction - Cannot get sender\ |
- information"); |
- }else |
- { |
- // Make sure ipAddress is null terminated. |
- ipAddress[kIpAddressVersion6Length - 1] = 0; |
- strncpy(_fromIP, ipAddress, kIpAddressVersion6Length - 1); |
- } |
- |
- // Filter based on port. |
- if (_rtpFilterPort != 0 && |
- _rtpFilterPort != portNr) |
- { |
- // Drop packet. |
- memset(_fromIP, 0, sizeof(_fromIP)); |
- WEBRTC_TRACE( |
- kTraceStream, |
- kTraceTransport, |
- _id, |
- "Incoming RTP packet blocked by filter incoming from port:%d\ |
- allowed port:%d", |
- portNr, |
- _rtpFilterPort); |
- return; |
- } |
- _fromPort = portNr; |
- } |
- |
- CriticalSectionScoped cs(_critPacketCallback); |
- if (_packetCallback) |
- { |
- WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, |
- "Incoming RTP packet from ip:%s port:%d", ipAddress, portNr); |
- _packetCallback->IncomingRTPPacket(rtpPacket, rtpPacketLength, |
- ipAddress, portNr); |
- } |
-} |
- |
-void UdpTransportImpl::IncomingRTCPFunction(const int8_t* rtcpPacket, |
- size_t rtcpPacketLength, |
- const SocketAddress* fromSocket) |
-{ |
- char ipAddress[kIpAddressVersion6Length]; |
- uint32_t ipAddressLength = kIpAddressVersion6Length; |
- uint16_t portNr = 0; |
- |
- { |
- CriticalSectionScoped cs(_critFilter); |
- if (FilterIPAddress(fromSocket) == false) |
- { |
- // Packet should be filtered out. Drop it. |
- WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, |
- "Incoming RTCP packet blocked by IP filter"); |
- return; |
- } |
- if (IPAddress(*fromSocket, ipAddress, ipAddressLength, portNr) < 0) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpTransportImpl::IncomingRTCPFunction - Cannot get sender\ |
- information"); |
- }else { |
- // Make sure ipAddress is null terminated. |
- ipAddress[kIpAddressVersion6Length - 1] = 0; |
- strncpy(_fromIP, ipAddress, kIpAddressVersion6Length - 1); |
- } |
- |
- // Filter based on port. |
- if (_rtcpFilterPort != 0 && |
- _rtcpFilterPort != portNr) |
- { |
- // Drop packet. |
- WEBRTC_TRACE( |
- kTraceStream, |
- kTraceTransport, |
- _id, |
- "Incoming RTCP packet blocked by filter incoming from port:%d\ |
- allowed port:%d", |
- portNr, |
- _rtpFilterPort); |
- return; |
- } |
- _fromPortRTCP = portNr; |
- } |
- |
- CriticalSectionScoped cs(_critPacketCallback); |
- if (_packetCallback) |
- { |
- WEBRTC_TRACE(kTraceStream, kTraceTransport, _id, |
- "Incoming RTCP packet from ip:%s port:%d", ipAddress, |
- portNr); |
- _packetCallback->IncomingRTCPPacket(rtcpPacket, rtcpPacketLength, |
- ipAddress, portNr); |
- } |
-} |
- |
-bool UdpTransportImpl::FilterIPAddress(const SocketAddress* fromAddress) |
-{ |
- if(fromAddress->_sockaddr_storage.sin_family == AF_INET) |
- { |
- if (_filterIPAddress._sockaddr_storage.sin_family == AF_INET) |
- { |
- // IP is stored in sin_addr. |
- if (_filterIPAddress._sockaddr_in.sin_addr != 0 && |
- (_filterIPAddress._sockaddr_in.sin_addr != |
- fromAddress->_sockaddr_in.sin_addr)) |
- { |
- return false; |
- } |
- } |
- } |
- else if(fromAddress->_sockaddr_storage.sin_family == AF_INET6) |
- { |
- if (_filterIPAddress._sockaddr_storage.sin_family == AF_INET6) |
- { |
- // IP is stored in sin_6addr. |
- for (int32_t i = 0; i < 4; i++) |
- { |
- if (_filterIPAddress._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i] != 0 && |
- _filterIPAddress._sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i] != fromAddress->_sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u32[i]) |
- { |
- return false; |
- } |
- } |
- } |
- } |
- else |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- _id, |
- "UdpTransportImpl::FilterIPAddress() unknown address family"); |
- return false; |
- } |
- return true; |
-} |
- |
-void UdpTransportImpl::CloseReceiveSockets() |
-{ |
- if(_ptrRtpSocket) |
- { |
- _ptrRtpSocket->CloseBlocking(); |
- _ptrRtpSocket = NULL; |
- } |
- if(_ptrRtcpSocket) |
- { |
- _ptrRtcpSocket->CloseBlocking(); |
- _ptrRtcpSocket = NULL; |
- } |
- _receiving = false; |
-} |
- |
-void UdpTransportImpl::CloseSendSockets() |
-{ |
- if(_ptrSendRtpSocket) |
- { |
- _ptrSendRtpSocket->CloseBlocking(); |
- _ptrSendRtpSocket = 0; |
- } |
- if(_ptrSendRtcpSocket) |
- { |
- _ptrSendRtcpSocket->CloseBlocking(); |
- _ptrSendRtcpSocket = 0; |
- } |
-} |
- |
-uint16_t UdpTransport::Htons(const uint16_t port) |
-{ |
- return htons(port); |
-} |
- |
-uint32_t UdpTransport::Htonl(const uint32_t a) |
-{ |
- return htonl(a); |
-} |
- |
-uint32_t UdpTransport::InetAddrIPV4(const char* ip) |
-{ |
- return ::inet_addr(ip); |
-} |
- |
-int32_t UdpTransport::InetPresentationToNumeric(int32_t af, |
- const char* src, |
- void* dst) |
-{ |
-#if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
- const int32_t result = inet_pton(af, src, dst); |
- return result > 0 ? 0 : -1; |
- |
-#elif defined(_WIN32) |
- SocketAddress temp; |
- int length=sizeof(SocketAddress); |
- |
- if(af == AF_INET) |
- { |
- int32_t result = WSAStringToAddressA( |
- (const LPSTR)src, |
- af, |
- 0, |
- reinterpret_cast<struct sockaddr*>(&temp), |
- &length); |
- if(result != 0) |
- { |
- return -1; |
- } |
- memcpy(dst,&(temp._sockaddr_in.sin_addr), |
- sizeof(temp._sockaddr_in.sin_addr)); |
- return 0; |
- } |
- else if(af == AF_INET6) |
- { |
- int32_t result = WSAStringToAddressA( |
- (const LPSTR)src, |
- af, |
- 0, |
- reinterpret_cast<struct sockaddr*>(&temp), |
- &length); |
- if(result !=0) |
- { |
- return -1; |
- } |
- memcpy(dst,&(temp._sockaddr_in6.sin6_addr), |
- sizeof(temp._sockaddr_in6.sin6_addr)); |
- return 0; |
- |
- }else |
- { |
- return -1; |
- } |
-#else |
- return -1; |
-#endif |
-} |
- |
-int32_t UdpTransport::LocalHostAddressIPV6(char n_localIP[16]) |
-{ |
- |
-#if defined(_WIN32) |
- struct addrinfo *result = NULL; |
- struct addrinfo *ptr = NULL; |
- struct addrinfo hints; |
- |
- ZeroMemory(&hints, sizeof(hints)); |
- hints.ai_family = AF_INET6; |
- |
- char szHostName[256] = ""; |
- if(::gethostname(szHostName, sizeof(szHostName) - 1)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, "gethostname failed"); |
- return -1; |
- } |
- |
- DWORD dwRetval = getaddrinfo(szHostName, NULL, &hints, &result); |
- if ( dwRetval != 0 ) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, |
- "getaddrinfo failed, error:%d", dwRetval); |
- return -1; |
- } |
- for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) |
- { |
- switch (ptr->ai_family) |
- { |
- case AF_INET6: |
- { |
- for(int i = 0; i< 16; i++) |
- { |
- n_localIP[i] = (*(SocketAddress*)ptr->ai_addr). |
- _sockaddr_in6.sin6_addr.Version6AddressUnion._s6_u8[i]; |
- } |
- bool islocalIP = true; |
- |
- for(int n = 0; n< 15; n++) |
- { |
- if(n_localIP[n] != 0) |
- { |
- islocalIP = false; |
- break; |
- } |
- } |
- |
- if(islocalIP && n_localIP[15] != 1) |
- { |
- islocalIP = false; |
- } |
- |
- if(islocalIP && ptr->ai_next) |
- { |
- continue; |
- } |
- if(n_localIP[0] == 0xfe && |
- n_localIP[1] == 0x80 && ptr->ai_next) |
- { |
- continue; |
- } |
- freeaddrinfo(result); |
- } |
- return 0; |
- default: |
- break; |
- }; |
- } |
- freeaddrinfo(result); |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, |
- "getaddrinfo failed to find address"); |
- return -1; |
- |
-#elif defined(WEBRTC_MAC) |
- struct ifaddrs* ptrIfAddrs = NULL; |
- struct ifaddrs* ptrIfAddrsStart = NULL; |
- |
- getifaddrs(&ptrIfAddrsStart); |
- ptrIfAddrs = ptrIfAddrsStart; |
- while(ptrIfAddrs) |
- { |
- if(ptrIfAddrs->ifa_addr->sa_family == AF_INET6) |
- { |
- const struct sockaddr_in6* sock_in6 = |
- reinterpret_cast<struct sockaddr_in6*>(ptrIfAddrs->ifa_addr); |
- const struct in6_addr* sin6_addr = &sock_in6->sin6_addr; |
- |
- if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || |
- IN6_IS_ADDR_LINKLOCAL(sin6_addr)) { |
- ptrIfAddrs = ptrIfAddrs->ifa_next; |
- continue; |
- } |
- memcpy(n_localIP, sin6_addr->s6_addr, sizeof(sin6_addr->s6_addr)); |
- freeifaddrs(ptrIfAddrsStart); |
- return 0; |
- } |
- ptrIfAddrs = ptrIfAddrs->ifa_next; |
- } |
- freeifaddrs(ptrIfAddrsStart); |
- return -1; |
-#elif defined(WEBRTC_ANDROID) |
- return -1; |
-#else // WEBRTC_LINUX |
- struct |
- { |
- struct nlmsghdr n; |
- struct ifaddrmsg r; |
- } req; |
- |
- struct rtattr* rta = NULL; |
- int status; |
- char buf[16384]; // = 16 * 1024 (16 kB) |
- struct nlmsghdr* nlmp; |
- struct ifaddrmsg* rtmp; |
- struct rtattr* rtatp; |
- int rtattrlen; |
- struct in6_addr* in6p; |
- |
- int fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); |
- if (fd == -1) |
- { |
- return -1; |
- } |
- |
- // RTM_GETADDR is used to fetch the ip address from the kernel interface |
- // table. Populate the msg structure (req) the size of the message buffer |
- // is specified to netlinkmessage header, and flags values are set as |
- // NLM_F_ROOT | NLM_F_REQUEST. |
- // The request flag must be set for all messages requesting the data from |
- // kernel. The root flag is used to notify the kernel to return the full |
- // tabel. Another flag (not used) is NLM_F_MATCH. This is used to get only |
- // specified entries in the table. At the time of writing this program this |
- // flag is not implemented in kernel |
- |
- memset(&req, 0, sizeof(req)); |
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); |
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; |
- req.n.nlmsg_type = RTM_GETADDR; |
- req.r.ifa_family = AF_INET6; |
- |
- // Fill up all the attributes for the rtnetlink header. |
- // The lenght is very important. 16 signifies the ipv6 address. |
- rta = (struct rtattr*)(((char*)&req) + NLMSG_ALIGN(req.n.nlmsg_len)); |
- rta->rta_len = RTA_LENGTH(16); |
- |
- status = send(fd, &req, req.n.nlmsg_len, 0); |
- if (status < 0) |
- { |
- close(fd); |
- return -1; |
- } |
- status = recv(fd, buf, sizeof(buf), 0); |
- if (status < 0) |
- { |
- close(fd); |
- return -1; |
- } |
- if(status == 0) |
- { |
- close(fd); |
- return -1; |
- } |
- close(fd); |
- |
- // The message is stored in buff. Parse the message to get the requested |
- // data. |
- { |
- nlmp = (struct nlmsghdr*)buf; |
- int len = nlmp->nlmsg_len; |
- int req_len = len - sizeof(*nlmp); |
- |
- if (req_len < 0 || len > status) |
- { |
- return -1; |
- } |
- if (!NLMSG_OK_NO_WARNING(nlmp, status)) |
- { |
- return -1; |
- } |
- rtmp = (struct ifaddrmsg*)NLMSG_DATA(nlmp); |
- rtatp = (struct rtattr*)IFA_RTA(rtmp); |
- |
- rtattrlen = IFA_PAYLOAD(nlmp); |
- |
- for (; RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen)) |
- { |
- |
- // Here we hit the fist chunk of the message. Time to validate the |
- // type. For more info on the different types see |
- // "man(7) rtnetlink" The table below is taken from man pages. |
- // Attributes |
- // rta_type value type description |
- // ------------------------------------------------------------- |
- // IFA_UNSPEC - unspecified. |
- // IFA_ADDRESS raw protocol address interface address |
- // IFA_LOCAL raw protocol address local address |
- // IFA_LABEL asciiz string name of the interface |
- // IFA_BROADCAST raw protocol address broadcast address. |
- // IFA_ANYCAST raw protocol address anycast address |
- // IFA_CACHEINFO struct ifa_cacheinfo Address information. |
- |
- if(rtatp->rta_type == IFA_ADDRESS) |
- { |
- bool islocalIP = true; |
- in6p = (struct in6_addr*)RTA_DATA(rtatp); |
- for(int n = 0; n< 15; n++) |
- { |
- if(in6p->s6_addr[n] != 0) |
- { |
- islocalIP = false; |
- break; |
- } |
- } |
- if(islocalIP && in6p->s6_addr[15] != 1) |
- { |
- islocalIP = false; |
- } |
- if(!islocalIP) |
- { |
- for(int i = 0; i< 16; i++) |
- { |
- n_localIP[i] = in6p->s6_addr[i]; |
- } |
- if(n_localIP[0] == static_cast<char> (0xfe) |
- && n_localIP[1] == static_cast<char>(0x80) ) |
- { |
- // Auto configured IP. |
- continue; |
- } |
- break; |
- } |
- } |
- } |
- } |
- return 0; |
-#endif |
-} |
- |
-int32_t UdpTransport::LocalHostAddress(uint32_t& localIP) |
-{ |
- #if defined(_WIN32) |
- hostent* localHost; |
- localHost = gethostbyname( "" ); |
- if(localHost) |
- { |
- if(localHost->h_addrtype != AF_INET) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- -1, |
- "LocalHostAddress can only get local IP for IP Version 4"); |
- return -1; |
- } |
- localIP= Htonl( |
- (*(struct in_addr *)localHost->h_addr_list[0]).S_un.S_addr); |
- return 0; |
- } |
- else |
- { |
- int32_t error = WSAGetLastError(); |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, |
- "gethostbyname failed, error:%d", error); |
- return -1; |
- } |
-#elif (defined(WEBRTC_MAC)) |
- char localname[255]; |
- if (gethostname(localname, 255) != -1) |
- { |
- hostent* localHost; |
- localHost = gethostbyname(localname); |
- if(localHost) |
- { |
- if(localHost->h_addrtype != AF_INET) |
- { |
- WEBRTC_TRACE( |
- kTraceError, |
- kTraceTransport, |
- -1, |
- "LocalHostAddress can only get local IP for IP Version 4"); |
- return -1; |
- } |
- localIP = Htonl((*(struct in_addr*)*localHost->h_addr_list).s_addr); |
- return 0; |
- } |
- } |
- WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, "gethostname failed"); |
- return -1; |
-#else // WEBRTC_LINUX |
- int sockfd, size = 1; |
- struct ifreq* ifr; |
- struct ifconf ifc; |
- |
- if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) |
- { |
- return -1; |
- } |
- ifc.ifc_len = IFRSIZE; |
- ifc.ifc_req = NULL; |
- do |
- { |
- ++size; |
- // Buffer size needed is unknown. Try increasing it until no overflow |
- // occurs. |
- if (NULL == (ifc.ifc_req = (ifreq*)realloc(ifc.ifc_req, IFRSIZE))) { |
- fprintf(stderr, "Out of memory.\n"); |
- exit(EXIT_FAILURE); |
- } |
- ifc.ifc_len = IFRSIZE; |
- if (ioctl(sockfd, SIOCGIFCONF, &ifc)) |
- { |
- free(ifc.ifc_req); |
- close(sockfd); |
- return -1; |
- } |
- } while (IFRSIZE <= ifc.ifc_len); |
- |
- ifr = ifc.ifc_req; |
- for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr) |
- { |
- if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data) |
- { |
- continue; // duplicate, skip it |
- } |
- if (ioctl(sockfd, SIOCGIFFLAGS, ifr)) |
- { |
- continue; // failed to get flags, skip it |
- } |
- if(strncmp(ifr->ifr_name, "lo",3) == 0) |
- { |
- continue; |
- }else |
- { |
- struct sockaddr* saddr = &(ifr->ifr_addr); |
- SocketAddress* socket_addess = reinterpret_cast<SocketAddress*>( |
- saddr); |
- localIP = Htonl(socket_addess->_sockaddr_in.sin_addr); |
- close(sockfd); |
- free(ifc.ifc_req); |
- return 0; |
- } |
- } |
- free(ifc.ifc_req); |
- close(sockfd); |
- return -1; |
-#endif |
-} |
- |
-int32_t UdpTransport::IPAddress(const SocketAddress& address, |
- char* ip, |
- uint32_t& ipSize, |
- uint16_t& sourcePort) |
-{ |
- #if defined(_WIN32) |
- DWORD dwIPSize = ipSize; |
- int32_t returnvalue = WSAAddressToStringA((LPSOCKADDR)(&address), |
- sizeof(SocketAddress), |
- NULL, |
- ip, |
- &dwIPSize); |
- if(returnvalue == -1) |
- { |
- return -1; |
- } |
- |
- uint16_t source_port = 0; |
- if(address._sockaddr_storage.sin_family == AF_INET) |
- { |
- // Parse IP assuming format "a.b.c.d:port". |
- char* ipEnd = strchr(ip,':'); |
- if(ipEnd != NULL) |
- { |
- *ipEnd = '\0'; |
- } |
- ipSize = (int32_t)strlen(ip); |
- if(ipSize == 0) |
- { |
- return -1; |
- } |
- source_port = address._sockaddr_in.sin_port; |
- } |
- else |
- { |
- // Parse IP assuming format "[address]:port". |
- char* ipEnd = strchr(ip,']'); |
- if(ipEnd != NULL) |
- { |
- // Calculate length |
- int32_t adrSize = int32_t(ipEnd - ip) - 1; |
- memmove(ip, &ip[1], adrSize); // Remove '[' |
- *(ipEnd - 1) = '\0'; |
- } |
- ipSize = (int32_t)strlen(ip); |
- if(ipSize == 0) |
- { |
- return -1; |
- } |
- |
- source_port = address._sockaddr_in6.sin6_port; |
- } |
- // Convert port number to network byte order. |
- sourcePort = htons(source_port); |
- return 0; |
- |
- #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) |
- int32_t ipFamily = address._sockaddr_storage.sin_family; |
- const void* ptrNumericIP = NULL; |
- |
- if(ipFamily == AF_INET) |
- { |
- ptrNumericIP = &(address._sockaddr_in.sin_addr); |
- } |
- else if(ipFamily == AF_INET6) |
- { |
- ptrNumericIP = &(address._sockaddr_in6.sin6_addr); |
- } |
- else |
- { |
- return -1; |
- } |
- if(inet_ntop(ipFamily, ptrNumericIP, ip, ipSize) == NULL) |
- { |
- return -1; |
- } |
- uint16_t source_port; |
- if(ipFamily == AF_INET) |
- { |
- source_port = address._sockaddr_in.sin_port; |
- } else |
- { |
- source_port = address._sockaddr_in6.sin6_port; |
- } |
- // Convert port number to network byte order. |
- sourcePort = htons(source_port); |
- return 0; |
- #else |
- return -1; |
- #endif |
-} |
- |
-bool UdpTransport::IsIpAddressValid(const char* ipadr, const bool ipV6) |
-{ |
- if(ipV6) |
- { |
- int32_t len = (int32_t)strlen(ipadr); |
- if( len>39 || len == 0) |
- { |
- return false; |
- } |
- |
- int32_t i; |
- int32_t colonPos[7] = {0,0,0,0,0,0,0}; |
- int32_t lastColonPos = -2; |
- int32_t nColons = 0; |
- int32_t nDubbleColons = 0; |
- int32_t nDots = 0; |
- int32_t error = 0; |
- char c; |
- for(i = 0; i < len ; i++) |
- { |
- c=ipadr[i]; |
- if(isxdigit(c)) |
- ; |
- else if(c == ':') |
- { |
- if(nColons < 7) |
- colonPos[nColons] = i; |
- if((i-lastColonPos)==1) |
- nDubbleColons++; |
- lastColonPos=i; |
- if(nDots != 0) |
- { |
- error = 1; |
- } |
- nColons++; |
- } |
- else if(c == '.') |
- { |
- nDots++; |
- } |
- else |
- { |
- error = 1; |
- } |
- |
- } |
- if(error) |
- { |
- return false; |
- } |
- if(nDubbleColons > 1) |
- { |
- return false; |
- } |
- if(nColons > 7 || nColons < 2) |
- { |
- return false; |
- } |
- if(!(nDots == 3 || nDots == 0)) |
- { |
- return false; |
- } |
- lastColonPos = -1; |
- int32_t charsBeforeColon = 0; |
- for(i = 0; i < nColons; i++) |
- { |
- charsBeforeColon=colonPos[i]-lastColonPos-1; |
- if(charsBeforeColon > 4) |
- { |
- return false; |
- } |
- lastColonPos=colonPos[i]; |
- } |
- int32_t lengthAfterLastColon = len - lastColonPos - 1; |
- if(nDots == 0) |
- { |
- if(lengthAfterLastColon > 4) |
- return false; |
- } |
- if(nDots == 3 && lengthAfterLastColon > 0) |
- { |
- return IsIpAddressValid((ipadr+lastColonPos+1),false); |
- } |
- |
- } |
- else |
- { |
- int32_t len = (int32_t)strlen(ipadr); |
- if((len>15)||(len==0)) |
- { |
- return false; |
- } |
- |
- // IPv4 should be [0-255].[0-255].[0-255].[0-255] |
- int32_t i; |
- int32_t nDots = 0; |
- int32_t iDotPos[4] = {0,0,0,0}; |
- |
- for (i = 0; (i < len) && (nDots < 4); i++) |
- { |
- if (ipadr[i] == (char)'.') |
- { |
- // Store index of dots and count number of dots. |
- iDotPos[nDots++] = i; |
- } |
- else if (isdigit(ipadr[i]) == 0) |
- { |
- return false; |
- } |
- } |
- |
- bool allUnder256 = false; |
- // TODO (hellner): while loop seems to be abused here to get |
- // label like functionality. Fix later to avoid introducing bugs now. |
- |
- // Check that all numbers are smaller than 256. |
- do |
- { |
- if (nDots != 3 ) |
- { |
- break; |
- } |
- |
- if (iDotPos[0] <= 3) |
- { |
- char nr[4]; |
- memset(nr,0,4); |
- strncpy(nr,&ipadr[0],iDotPos[0]); |
- int32_t num = atoi(nr); |
- if (num > 255 || num < 0) |
- { |
- break; |
- } |
- } else { |
- break; |
- } |
- |
- if (iDotPos[1] - iDotPos[0] <= 4) |
- { |
- char nr[4]; |
- memset(nr,0,4); |
- strncpy(nr,&ipadr[iDotPos[0]+1], iDotPos[1] - iDotPos[0] - 1); |
- int32_t num = atoi(nr); |
- if (num > 255 || num < 0) |
- break; |
- } else { |
- break; |
- } |
- |
- if (iDotPos[2] - iDotPos[1] <= 4) |
- { |
- char nr[4]; |
- memset(nr,0,4); |
- strncpy(nr,&ipadr[iDotPos[1]+1], iDotPos[2] - iDotPos[1] - 1); |
- int32_t num = atoi(nr); |
- if (num > 255 || num < 0) |
- break; |
- } else { |
- break; |
- } |
- |
- if (len - iDotPos[2] <= 4) |
- { |
- char nr[4]; |
- memset(nr,0,4); |
- strncpy(nr,&ipadr[iDotPos[2]+1], len - iDotPos[2] -1); |
- int32_t num = atoi(nr); |
- if (num > 255 || num < 0) |
- break; |
- else |
- allUnder256 = true; |
- } else { |
- break; |
- } |
- } while(false); |
- |
- if (nDots != 3 || !allUnder256) |
- { |
- return false; |
- } |
- } |
- return true; |
-} |
- |
-} // namespace test |
-} // namespace webrtc |