diff options
author | pwestin@webrtc.org <pwestin@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-03-13 23:20:57 +0000 |
---|---|---|
committer | pwestin@webrtc.org <pwestin@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-03-13 23:20:57 +0000 |
commit | 912b7f727086279bfa950dce96953fe018f49580 (patch) | |
tree | 4afcdf076abaae606bf7f4c500b8ad76e90301e0 /voice_engine | |
parent | 40749c1740c81cf0e637f4d3434c5d24619b0580 (diff) | |
download | webrtc-912b7f727086279bfa950dce96953fe018f49580.tar.gz |
Revert r3667 and r3665
Review URL: https://webrtc-codereview.appspot.com/1199004
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@3668 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'voice_engine')
24 files changed, 4029 insertions, 356 deletions
diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc index 7691bf09..1eabee84 100644 --- a/voice_engine/channel.cc +++ b/voice_engine/channel.cc @@ -332,6 +332,163 @@ Channel::SendRTCPPacket(int channel, const void *data, int len) } void +Channel::IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket, + const WebRtc_Word32 rtpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) +{ + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::IncomingRTPPacket(rtpPacketLength=%d," + " fromIP=%s, fromPort=%u)", + rtpPacketLength, fromIP, fromPort); + + // Store playout timestamp for the received RTP packet + // to be used for upcoming delay estimations + WebRtc_UWord32 playoutTimestamp(0); + if (GetPlayoutTimeStamp(playoutTimestamp) == 0) + { + _playoutTimeStampRTP = playoutTimestamp; + } + + WebRtc_UWord8* rtpBufferPtr = (WebRtc_UWord8*)incomingRtpPacket; + WebRtc_Word32 rtpBufferLength = rtpPacketLength; + + // SRTP or External decryption + if (_decrypting) + { + CriticalSectionScoped cs(&_callbackCritSect); + + if (_encryptionPtr) + { + if (!_decryptionRTPBufferPtr) + { + // Allocate memory for decryption buffer one time only + _decryptionRTPBufferPtr = + new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes]; + } + + // Perform decryption (SRTP or external) + WebRtc_Word32 decryptedBufferLength = 0; + _encryptionPtr->decrypt(_channelId, + rtpBufferPtr, + _decryptionRTPBufferPtr, + rtpBufferLength, + (int*)&decryptedBufferLength); + if (decryptedBufferLength <= 0) + { + _engineStatisticsPtr->SetLastError( + VE_DECRYPTION_FAILED, kTraceError, + "Channel::IncomingRTPPacket() decryption failed"); + return; + } + + // Replace default data buffer with decrypted buffer + rtpBufferPtr = _decryptionRTPBufferPtr; + rtpBufferLength = decryptedBufferLength; + } + } + + // Dump the RTP packet to a file (if RTP dump is enabled). + if (_rtpDumpIn.DumpPacket(rtpBufferPtr, + (WebRtc_UWord16)rtpBufferLength) == -1) + { + WEBRTC_TRACE(kTraceWarning, kTraceVoice, + VoEId(_instanceId,_channelId), + "Channel::SendPacket() RTP dump to input file failed"); + } + + // Deliver RTP packet to RTP/RTCP module for parsing + // The packet will be pushed back to the channel thru the + // OnReceivedPayloadData callback so we don't push it to the ACM here + if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtpBufferPtr, + (WebRtc_UWord16)rtpBufferLength) == -1) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, + "Channel::IncomingRTPPacket() RTP packet is invalid"); + return; + } +} + +void +Channel::IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket, + const WebRtc_Word32 rtcpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort) +{ + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::IncomingRTCPPacket(rtcpPacketLength=%d, fromIP=%s," + " fromPort=%u)", + rtcpPacketLength, fromIP, fromPort); + + // Temporary buffer pointer and size for decryption + WebRtc_UWord8* rtcpBufferPtr = (WebRtc_UWord8*)incomingRtcpPacket; + WebRtc_Word32 rtcpBufferLength = rtcpPacketLength; + + // Store playout timestamp for the received RTCP packet + // which will be read by the GetRemoteRTCPData API + WebRtc_UWord32 playoutTimestamp(0); + if (GetPlayoutTimeStamp(playoutTimestamp) == 0) + { + _playoutTimeStampRTCP = playoutTimestamp; + } + + // SRTP or External decryption + if (_decrypting) + { + CriticalSectionScoped cs(&_callbackCritSect); + + if (_encryptionPtr) + { + if (!_decryptionRTCPBufferPtr) + { + // Allocate memory for decryption buffer one time only + _decryptionRTCPBufferPtr = + new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes]; + } + + // Perform decryption (SRTP or external). + WebRtc_Word32 decryptedBufferLength = 0; + _encryptionPtr->decrypt_rtcp(_channelId, + rtcpBufferPtr, + _decryptionRTCPBufferPtr, + rtcpBufferLength, + (int*)&decryptedBufferLength); + if (decryptedBufferLength <= 0) + { + _engineStatisticsPtr->SetLastError( + VE_DECRYPTION_FAILED, kTraceError, + "Channel::IncomingRTCPPacket() decryption failed"); + return; + } + + // Replace default data buffer with decrypted buffer + rtcpBufferPtr = _decryptionRTCPBufferPtr; + rtcpBufferLength = decryptedBufferLength; + } + } + + // Dump the RTCP packet to a file (if RTP dump is enabled). + if (_rtpDumpIn.DumpPacket(rtcpBufferPtr, + (WebRtc_UWord16)rtcpBufferLength) == -1) + { + WEBRTC_TRACE(kTraceWarning, kTraceVoice, + VoEId(_instanceId,_channelId), + "Channel::SendPacket() RTCP dump to input file failed"); + } + + // Deliver RTCP packet to RTP/RTCP module for parsing + if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtcpBufferPtr, + (WebRtc_UWord16)rtcpBufferLength) == -1) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, + "Channel::IncomingRTPPacket() RTCP packet is invalid"); + return; + } +} + +void Channel::OnPlayTelephoneEvent(const WebRtc_Word32 id, const WebRtc_UWord8 event, const WebRtc_UWord16 lengthMs, @@ -871,6 +1028,11 @@ Channel::Channel(const WebRtc_Word32 channelId, _channelId(channelId), _audioCodingModule(*AudioCodingModule::Create( VoEModuleId(instanceId, channelId))), +#ifndef WEBRTC_EXTERNAL_TRANSPORT + _numSocketThreads(KNumSocketThreads), + _socketTransportModule(*UdpTransport::Create( + VoEModuleId(instanceId, channelId), _numSocketThreads)), +#endif #ifdef WEBRTC_SRTP _srtpModule(*SrtpModule::CreateSrtpModule(VoEModuleId(instanceId, channelId))), @@ -999,6 +1161,18 @@ Channel::~Channel() DeRegisterExternalMediaProcessing(kRecordingPerChannel); } StopSend(); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + StopReceiving(); + // De-register packet callback to ensure we're not in a callback when + // deleting channel state, avoids race condition and deadlock. + if (_socketTransportModule.InitializeReceiveSockets(NULL, 0, NULL, NULL, 0) + != 0) + { + WEBRTC_TRACE(kTraceWarning, kTraceVoice, + VoEId(_instanceId, _channelId), + "~Channel() failed to de-register receive callback"); + } +#endif StopPlayout(); { @@ -1045,6 +1219,15 @@ Channel::~Channel() " (Audio coding module)"); } // De-register modules in process thread +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (_moduleProcessThreadPtr->DeRegisterModule(&_socketTransportModule) + == -1) + { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, + VoEId(_instanceId,_channelId), + "~Channel() failed to deregister socket module"); + } +#endif if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, @@ -1053,6 +1236,10 @@ Channel::~Channel() } // Destroy modules +#ifndef WEBRTC_EXTERNAL_TRANSPORT + UdpTransport::Destroy( + &_socketTransportModule); +#endif AudioCodingModule::Destroy(&_audioCodingModule); #ifdef WEBRTC_SRTP SrtpModule::DestroySrtpModule(&_srtpModule); @@ -1097,7 +1284,12 @@ Channel::Init() const bool processThreadFail = ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) || +#ifndef WEBRTC_EXTERNAL_TRANSPORT + (_moduleProcessThreadPtr->RegisterModule( + &_socketTransportModule) != 0)); +#else false); +#endif if (processThreadFail) { _engineStatisticsPtr->SetLastError( @@ -1231,6 +1423,17 @@ Channel::Init() } #endif } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + // Ensure that the WebRtcSocketTransport implementation is used as + // Transport on the sending side + { + // A lock is needed here since users can call + // RegisterExternalTransport() at the same time. + CriticalSectionScoped cs(&_callbackCritSect); + _transportPtr = &_socketTransportModule; + } +#endif + // Initialize the far end AP module // Using 8 kHz as initial Fs, the same as in transmission. Might be // changed at the first receiving audio. @@ -1459,6 +1662,25 @@ Channel::StartReceiving() // If external transport is used, we will only initialize/set the variables // after this section, since we are not using the WebRtc transport but // still need to keep track of e.g. if we are receiving. +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_externalTransport) + { + if (!_socketTransportModule.ReceiveSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKETS_NOT_INITED, kTraceError, + "StartReceive() must set local receiver first"); + return -1; + } + if (_socketTransportModule.StartReceiving(KNumberOfSocketBuffers) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "StartReceiving() failed to start receiving"); + return -1; + } + } +#endif _receiving = true; _numberOfDiscardedPackets = 0; return 0; @@ -1473,6 +1695,20 @@ Channel::StopReceiving() { return 0; } + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_externalTransport && + _socketTransportModule.ReceiveSocketsInitialized()) + { + if (_socketTransportModule.StopReceiving() != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "StopReceiving() failed to stop receiving."); + return -1; + } + } +#endif // Recover DTMF detection status. WebRtc_Word32 ret = _rtpRtcpModule->SetTelephoneEventForwardToDecoder(true); if (ret != 0) { @@ -1485,6 +1721,310 @@ Channel::StopReceiving() return 0; } +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::SetLocalReceiver(const WebRtc_UWord16 rtpPort, + const WebRtc_UWord16 rtcpPort, + const char ipAddr[64], + const char multicastIpAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetLocalReceiver()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetLocalReceiver() conflict with external transport"); + return -1; + } + + if (_sending) + { + _engineStatisticsPtr->SetLastError( + VE_ALREADY_SENDING, kTraceError, + "SetLocalReceiver() already sending"); + return -1; + } + if (_receiving) + { + _engineStatisticsPtr->SetLastError( + VE_ALREADY_LISTENING, kTraceError, + "SetLocalReceiver() already receiving"); + return -1; + } + + if (_socketTransportModule.InitializeReceiveSockets(this, + rtpPort, + ipAddr, + multicastIpAddr, + rtcpPort) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kIpAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetLocalReceiver() invalid IP address"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetLocalReceiver() invalid socket"); + break; + case UdpTransport::kPortInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_PORT_NMBR, kTraceError, + "SetLocalReceiver() invalid port"); + break; + case UdpTransport::kFailedToBindPort: + _engineStatisticsPtr->SetLastError( + VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED, kTraceError, + "SetLocalReceiver() binding failed"); + break; + default: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetLocalReceiver() undefined socket error"); + break; + } + return -1; + } + return 0; +} +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::GetLocalReceiver(int& port, int& RTCPport, char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetLocalReceiver()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetLocalReceiver() conflict with external transport"); + return -1; + } + + char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0}; + WebRtc_UWord16 rtpPort(0); + WebRtc_UWord16 rtcpPort(0); + char multicastIpAddr[UdpTransport::kIpAddressVersion6Length] = {0}; + + // Acquire socket information from the socket module + if (_socketTransportModule.ReceiveSocketInformation(ipAddrTmp, + rtpPort, + rtcpPort, + multicastIpAddr) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_CANNOT_GET_SOCKET_INFO, kTraceError, + "GetLocalReceiver() unable to retrieve socket information"); + return -1; + } + + // Deliver valid results to the user + port = static_cast<int> (rtpPort); + RTCPport = static_cast<int> (rtcpPort); + if (ipAddr != NULL) + { + strcpy(ipAddr, ipAddrTmp); + } + return 0; +} +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::SetSendDestination(const WebRtc_UWord16 rtpPort, + const char ipAddr[64], + const int sourcePort, + const WebRtc_UWord16 rtcpPort) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSendDestination()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSendDestination() conflict with external transport"); + return -1; + } + + // Initialize ports and IP address for the remote (destination) side. + // By default, the sockets used for receiving are used for transmission as + // well, hence the source ports for outgoing packets are the same as the + // receiving ports specified in SetLocalReceiver. + // If an extra send socket has been created, it will be utilized until a + // new source port is specified or until the channel has been deleted and + // recreated. If no socket exists, sockets will be created when the first + // RTP and RTCP packets shall be transmitted (see e.g. + // UdpTransportImpl::SendPacket()). + // + // NOTE: this function does not require that sockets exists; all it does is + // to build send structures to be used with the sockets when they exist. + // It is therefore possible to call this method before SetLocalReceiver. + // However, sockets must exist if a multi-cast address is given as input. + + // Build send structures and enable QoS (if enabled and supported) + if (_socketTransportModule.InitializeSendSockets( + ipAddr, rtpPort, rtcpPort) != UdpTransport::kNoSocketError) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kIpAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetSendDestination() invalid IP address 1"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() invalid socket 1"); + break; + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError( + VE_GQOS_ERROR, kTraceError, + "SetSendDestination() failed to set QoS"); + break; + case UdpTransport::kMulticastAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_MULTICAST_ADDRESS, kTraceError, + "SetSendDestination() invalid multicast address"); + break; + default: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() undefined socket error 1"); + break; + } + return -1; + } + + // Check if the user has specified a non-default source port different from + // the local receive port. + // If so, an extra local socket will be created unless the source port is + // not unique. + if (sourcePort != kVoEDefault) + { + WebRtc_UWord16 receiverRtpPort(0); + WebRtc_UWord16 rtcpNA(0); + if (_socketTransportModule.ReceiveSocketInformation(NULL, + receiverRtpPort, + rtcpNA, + NULL) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_CANNOT_GET_SOCKET_INFO, kTraceError, + "SetSendDestination() failed to retrieve socket information"); + return -1; + } + + WebRtc_UWord16 sourcePortUW16 = + static_cast<WebRtc_UWord16> (sourcePort); + + // An extra socket will only be created if the specified source port + // differs from the local receive port. + if (sourcePortUW16 != receiverRtpPort) + { + // Initialize extra local socket to get a different source port + // than the local + // receiver port. Always use default source for RTCP. + // Note that, this calls UdpTransport::CloseSendSockets(). + if (_socketTransportModule.InitializeSourcePorts( + sourcePortUW16, + sourcePortUW16+1) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kIpAddressInvalid: + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetSendDestination() invalid IP address 2"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() invalid socket 2"); + break; + default: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendDestination() undefined socket error 2"); + break; + } + return -1; + } + WEBRTC_TRACE(kTraceInfo, kTraceVoice, + VoEId(_instanceId,_channelId), + "SetSendDestination() extra local socket is created" + " to facilitate unique source port"); + } + else + { + WEBRTC_TRACE(kTraceInfo, kTraceVoice, + VoEId(_instanceId,_channelId), + "SetSendDestination() sourcePort equals the local" + " receive port => no extra socket is created"); + } + } + + return 0; +} +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::GetSendDestination(int& port, + char ipAddr[64], + int& sourcePort, + int& RTCPport) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSendDestination()"); + + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSendDestination() conflict with external transport"); + return -1; + } + + char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0}; + WebRtc_UWord16 rtpPort(0); + WebRtc_UWord16 rtcpPort(0); + WebRtc_UWord16 rtpSourcePort(0); + WebRtc_UWord16 rtcpSourcePort(0); + + // Acquire sending socket information from the socket module + _socketTransportModule.SendSocketInformation(ipAddrTmp, rtpPort, rtcpPort); + _socketTransportModule.SourcePorts(rtpSourcePort, rtcpSourcePort); + + // Deliver valid results to the user + port = static_cast<int> (rtpPort); + RTCPport = static_cast<int> (rtcpPort); + sourcePort = static_cast<int> (rtpSourcePort); + if (ipAddr != NULL) + { + strcpy(ipAddr, ipAddrTmp); + } + + return 0; +} +#endif + + WebRtc_Word32 Channel::SetNetEQPlayoutMode(NetEqModes mode) { @@ -2088,6 +2628,24 @@ WebRtc_Word32 Channel::RegisterExternalTransport(Transport& transport) CriticalSectionScoped cs(&_callbackCritSect); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + // Sanity checks for default (non external transport) to avoid conflict with + // WebRtc sockets. + if (_socketTransportModule.SendSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError(VE_SEND_SOCKETS_CONFLICT, + kTraceError, + "RegisterExternalTransport() send sockets already initialized"); + return -1; + } + if (_socketTransportModule.ReceiveSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError(VE_RECEIVE_SOCKETS_CONFLICT, + kTraceError, + "RegisterExternalTransport() receive sockets already initialized"); + return -1; + } +#endif if (_externalTransport) { _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, @@ -2117,82 +2675,397 @@ Channel::DeRegisterExternalTransport() return 0; } _externalTransport = false; +#ifdef WEBRTC_EXTERNAL_TRANSPORT _transportPtr = NULL; WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "DeRegisterExternalTransport() all transport is disabled"); +#else + _transportPtr = &_socketTransportModule; + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "DeRegisterExternalTransport() internal Transport is enabled"); +#endif return 0; } WebRtc_Word32 Channel::ReceivedRTPPacket(const WebRtc_Word8* data, WebRtc_Word32 length) { - WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::ReceivedRTPPacket()"); + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::ReceivedRTPPacket()"); + const char dummyIP[] = "127.0.0.1"; + IncomingRTPPacket(data, length, dummyIP, 0); + return 0; +} - // Store playout timestamp for the received RTP packet - // to be used for upcoming delay estimations - WebRtc_UWord32 playoutTimestamp(0); - if (GetPlayoutTimeStamp(playoutTimestamp) == 0) - { - _playoutTimeStampRTP = playoutTimestamp; - } - // Dump the RTP packet to a file (if RTP dump is enabled). - if (_rtpDumpIn.DumpPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, - VoEId(_instanceId,_channelId), - "Channel::SendPacket() RTP dump to input file failed"); - } +WebRtc_Word32 +Channel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length) +{ + WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::ReceivedRTCPPacket()"); + const char dummyIP[] = "127.0.0.1"; + IncomingRTCPPacket(data, length, dummyIP, 0); + return 0; +} - // Deliver RTP packet to RTP/RTCP module for parsing - // The packet will be pushed back to the channel thru the - // OnReceivedPayloadData callback so we don't push it to the ACM here - if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - _engineStatisticsPtr->SetLastError( - VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, - "Channel::IncomingRTPPacket() RTP packet is invalid"); - } - return 0; +#ifndef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 +Channel::GetSourceInfo(int& rtpPort, int& rtcpPort, char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSourceInfo()"); + + WebRtc_UWord16 rtpPortModule; + WebRtc_UWord16 rtcpPortModule; + char ipaddr[UdpTransport::kIpAddressVersion6Length] = {0}; + + if (_socketTransportModule.RemoteSocketInformation(ipaddr, + rtpPortModule, + rtcpPortModule) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetSourceInfo() failed to retrieve remote socket information"); + return -1; + } + strcpy(ipAddr, ipaddr); + rtpPort = rtpPortModule; + rtcpPort = rtcpPortModule; + + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "GetSourceInfo() => rtpPort=%d, rtcpPort=%d, ipAddr=%s", + rtpPort, rtcpPort, ipAddr); + return 0; } WebRtc_Word32 -Channel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length) +Channel::EnableIPv6() { - WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), - "Channel::ReceivedRTCPPacket()"); + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::EnableIPv6()"); + if (_socketTransportModule.ReceiveSocketsInitialized() || + _socketTransportModule.SendSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_OPERATION, kTraceError, + "EnableIPv6() socket layer is already initialized"); + return -1; + } + if (_socketTransportModule.EnableIpV6() != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "EnableIPv6() failed to enable IPv6"); + const UdpTransport::ErrorCode lastError = + _socketTransportModule.LastError(); + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport::LastError() => %d", lastError); + return -1; + } + return 0; +} - // Store playout timestamp for the received RTCP packet - // which will be read by the GetRemoteRTCPData API - WebRtc_UWord32 playoutTimestamp(0); - if (GetPlayoutTimeStamp(playoutTimestamp) == 0) - { - _playoutTimeStampRTCP = playoutTimestamp; - } +bool +Channel::IPv6IsEnabled() const +{ + bool isEnabled = _socketTransportModule.IpV6Enabled(); + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "IPv6IsEnabled() => %d", isEnabled); + return isEnabled; +} - // Dump the RTCP packet to a file (if RTP dump is enabled). - if (_rtpDumpIn.DumpPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - WEBRTC_TRACE(kTraceWarning, kTraceVoice, - VoEId(_instanceId,_channelId), - "Channel::SendPacket() RTCP dump to input file failed"); - } +WebRtc_Word32 +Channel::SetSourceFilter(int rtpPort, int rtcpPort, const char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSourceFilter()"); + if (_socketTransportModule.SetFilterPorts( + static_cast<WebRtc_UWord16>(rtpPort), + static_cast<WebRtc_UWord16>(rtcpPort)) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "SetSourceFilter() failed to set filter ports"); + const UdpTransport::ErrorCode lastError = + _socketTransportModule.LastError(); + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport::LastError() => %d", + lastError); + return -1; + } + const char* filterIpAddress = ipAddr; + if (_socketTransportModule.SetFilterIP(filterIpAddress) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_IP_ADDRESS, kTraceError, + "SetSourceFilter() failed to set filter IP address"); + const UdpTransport::ErrorCode lastError = + _socketTransportModule.LastError(); + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport::LastError() => %d", lastError); + return -1; + } + return 0; +} - // Deliver RTCP packet to RTP/RTCP module for parsing - if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, - (WebRtc_UWord16)length) == -1) - { - _engineStatisticsPtr->SetLastError( - VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, - "Channel::IncomingRTPPacket() RTCP packet is invalid"); - } - return 0; +WebRtc_Word32 +Channel::GetSourceFilter(int& rtpPort, int& rtcpPort, char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSourceFilter()"); + WebRtc_UWord16 rtpFilterPort(0); + WebRtc_UWord16 rtcpFilterPort(0); + if (_socketTransportModule.FilterPorts(rtpFilterPort, rtcpFilterPort) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, + "GetSourceFilter() failed to retrieve filter ports"); + } + char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0}; + if (_socketTransportModule.FilterIP(ipAddrTmp) != 0) + { + // no filter has been configured (not seen as an error) + memset(ipAddrTmp, + 0, UdpTransport::kIpAddressVersion6Length); + } + rtpPort = static_cast<int> (rtpFilterPort); + rtcpPort = static_cast<int> (rtcpFilterPort); + strcpy(ipAddr, ipAddrTmp); + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "GetSourceFilter() => rtpPort=%d, rtcpPort=%d, ipAddr=%s", + rtpPort, rtcpPort, ipAddr); + return 0; } WebRtc_Word32 +Channel::SetSendTOS(int DSCP, int priority, bool useSetSockopt) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSendTOS(DSCP=%d, useSetSockopt=%d)", + DSCP, (int)useSetSockopt); + + // Set TOS value and possibly try to force usage of setsockopt() + if (_socketTransportModule.SetToS(DSCP, useSetSockopt) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kTosError: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() TOS error"); + break; + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError( + VE_TOS_GQOS_CONFLICT, kTraceError, + "SetSendTOS() GQOS error"); + break; + case UdpTransport::kTosInvalid: + // can't switch SetSockOpt method without disabling TOS first, or + // SetSockopt() call failed + _engineStatisticsPtr->SetLastError(VE_TOS_INVALID, kTraceError, + "SetSendTOS() invalid TOS"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError, + "SetSendTOS() invalid Socket"); + break; + default: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() TOS error"); + break; + } + WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport => lastError = %d", + lastSockError); + return -1; + } + + // Set priority (PCP) value, -1 means don't change + if (-1 != priority) + { + if (_socketTransportModule.SetPCP(priority) != 0) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kPcpError: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() PCP error"); + break; + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError( + VE_TOS_GQOS_CONFLICT, kTraceError, + "SetSendTOS() GQOS conflict"); + break; + case UdpTransport::kSocketInvalid: + _engineStatisticsPtr->SetLastError( + VE_SOCKET_ERROR, kTraceError, + "SetSendTOS() invalid Socket"); + break; + default: + _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError, + "SetSendTOS() PCP error"); + break; + } + WEBRTC_TRACE(kTraceError, kTraceVoice, + VoEId(_instanceId,_channelId), + "UdpTransport => lastError = %d", + lastSockError); + return -1; + } + } + + return 0; +} + +WebRtc_Word32 +Channel::GetSendTOS(int &DSCP, int& priority, bool &useSetSockopt) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSendTOS(DSCP=?, useSetSockopt=?)"); + WebRtc_Word32 dscp(0), prio(0); + bool setSockopt(false); + if (_socketTransportModule.ToS(dscp, setSockopt) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetSendTOS() failed to get TOS info"); + return -1; + } + if (_socketTransportModule.PCP(prio) != 0) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetSendTOS() failed to get PCP info"); + return -1; + } + DSCP = static_cast<int> (dscp); + priority = static_cast<int> (prio); + useSetSockopt = setSockopt; + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), + "GetSendTOS() => DSCP=%d, priority=%d, useSetSockopt=%d", + DSCP, priority, (int)useSetSockopt); + return 0; +} + +#if defined(_WIN32) +WebRtc_Word32 +Channel::SetSendGQoS(bool enable, int serviceType, int overrideDSCP) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SetSendGQoS(enable=%d, serviceType=%d, " + "overrideDSCP=%d)", + (int)enable, serviceType, overrideDSCP); + if(!_socketTransportModule.ReceiveSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKETS_NOT_INITED, kTraceError, + "SetSendGQoS() GQoS state must be set after sockets are created"); + return -1; + } + if(!_socketTransportModule.SendSocketsInitialized()) + { + _engineStatisticsPtr->SetLastError( + VE_DESTINATION_NOT_INITED, kTraceError, + "SetSendGQoS() GQoS state must be set after sending side is " + "initialized"); + return -1; + } + if (enable && + (serviceType != SERVICETYPE_BESTEFFORT) && + (serviceType != SERVICETYPE_CONTROLLEDLOAD) && + (serviceType != SERVICETYPE_GUARANTEED) && + (serviceType != SERVICETYPE_QUALITATIVE)) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_ARGUMENT, kTraceError, + "SetSendGQoS() Invalid service type"); + return -1; + } + if (enable && ((overrideDSCP < 0) || (overrideDSCP > 63))) + { + _engineStatisticsPtr->SetLastError( + VE_INVALID_ARGUMENT, kTraceError, + "SetSendGQoS() Invalid overrideDSCP value"); + return -1; + } + + // Avoid GQoS/ToS conflict when user wants to override the default DSCP + // mapping + bool QoS(false); + WebRtc_Word32 sType(0); + WebRtc_Word32 ovrDSCP(0); + if (_socketTransportModule.QoS(QoS, sType, ovrDSCP)) + { + _engineStatisticsPtr->SetLastError( + VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "SetSendGQoS() failed to get QOS info"); + return -1; + } + if (QoS && ovrDSCP == 0 && overrideDSCP != 0) + { + _engineStatisticsPtr->SetLastError( + VE_TOS_GQOS_CONFLICT, kTraceError, + "SetSendGQoS() QOS is already enabled and overrideDSCP differs," + " not allowed"); + return -1; + } + const WebRtc_Word32 maxBitrate(0); + if (_socketTransportModule.SetQoS(enable, + static_cast<WebRtc_Word32>(serviceType), + maxBitrate, + static_cast<WebRtc_Word32>(overrideDSCP), + true)) + { + UdpTransport::ErrorCode lastSockError( + _socketTransportModule.LastError()); + switch (lastSockError) + { + case UdpTransport::kQosError: + _engineStatisticsPtr->SetLastError(VE_GQOS_ERROR, kTraceError, + "SetSendGQoS() QOS error"); + break; + default: + _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError, + "SetSendGQoS() Socket error"); + break; + } + WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), + "UdpTransport() => lastError = %d", + lastSockError); + return -1; + } + return 0; +} +#endif + +#if defined(_WIN32) +WebRtc_Word32 +Channel::GetSendGQoS(bool &enabled, int &serviceType, int &overrideDSCP) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::GetSendGQoS(enable=?, serviceType=?, " + "overrideDSCP=?)"); + + bool QoS(false); + WebRtc_Word32 serviceTypeModule(0); + WebRtc_Word32 overrideDSCPModule(0); + _socketTransportModule.QoS(QoS, serviceTypeModule, overrideDSCPModule); + + enabled = QoS; + serviceType = static_cast<int> (serviceTypeModule); + overrideDSCP = static_cast<int> (overrideDSCPModule); + + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "GetSendGQoS() => enabled=%d, serviceType=%d, overrideDSCP=%d", + (int)enabled, serviceType, overrideDSCP); + return 0; +} +#endif +#endif + +WebRtc_Word32 Channel::SetPacketTimeoutNotification(bool enable, int timeoutSeconds) { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), @@ -2327,6 +3200,65 @@ Channel::GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds) return 0; } +WebRtc_Word32 +Channel::SendUDPPacket(const void* data, + unsigned int length, + int& transmittedBytes, + bool useRtcpSocket) +{ + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "Channel::SendUDPPacket()"); + if (_externalTransport) + { + _engineStatisticsPtr->SetLastError( + VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SendUDPPacket() external transport is enabled"); + return -1; + } + if (useRtcpSocket && !_rtpRtcpModule->RTCP()) + { + _engineStatisticsPtr->SetLastError( + VE_RTCP_ERROR, kTraceError, + "SendUDPPacket() RTCP is disabled"); + return -1; + } + if (!_sending) + { + _engineStatisticsPtr->SetLastError( + VE_NOT_SENDING, kTraceError, + "SendUDPPacket() not sending"); + return -1; + } + + char* dataC = new char[length]; + if (NULL == dataC) + { + _engineStatisticsPtr->SetLastError( + VE_NO_MEMORY, kTraceError, + "SendUDPPacket() memory allocation failed"); + return -1; + } + memcpy(dataC, data, length); + + transmittedBytes = SendPacketRaw(dataC, length, useRtcpSocket); + + delete [] dataC; + dataC = NULL; + + if (transmittedBytes <= 0) + { + _engineStatisticsPtr->SetLastError( + VE_SEND_ERROR, kTraceError, + "SendUDPPacket() transmission failed"); + transmittedBytes = 0; + return -1; + } + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), + "SendUDPPacket() => transmittedBytes=%d", transmittedBytes); + return 0; +} + + int Channel::StartPlayingFileLocally(const char* fileName, const bool loop, const FileFormats format, diff --git a/voice_engine/channel.h b/voice_engine/channel.h index cdb0790e..f1c5809b 100644 --- a/voice_engine/channel.h +++ b/voice_engine/channel.h @@ -27,6 +27,9 @@ #include "webrtc/voice_engine/shared_data.h" #include "webrtc/voice_engine/voice_engine_defines.h" +#ifndef WEBRTC_EXTERNAL_TRANSPORT +#include "webrtc/modules/udp_transport/interface/udp_transport.h" +#endif #ifdef WEBRTC_SRTP #include "SrtpModule.h" #endif @@ -62,6 +65,9 @@ class Channel: public RtpData, public RtpFeedback, public RtcpFeedback, +#ifndef WEBRTC_EXTERNAL_TRANSPORT + public UdpTransportData, // receiving packet from sockets +#endif public FileCallback, // receiving notification from file player & recorder public Transport, public RtpAudioFeedback, @@ -175,6 +181,9 @@ public: int sampleTimeSeconds); WebRtc_Word32 GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds); + WebRtc_Word32 SendUDPPacket(const void* data, unsigned int length, + int& transmittedBytes, bool useRtcpSocket); + // VoEFile int StartPlayingFileLocally(const char* fileName, const bool loop, const FileFormats format, @@ -404,6 +413,18 @@ public: const WebRtc_UWord8 volume); public: + // From UdpTransportData in the Socket Transport module + void IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket, + const WebRtc_Word32 rtpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort); + + void IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket, + const WebRtc_Word32 rtcpPacketLength, + const char* fromIP, + const WebRtc_UWord16 fromPort); + +public: // From Transport (called by the RTP/RTCP module) int SendPacket(int /*channel*/, const void *data, int len); int SendRTCPPacket(int /*channel*/, const void *data, int len); @@ -476,6 +497,16 @@ public: { return _outputAudioLevel.Level(); } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + bool SendSocketsInitialized() const + { + return _socketTransportModule.SendSocketsInitialized(); + } + bool ReceiveSocketsInitialized() const + { + return _socketTransportModule.ReceiveSocketsInitialized(); + } +#endif WebRtc_UWord32 Demultiplex(const AudioFrame& audioFrame); WebRtc_UWord32 PrepareEncodeAndSend(int mixingFrequency); WebRtc_UWord32 EncodeAndSend(); @@ -504,6 +535,10 @@ private: private: scoped_ptr<RtpRtcp> _rtpRtcpModule; AudioCodingModule& _audioCodingModule; +#ifndef WEBRTC_EXTERNAL_TRANSPORT + WebRtc_UWord8 _numSocketThreads; + UdpTransport& _socketTransportModule; +#endif #ifdef WEBRTC_SRTP SrtpModule& _srtpModule; #endif diff --git a/voice_engine/include/voe_base.h b/voice_engine/include/voe_base.h index 70cbab19..84cd4fc4 100644 --- a/voice_engine/include/voe_base.h +++ b/voice_engine/include/voe_base.h @@ -14,6 +14,7 @@ // - Initialization and termination. // - Trace information on text files or via callbacks. // - Multi-channel support (mixing, sending to multiple destinations etc.). +// - Call setup (port and address) for receiving and sending sides. // // To support other codecs than G.711, the VoECodec sub-API must be utilized. // @@ -139,6 +140,28 @@ public: // Deletes an existing channel and releases the utilized resources. virtual int DeleteChannel(int channel) = 0; + // Sets the local receiver port and address for a specified + // |channel| number. + virtual int SetLocalReceiver(int channel, int port, + int RTCPport = kVoEDefault, + const char ipAddr[64] = NULL, + const char multiCastAddr[64] = NULL) = 0; + + // Gets the local receiver port and address for a specified + // |channel| number. + virtual int GetLocalReceiver(int channel, int& port, int& RTCPport, + char ipAddr[64]) = 0; + + // Sets the destination port and address for a specified |channel| number. + virtual int SetSendDestination(int channel, int port, + const char ipAddr[64], + int sourcePort = kVoEDefault, + int RTCPport = kVoEDefault) = 0; + + // Gets the destination port and address for a specified |channel| number. + virtual int GetSendDestination(int channel, int& port, char ipAddr[64], + int& sourcePort, int& RTCPport) = 0; + // Prepares and initiates the VoiceEngine for reception of // incoming RTP/RTCP packets on the specified |channel|. virtual int StartReceive(int channel) = 0; diff --git a/voice_engine/include/voe_network.h b/voice_engine/include/voe_network.h index 9a2ff732..10acf1c5 100644 --- a/voice_engine/include/voe_network.h +++ b/voice_engine/include/voe_network.h @@ -11,6 +11,9 @@ // This sub-API supports the following functionalities: // // - External protocol support. +// - Extended port and address APIs. +// - Port and address filters. +// - Windows GQoS functions. // - Packet timeout notification. // - Dead-or-Alive connection observations. // - Transmission of raw RTP/RTCP packets into existing channels. @@ -90,6 +93,49 @@ public: virtual int ReceivedRTCPPacket( int channel, const void* data, unsigned int length) = 0; + // Gets the source ports and IP address of incoming packets on a + // specific |channel|. + virtual int GetSourceInfo( + int channel, int& rtpPort, int& rtcpPort, char ipAddr[64]) = 0; + + // Gets the local (host) IP address. + virtual int GetLocalIP(char ipAddr[64], bool ipv6 = false) = 0; + + // Enables IPv6 for a specified |channel|. + virtual int EnableIPv6(int channel) = 0; + + // Gets the current IPv6 staus for a specified |channel|. + virtual bool IPv6IsEnabled(int channel) = 0; + + // Enables a port and IP address filter for incoming packets on a + // specific |channel|. + virtual int SetSourceFilter(int channel, + int rtpPort, int rtcpPort = 0, const char ipAddr[64] = 0) = 0; + + // Gets the current port and IP-address filter for a specified |channel|. + virtual int GetSourceFilter( + int channel, int& rtpPort, int& rtcpPort, char ipAddr[64]) = 0; + + // Sets the six-bit Differentiated Services Code Point (DSCP) in the + // IP header of the outgoing stream for a specific |channel|. + virtual int SetSendTOS(int channel, + int DSCP, int priority = -1, bool useSetSockopt = false) = 0; + + // Gets the six-bit DSCP in the IP header of the outgoing stream for + // a specific channel. + virtual int GetSendTOS( + int channel, int& DSCP, int& priority, bool& useSetSockopt) = 0; + + // Sets the Generic Quality of Service (GQoS) service level. + // The Windows operating system then maps to a Differentiated Services + // Code Point (DSCP) and to an 802.1p setting. [Windows only] + virtual int SetSendGQoS( + int channel, bool enable, int serviceType, int overrideDSCP = 0) = 0; + + // Gets the Generic Quality of Service (GQoS) service level. + virtual int GetSendGQoS( + int channel, bool& enabled, int& serviceType, int& overrideDSCP) = 0; + // Enables or disables warnings that report if packets have not been // received in |timeoutSeconds| seconds for a specific |channel|. virtual int SetPacketTimeoutNotification( @@ -115,6 +161,12 @@ public: virtual int GetPeriodicDeadOrAliveStatus( int channel, bool& enabled, int& sampleTimeSeconds) = 0; + // Handles sending a raw UDP data packet over an existing RTP or RTCP + // socket. + virtual int SendUDPPacket( + int channel, const void* data, unsigned int length, + int& transmittedBytes, bool useRtcpSocket = false) = 0; + protected: VoENetwork() {} virtual ~VoENetwork() {} diff --git a/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h b/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h index c5f05007..bbdd64d0 100644 --- a/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h +++ b/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h @@ -13,30 +13,9 @@ #include "before_initialization_fixture.h" #include "scoped_ptr.h" -#include "webrtc/common_types.h" class TestErrorObserver; -class LoopBackTransport : public webrtc::Transport { - public: - LoopBackTransport(webrtc::VoENetwork* voe_network) - : voe_network_(voe_network) { - } - - virtual int SendPacket(int channel, const void *data, int len) { - voe_network_->ReceivedRTPPacket(channel, data, len); - return len; - } - - virtual int SendRTCPPacket(int channel, const void *data, int len) { - voe_network_->ReceivedRTCPPacket(channel, data, len); - return len; - } - - private: - webrtc::VoENetwork* voe_network_; -}; - // This fixture initializes the voice engine in addition to the work // done by the before-initialization fixture. It also registers an error // observer which will fail tests on error callbacks. This fixture is diff --git a/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc b/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc index 353888a6..d1e6039e 100644 --- a/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc +++ b/voice_engine/test/auto_test/fixtures/after_streaming_fixture.cc @@ -12,6 +12,8 @@ #include <cstring> +static const char* kLoopbackIp = "127.0.0.1"; + AfterStreamingFixture::AfterStreamingFixture() : channel_(voe_base_->CreateChannel()) { EXPECT_GE(channel_, 0); @@ -28,9 +30,7 @@ AfterStreamingFixture::~AfterStreamingFixture() { voe_file_->StopPlayingFileAsMicrophone(channel_); PausePlaying(); - EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(channel_)); voe_base_->DeleteChannel(channel_); - delete transport_; } void AfterStreamingFixture::SwitchToManualMicrophone() { @@ -59,8 +59,8 @@ void AfterStreamingFixture::ResumePlaying() { } void AfterStreamingFixture::SetUpLocalPlayback() { - transport_ = new LoopBackTransport(voe_network_); - EXPECT_EQ(0, voe_network_->RegisterExternalTransport(channel_, *transport_)); + EXPECT_EQ(0, voe_base_->SetSendDestination(channel_, 8000, kLoopbackIp)); + EXPECT_EQ(0, voe_base_->SetLocalReceiver(0, 8000)); webrtc::CodecInst codec; codec.channels = 1; diff --git a/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h b/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h index 26e37a7b..6b0a61f3 100644 --- a/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h +++ b/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h @@ -42,8 +42,6 @@ class AfterStreamingFixture : public AfterInitializationFixture { private: void SetUpLocalPlayback(); - - LoopBackTransport* transport_; }; diff --git a/voice_engine/test/auto_test/standard/mixing_test.cc b/voice_engine/test/auto_test/standard/mixing_test.cc index 1d2aea38..6a90c07e 100644 --- a/voice_engine/test/auto_test/standard/mixing_test.cc +++ b/voice_engine/test/auto_test/standard/mixing_test.cc @@ -32,13 +32,7 @@ class MixingTest : public AfterInitializationFixture { : input_filename_(test::OutputPath() + "mixing_test_input.pcm"), output_filename_(test::OutputPath() + "mixing_test_output.pcm") { } - void SetUp() { - transport_ = new LoopBackTransport(voe_network_); - } - void TearDown() { - delete transport_; - } - + // Creates and mixes |num_remote_streams| which play a file "as microphone" // with |num_local_streams| which play a file "locally", using a constant // amplitude of |input_value|. The local streams manifest as "anonymous" @@ -171,7 +165,8 @@ class MixingTest : public AfterInitializationFixture { // Start up a single remote stream. void StartRemoteStream(int stream, const CodecInst& codec_inst, int port) { EXPECT_EQ(0, voe_codec_->SetRecPayloadType(stream, codec_inst)); - EXPECT_EQ(0, voe_network_->RegisterExternalTransport(stream, *transport_)); + EXPECT_EQ(0, voe_base_->SetLocalReceiver(stream, port)); + EXPECT_EQ(0, voe_base_->SetSendDestination(stream, port, "127.0.0.1")); EXPECT_EQ(0, voe_base_->StartReceive(stream)); EXPECT_EQ(0, voe_base_->StartPlayout(stream)); EXPECT_EQ(0, voe_codec_->SetSendCodec(stream, codec_inst)); @@ -185,14 +180,12 @@ class MixingTest : public AfterInitializationFixture { EXPECT_EQ(0, voe_base_->StopSend(streams[i])); EXPECT_EQ(0, voe_base_->StopPlayout(streams[i])); EXPECT_EQ(0, voe_base_->StopReceive(streams[i])); - EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(streams[i])); EXPECT_EQ(0, voe_base_->DeleteChannel(streams[i])); } } const std::string input_filename_; const std::string output_filename_; - LoopBackTransport* transport_; }; // These tests assume a maximum of three mixed participants. We typically allow diff --git a/voice_engine/test/auto_test/standard/network_before_streaming_test.cc b/voice_engine/test/auto_test/standard/network_before_streaming_test.cc new file mode 100644 index 00000000..7a41e806 --- /dev/null +++ b/voice_engine/test/auto_test/standard/network_before_streaming_test.cc @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011 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 "after_initialization_fixture.h" + +class NetworkBeforeStreamingTest : public AfterInitializationFixture { + protected: + void SetUp() { + channel_ = voe_base_->CreateChannel(); + } + + void TearDown() { + voe_base_->DeleteChannel(channel_); + } + + int channel_; +}; + +TEST_F(NetworkBeforeStreamingTest, + GetSourceInfoReturnsEmptyValuesForUnconfiguredChannel) { + char src_ip[32] = "0.0.0.0"; + int src_rtp_port = 1234; + int src_rtcp_port = 1235; + + EXPECT_EQ(0, voe_network_->GetSourceInfo( + channel_, src_rtp_port, src_rtcp_port, src_ip)); + EXPECT_EQ(0, src_rtp_port); + EXPECT_EQ(0, src_rtcp_port); + EXPECT_STRCASEEQ("", src_ip); +} + +TEST_F(NetworkBeforeStreamingTest, + GetSourceFilterReturnsEmptyValuesForUnconfiguredChannel) { + int filter_port = -1; + int filter_port_rtcp = -1; + char filter_ip[32] = "0.0.0.0"; + + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_port, filter_port_rtcp, filter_ip)); + + EXPECT_EQ(0, filter_port); + EXPECT_EQ(0, filter_port_rtcp); + EXPECT_STRCASEEQ("", filter_ip); +} + +TEST_F(NetworkBeforeStreamingTest, SetSourceFilterSucceeds) { + EXPECT_EQ(0, voe_network_->SetSourceFilter(channel_, 0)); +} diff --git a/voice_engine/test/auto_test/standard/network_test.cc b/voice_engine/test/auto_test/standard/network_test.cc index f4713dc1..8bf2d11c 100644 --- a/voice_engine/test/auto_test/standard/network_test.cc +++ b/voice_engine/test/auto_test/standard/network_test.cc @@ -23,6 +23,79 @@ class NetworkTest : public AfterStreamingFixture { using ::testing::Between; +TEST_F(NetworkTest, GetSourceInfoReturnsPortsAndIpAfterReceivingPackets) { + // Give some time to send speech packets. + Sleep(200); + + int rtp_port = 0; + int rtcp_port = 0; + char source_ip[32] = "127.0.0.1"; + + EXPECT_EQ(0, voe_network_->GetSourceInfo(channel_, rtp_port, rtcp_port, + source_ip)); + + EXPECT_EQ(kDefaultRtpPort, rtp_port); + EXPECT_EQ(kDefaultRtcpPort, rtcp_port); +} + +TEST_F(NetworkTest, NoFilterIsEnabledByDefault) { + int filter_rtp_port = -1; + int filter_rtcp_port = -1; + char filter_ip[64] = { 0 }; + + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_rtp_port, filter_rtcp_port, filter_ip)); + + EXPECT_EQ(0, filter_rtp_port); + EXPECT_EQ(0, filter_rtcp_port); + EXPECT_STREQ("", filter_ip); +} + +TEST_F(NetworkTest, ManualCanFilterRtpPort) { + TEST_LOG("No filter, should hear audio.\n"); + Sleep(1000); + + int port_to_block = kDefaultRtpPort + 10; + EXPECT_EQ(0, voe_network_->SetSourceFilter(channel_, port_to_block)); + + // Changes should take effect immediately. + int filter_rtp_port = -1; + int filter_rtcp_port = -1; + char filter_ip[64] = { 0 }; + + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_rtp_port, filter_rtcp_port, filter_ip)); + + EXPECT_EQ(port_to_block, filter_rtp_port); + + TEST_LOG("Now filtering port %d, should not hear audio.\n", port_to_block); + Sleep(1000); + + TEST_LOG("Removing filter, should hear audio.\n"); + EXPECT_EQ(0, voe_network_->SetSourceFilter(channel_, 0)); + Sleep(1000); +} + +TEST_F(NetworkTest, ManualCanFilterIp) { + TEST_LOG("You should hear audio.\n"); + Sleep(1000); + + int rtcp_port_to_block = kDefaultRtcpPort + 10; + TEST_LOG("Filtering IP 10.10.10.10, should not hear audio.\n"); + EXPECT_EQ(0, voe_network_->SetSourceFilter( + channel_, 0, rtcp_port_to_block, "10.10.10.10")); + + int filter_rtp_port = -1; + int filter_rtcp_port = -1; + char filter_ip[64] = { 0 }; + EXPECT_EQ(0, voe_network_->GetSourceFilter( + channel_, filter_rtp_port, filter_rtcp_port, filter_ip)); + + EXPECT_EQ(0, filter_rtp_port); + EXPECT_EQ(rtcp_port_to_block, filter_rtcp_port); + EXPECT_STREQ("10.10.10.10", filter_ip); +} + TEST_F(NetworkTest, CallsObserverOnTimeoutAndRestartWhenPacketTimeoutNotificationIsEnabled) { // First, get rid of the default, asserting observer and install our observer. diff --git a/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc b/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc index 7815288d..3549cb36 100644 --- a/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc +++ b/voice_engine/test/auto_test/standard/rtp_rtcp_test.cc @@ -101,10 +101,10 @@ class RtpRtcpTest : public AfterStreamingFixture { second_channel_ = voe_base_->CreateChannel(); EXPECT_GE(second_channel_, 0); - transport_ = new LoopBackTransport(voe_network_); - EXPECT_EQ(0, voe_network_->RegisterExternalTransport(second_channel_, - *transport_)); - + EXPECT_EQ(0, voe_base_->SetSendDestination( + second_channel_, 8002, "127.0.0.1")); + EXPECT_EQ(0, voe_base_->SetLocalReceiver( + second_channel_, 8002)); EXPECT_EQ(0, voe_base_->StartReceive(second_channel_)); EXPECT_EQ(0, voe_base_->StartPlayout(second_channel_)); EXPECT_EQ(0, voe_rtp_rtcp_->SetLocalSSRC(second_channel_, 5678)); @@ -115,13 +115,10 @@ class RtpRtcpTest : public AfterStreamingFixture { } void TearDown() { - EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(second_channel_)); voe_base_->DeleteChannel(second_channel_); - delete transport_; } int second_channel_; - LoopBackTransport* transport_; }; void RtcpAppHandler::OnApplicationDataReceived( diff --git a/voice_engine/test/auto_test/voe_cpu_test.cc b/voice_engine/test/auto_test/voe_cpu_test.cc index 2737ee82..14e4a00e 100644 --- a/voice_engine/test/auto_test/voe_cpu_test.cc +++ b/voice_engine/test/auto_test/voe_cpu_test.cc @@ -8,8 +8,6 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "voe_cpu_test.h" - #include <stdio.h> #include <string.h> #include <time.h> @@ -18,8 +16,7 @@ #include <conio.h> #endif -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" +#include "voe_cpu_test.h" using namespace webrtc; @@ -48,7 +45,6 @@ int VoECpuTest::DoTest() { VoEFile* file = _mgr.FilePtr(); VoECodec* codec = _mgr.CodecPtr(); VoEAudioProcessing* apm = _mgr.APMPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); int channel(-1); CodecInst isac; @@ -63,12 +59,8 @@ int VoECpuTest::DoTest() { CHECK(base->Init()); channel = base->CreateChannel(); - scoped_ptr<VoiceChannelTransport> voice_socket_transport( - new VoiceChannelTransport(voe_network, channel)); - - CHECK(voice_socket_transport->SetSendDestination("127.0.0.1", 5566)); - CHECK(voice_socket_transport->SetLocalReceiver(5566)); - + CHECK(base->SetLocalReceiver(channel, 5566)); + CHECK(base->SetSendDestination(channel, 5566, "127.0.0.1")); CHECK(codec->SetRecPayloadType(channel, isac)); CHECK(codec->SetSendCodec(channel, isac)); @@ -94,6 +86,7 @@ int VoECpuTest::DoTest() { base->DeleteChannel(channel); CHECK(base->Terminate()); + return 0; } diff --git a/voice_engine/test/auto_test/voe_extended_test.cc b/voice_engine/test/auto_test/voe_extended_test.cc index ce269923..d4c49c44 100644 --- a/voice_engine/test/auto_test/voe_extended_test.cc +++ b/voice_engine/test/auto_test/voe_extended_test.cc @@ -8,17 +8,22 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/voice_engine/test/auto_test/voe_extended_test.h" - #include <stdio.h> #include <string.h> #include <vector> +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" +#include "webrtc/system_wrappers/interface/event_wrapper.h" +#include "webrtc/system_wrappers/interface/ref_count.h" +#include "webrtc/system_wrappers/interface/sleep.h" +#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/voice_engine/voice_engine_defines.h" +#include "webrtc/voice_engine/test/auto_test/voe_extended_test.h" #if defined(_WIN32) #include <conio.h> +#include <winsock2.h> #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) #include <netdb.h> #endif @@ -153,6 +158,21 @@ int ExtendedTestTransport::SendRTCPPacket(int channel, const void *data, int len return len; } +XTransport::XTransport(VoENetwork* netw, VoEFile* file) : + _netw(netw), _file(file) { +} + +int XTransport::SendPacket(int channel, const void *data, int len) { + // loopback + // _netw->ReceivedRTPPacket(channel, data, len); + + return 0; +} + +int XTransport::SendRTCPPacket(int, const void *, int) { + return 0; +} + // ---------------------------------------------------------------------------- // VoERTPObserver // ---------------------------------------------------------------------------- @@ -235,14 +255,8 @@ void VoEExtendedTest::StartMedia(int channel, int rtpPort, bool listen, _playing[channel] = false; _sending[channel] = false; - VoENetwork* voe_network = _mgr.NetworkPtr(); - - voice_channel_transports_[channel].reset( - new VoiceChannelTransport(voe_network, channel)); - - voice_channel_transports_[channel]->SetSendDestination("127.0.0.1", rtpPort); - voice_channel_transports_[channel]->SetLocalReceiver(rtpPort); - + voe_base_->SetLocalReceiver(channel, rtpPort); + voe_base_->SetSendDestination(channel, rtpPort, "127.0.0.1"); if (listen) { _listening[channel] = true; voe_base_->StartReceive(channel); @@ -272,7 +286,6 @@ void VoEExtendedTest::StopMedia(int channel) { _sending[channel] = false; voe_base_->StopSend(channel); } - voice_channel_transports_[channel].reset(NULL); } void VoEExtendedTest::Play(int channel, unsigned int timeMillisec, bool addFileAsMicrophone, @@ -320,7 +333,7 @@ int VoEExtendedTest::TestBase() { // instance variable since it is required in order to appease the // gods of darkness. VoEBase* voe_base_ = _mgr.BasePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); + VoENetwork* netw = _mgr.NetworkPtr(); #ifdef _TEST_RTP_RTCP_ VoERTP_RTCP* rtp = _mgr.RTP_RTCPPtr(); #endif @@ -542,6 +555,305 @@ int VoEExtendedTest::TestBase() { ANL(); // ------------------------------------------------------------------------ + // >> SetLocalReceiver + // + // State: VE not initialized, no existing channels + TEST_MUSTPASS(voe_base_->Init()); + + int ch; + + TEST(SetLocalReceiver); + ANL(); + + // no channel created yet => should fail + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(0, 100)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + ch = voe_base_->CreateChannel(); + +#ifdef WEBRTC_IOS + printf("\nNOTE: Local IP must be set in source code (line %d) \n", + __LINE__ + 1); + char* localIp = "127.0.0.1"; +#else + char localIp[64] = { 0 }; + TEST_MUSTPASS(netw->GetLocalIP(localIp)); + MARK(); + // NOTE: This API is supported on Win, Mac and Linux and may fail or not + // return local IP for other platforms. +#endif + + // trivial invalid function calls + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch+1, 12345)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, -1)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); + + // check conflict with ongoing receiving + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + TEST_ERROR(VE_ALREADY_LISTENING); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + // check conflict with ongoing transmission + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + TEST_ERROR(VE_ALREADY_SENDING); + TEST_MUSTPASS(voe_base_->StopSend(ch)); + + // valid function calls + // Need to sleep between, otherwise it may fail for unknown reason + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, NULL, + "230.1.2.3")); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp, + "230.1.2.3")); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 5555, NULL)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + + // STATE: no media but sockets exists and are binded to 12345 and 12346 + // respectively + + // Add some dynamic tests as well: + + // ensure that last setting is used (cancels old settings) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 44444)); + MARK(); + SleepMs(100); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 54321)); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 54321, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + Play(ch, 1000, true, true); + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of SetLocalReceiver + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetLocalReceiver + // + // State: VE initialized, no existing channels + TEST(GetLocalReceiver); + ANL(); + + int port; + char ipaddr[64]; + int RTCPport; + + ch = voe_base_->CreateChannel(); + + // verify non-configured (blank) local receiver + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 0); + TEST_MUSTPASS(RTCPport != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // check some trivial set/get combinations + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)) + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 12345); + TEST_MUSTPASS(RTCPport != 12346); + TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0); // now binded to "any" IP + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 55555)) + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 12345); + TEST_MUSTPASS(RTCPport != 55555); + TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, kVoEDefault, localIp)) + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, port, RTCPport, ipaddr)); + MARK(); + TEST_MUSTPASS(port != 12345); + TEST_MUSTPASS(RTCPport != 12346); + TEST_MUSTPASS(strcmp(ipaddr, localIp) != 0); + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetLocalReceiver + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSendDestination + // + // State: VE initialized, no existing channels + TEST(SetSendDestination); + ANL(); + + // call without existing channel + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + ch = voe_base_->CreateChannel(); + + // trivial fail tests + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 65536, "127.0.0.1")); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid RTP port + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid source port + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", kVoEDefault, + 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); // invalid RTCP port + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 12345, "127.0.0.300")); + MARK(); + TEST_ERROR(VE_INVALID_IP_ADDRESS); // invalid IP address + + // sockets must be created first to support multi-cast (not required + // otherwise) + TEST_MUSTPASS(!voe_base_->SetSendDestination(ch, 55555, "230.0.0.1")); + MARK(); + TEST_ERROR(VE_SOCKET_ERROR); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); // create sockets + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "230.0.0.1")); + MARK(); // should work now + + voe_base_->DeleteChannel(0); + ch = voe_base_->CreateChannel(); + + // STATE: one channel created, no sockets exist + + // valid function calls + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1")); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444)); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", kVoEDefault, + 55555)); + MARK(); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444, + 55555)); + MARK(); + + voe_base_->DeleteChannel(0); + ch = voe_base_->CreateChannel(); + + // create receive sockets first and then an extra pair of send sockets + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 44444)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1", 11111)); + MARK(); // binds to 11111 + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of SetSendDestination + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetSendDestination + // + // State: VE initialized, no existing channels + TEST(GetSendDestination); + ANL(); + + int sourcePort; + + ch = voe_base_->CreateChannel(); + + // verify non-configured (blank) local receiver + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 0); + TEST_MUSTPASS(sourcePort != 0); + TEST_MUSTPASS(RTCPport != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // check some trivial set/get combinations + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 44444); + TEST_MUSTPASS(sourcePort != 0); // should be 0 since no local receiver has + // NOT been defined yet + TEST_MUSTPASS(RTCPport != 44445); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, ipaddr, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 44444); + TEST_MUSTPASS(sourcePort != 55555); // should be equal to local port + TEST_MUSTPASS(RTCPport != 44445); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + voe_base_->DeleteChannel(0); + ch = voe_base_->CreateChannel(); + + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 44444, "127.0.0.1")); + // NULL as IP-address input should work as well + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, port, NULL, sourcePort, + RTCPport)); + MARK(); + TEST_MUSTPASS(port != 44444); + TEST_MUSTPASS(sourcePort != 0); + TEST_MUSTPASS(RTCPport != 44445); + + TEST_MUSTPASS(voe_base_->DeleteChannel(ch)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetLocalReceiver + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ // >> StartReceive // >> StopReceive // @@ -559,14 +871,14 @@ int VoEExtendedTest::TestBase() { MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); - int ch = voe_base_->CreateChannel(); + ch = voe_base_->CreateChannel(); - // must register external transport first. + // sockets must be created first TEST_MUSTPASS(!voe_base_->StartReceive(0)); MARK(); - - ExtendedTestTransport* ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + TEST_ERROR(VE_SOCKETS_NOT_INITED); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); MARK(); // should work this time // enable again (should work) @@ -580,6 +892,7 @@ int VoEExtendedTest::TestBase() { MARK(); // Verify in loopback + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartSend(ch)); Play(ch, 1000, true, true); TEST_MUSTPASS(voe_base_->StopSend(ch)); @@ -587,15 +900,16 @@ int VoEExtendedTest::TestBase() { MARK(); voe_base_->DeleteChannel(0); - delete ptrTransport; ch = voe_base_->CreateChannel(); // Ensure that it is OK to add delay between SetLocalReceiver and StarListen TEST_LOG("\nspeak after 2 seconds and ensure that no delay is added:\n"); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 55555)); Sleep(2000, true); // adding emulated delay here TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 55555, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartSend(ch)); Play(ch, 2000, true, true); TEST_MUSTPASS(voe_base_->StopSend(ch)); @@ -608,23 +922,23 @@ int VoEExtendedTest::TestBase() { for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 11111+2*i)); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); MARK(); } for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { - voe_base_->DeleteChannel(i); + TEST_MUSTPASS(voe_base_->StopReceive(i)); MARK(); + voe_base_->DeleteChannel(i); } for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { ch = voe_base_->CreateChannel(); - ExtendedTestTransport* ptrTransport = - new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 11111+2*i)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); MARK(); TEST_MUSTPASS(voe_base_->StopReceive(ch)); MARK(); voe_base_->DeleteChannel(ch); - delete ptrTransport; } ANL(); @@ -719,24 +1033,25 @@ int VoEExtendedTest::TestBase() { MARK(); TEST_ERROR(VE_DESTINATION_NOT_INITED); - // initialize destination and try again (should work even without existing // sockets) - ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartSend(ch)); MARK(); SleepMs(100); + // STATE: sockets should now have been created automatically at the first + // transmitted packet should be binded to 33333 and "0.0.0.0" TEST_MUSTPASS(voe_base_->StopSend(ch)); MARK(); voe_base_->DeleteChannel(ch); - delete ptrTransport; ch = voe_base_->CreateChannel(); - ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(ch, *ptrTransport)); + // try loopback with unique send sockets (closed when channel is deleted or + // new source is set) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33333)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333, "127.0.0.1", 44444)); TEST_MUSTPASS(voe_base_->StartSend(ch)); MARK(); TEST_MUSTPASS(voe_base_->StartReceive(ch)); @@ -746,7 +1061,31 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopReceive(ch)); voe_base_->DeleteChannel(ch); + ANL(); + // Multi-channel tests + for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { + ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33333 + 2*i)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33333 + 2*i, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + MARK(); + } + for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { + TEST_MUSTPASS(voe_base_->StopSend(i)); + MARK(); + voe_base_->DeleteChannel(i); + } + for (i = 0; i < voe_base_->MaxNumOfChannels(); i++) { + ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 45633 + 2*i)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 45633 + 2*i, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + MARK(); + TEST_MUSTPASS(voe_base_->StopSend(ch)); + MARK(); + voe_base_->DeleteChannel(ch); + } ANL(); AOK(); ANL(); @@ -824,11 +1163,9 @@ int VoEExtendedTest::TestBase() { ch = voe_base_->CreateChannel(); - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(voe_network, ch)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); @@ -869,9 +1206,9 @@ int VoEExtendedTest::TestBase() { #ifdef _TEST_RTP_RTCP_ TEST_MUSTPASS(rtp->SetRTCP_CNAME(ch, "Johnny")); #endif - voice_channel_transport.reset(new VoiceChannelTransport(voe_network, ch)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345, 12349)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", kVoEDefault, + 12349)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -889,11 +1226,18 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(rtp->GetRemoteRTCP_CNAME(ch, tmpStr)); TEST_MUSTPASS(_stricmp("Johnny", tmpStr)); #endif + int rtpPort(0), rtcpPort(0); + char ipAddr[64] = { 0 }; + TEST_MUSTPASS(netw->GetSourceInfo(ch, rtpPort, rtcpPort, ipAddr)); + TEST_MUSTPASS(12349 != rtcpPort); TEST_MUSTPASS(voe_base_->StopSend(ch)); TEST_MUSTPASS(voe_base_->StopPlayout(ch)); TEST_MUSTPASS(voe_base_->StopReceive(ch)); // Call StartSend before StartReceive + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); @@ -907,6 +1251,9 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopReceive(ch)); // Try again using same ports + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartSend(ch)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); @@ -917,17 +1264,38 @@ int VoEExtendedTest::TestBase() { SleepMs(7000); // Make sure we get RTCP packet PAUSE + // Verify correct RTCP source port + TEST_MUSTPASS(netw->GetSourceInfo(ch, rtpPort, rtcpPort, ipAddr)); + TEST_MUSTPASS(12345+1 != rtcpPort); TEST_MUSTPASS(voe_base_->StopSend(ch)); TEST_MUSTPASS(voe_base_->StopPlayout(ch)); TEST_MUSTPASS(voe_base_->StopReceive(ch)); voe_base_->DeleteChannel(ch); - ch = voe_base_->CreateChannel(); - voice_channel_transport.reset(new VoiceChannelTransport(voe_network, ch)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + // Try with extra send socket + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 22222)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 22222, "127.0.0.1", 11111)); + + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + TEST_MUSTPASS(voe_base_->StartPlayout(ch)); + + TEST_LOG("\nfull duplex is now activated (4)\n"); + + PAUSE + + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopPlayout(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + // repeat default case starting with a fresh channel + + voe_base_->DeleteChannel(ch); + ch = voe_base_->CreateChannel(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -942,6 +1310,7 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopReceive(ch)); // restart call again + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 12345)); TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -954,15 +1323,35 @@ int VoEExtendedTest::TestBase() { TEST_MUSTPASS(voe_base_->StopPlayout(ch)); TEST_MUSTPASS(voe_base_->StopReceive(ch)); + // force sending from new socket + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 12345, "127.0.0.1", 12350, + 12359)); + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartPlayout(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + TEST_LOG("\nfull duplex is now activated (7)\n"); + + PAUSE + + // Test getting send settings + TEST_MUSTPASS(voe_base_->GetSendDestination(ch, rtpPort, ipAddr, sourcePort, + rtcpPort)); + TEST_MUSTPASS(12345 != rtpPort); + TEST_MUSTPASS(_stricmp("127.0.0.1", ipAddr)); + TEST_MUSTPASS(12350 != sourcePort); + TEST_MUSTPASS(12359 != rtcpPort); + + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopPlayout(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + // new channel and new port ch = voe_base_->CreateChannel(); - scoped_ptr<VoiceChannelTransport> voice_channel_transport_2( - new VoiceChannelTransport(voe_network, ch)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch , 33221)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33221, "127.0.0.1")); - voice_channel_transport_2->SetSendDestination("127.0.0.1", 33221); - voice_channel_transport_2->SetLocalReceiver(33221); - TEST_MUSTPASS(voe_base_->StartReceive(ch)); TEST_MUSTPASS(voe_base_->StartPlayout(ch)); TEST_MUSTPASS(voe_base_->StartSend(ch)); @@ -971,6 +1360,36 @@ int VoEExtendedTest::TestBase() { PAUSE + TEST_MUSTPASS(voe_base_->StopSend(ch)); + TEST_MUSTPASS(voe_base_->StopPlayout(ch)); + TEST_MUSTPASS(voe_base_->StopReceive(ch)); + + voe_base_->DeleteChannel(ch); + ch = voe_base_->CreateChannel(); + +#ifndef WEBRTC_IOS + // bind to local IP and try again + strcpy(localIp, "127.0.0.1"); +#else + localIp = "127.0.0.1"; +#endif + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(ch, 33221, 12349, localIp)); + TEST_MUSTPASS(voe_base_->SetSendDestination(ch, 33221, localIp)); + + TEST_MUSTPASS(voe_base_->StartReceive(ch)); + TEST_MUSTPASS(voe_base_->StartPlayout(ch)); + TEST_MUSTPASS(voe_base_->StartSend(ch)); + + TEST_LOG("\nfull duplex is now activated (9)\n"); + + PAUSE + + TEST_MUSTPASS(voe_base_->GetLocalReceiver(ch, rtpPort, rtcpPort, ipAddr)); + TEST_MUSTPASS(33221 != rtpPort); + TEST_MUSTPASS(_stricmp(localIp, ipAddr)); + TEST_MUSTPASS(12349 != rtcpPort); + ANL(); AOK(); ANL(); @@ -1058,6 +1477,7 @@ int VoEExtendedTest::TestBase() { voe_base_->DeleteChannel(0); TEST_MUSTPASS(voe_base_->Terminate()); + return 0; } @@ -1071,7 +1491,7 @@ int VoEExtendedTest::TestCallReport() { VoECallReport* report = _mgr.CallReportPtr(); VoEFile* file = _mgr.FilePtr(); VoEAudioProcessing* apm = _mgr.APMPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); + VoENetwork* netw = _mgr.NetworkPtr(); PrepareTest("CallReport"); @@ -1096,10 +1516,8 @@ int VoEExtendedTest::TestCallReport() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -1163,14 +1581,14 @@ int VoEExtendedTest::TestCallReport() { // All results should be -1 since dead-or-alive is not active TEST_MUSTPASS(report->GetDeadOrAliveSummary(0, nDead, nAlive) != -1); MARK(); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 1)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 1)); SleepMs(2000); // All results should be >= 0 since dead-or-alive is active TEST_MUSTPASS(report->GetDeadOrAliveSummary(0, nDead, nAlive)); MARK(); TEST_MUSTPASS(nDead == -1); TEST_MUSTPASS(nAlive == -1) - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); AOK(); ANL(); @@ -1223,7 +1641,6 @@ int VoEExtendedTest::TestCodec() { VoEBase* voe_base_ = _mgr.BasePtr(); VoECodec* codec = _mgr.CodecPtr(); VoEFile* file = _mgr.FilePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -1240,8 +1657,14 @@ int VoEExtendedTest::TestCodec() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - ExtendedTestTransport* ptrTransport = new ExtendedTestTransport(voe_network); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + ExtendedTestTransport* ptrTransport(NULL); + ptrTransport = new ExtendedTestTransport(netw); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); +#else + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); +#endif TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -1717,6 +2140,10 @@ int VoEExtendedTest::TestCodec() { TEST_MUSTPASS(voe_base_->StopReceive(0)); // start loopback streaming (PCMU is default) +#ifndef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(voe_base_->SetSendDestination(0,8000,"127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0,8000)); +#endif TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -1989,12 +2416,16 @@ int VoEExtendedTest::TestCodec() { TEST(SetRecPayloadType - removing receive codecs); ANL(); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); +#endif TEST_MUSTPASS(voe_base_->StartSend(0)); if (file) { TEST_MUSTPASS(file->StartPlayingFileAsMicrophone(0, - _mgr.AudioFilename(), - true, - true)); + _mgr.AudioFilename(), + true, + true)); } // Scan all supported and valid codecs and remove from receiving db, then @@ -2509,7 +2940,12 @@ int VoEExtendedTest::TestCodec() { // set iSAC as sending codec // set iSAC-wb as sending codec - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); +#else + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8001, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8001)); +#endif TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartReceive(0)); @@ -2555,8 +2991,10 @@ int VoEExtendedTest::TestCodec() { TEST_LOG("Skipping extended iSAC API tests - " "WEBRTC_CODEC_ISAC not defined\n"); #endif // #if defined(WEBRTC_CODEC_ISAC) - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); delete ptrTransport; +#endif TEST_MUSTPASS(voe_base_->DeleteChannel(0)); TEST_MUSTPASS(voe_base_->Terminate()); @@ -2575,7 +3013,6 @@ int VoEExtendedTest::TestDtmf() { VoEDtmf* dtmf = _mgr.DtmfPtr(); VoECodec* codec = _mgr.CodecPtr(); VoEVolumeControl* volume = _mgr.VolumeControlPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); std::string output_path = webrtc::test::OutputPath(); TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -2591,10 +3028,8 @@ int VoEExtendedTest::TestDtmf() { //#endif TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -2904,7 +3339,6 @@ int VoEExtendedTest::TestEncryption() { VoEBase* voe_base_ = _mgr.BasePtr(); VoEFile* file = _mgr.FilePtr(); VoEEncryption* encrypt = _mgr.EncryptionPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -2920,10 +3354,8 @@ int VoEExtendedTest::TestEncryption() { #endif TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -3418,7 +3850,6 @@ int VoEExtendedTest::TestExternalMedia() { VoEBase* voe_base_ = _mgr.BasePtr(); VoEExternalMedia* xmedia = _mgr.ExternalMediaPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); // check if this interface is supported if (!xmedia) { @@ -3436,10 +3867,8 @@ int VoEExtendedTest::TestExternalMedia() { #endif TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -3544,7 +3973,6 @@ int VoEExtendedTest::TestFile() { VoEBase* voe_base_ = _mgr.BasePtr(); VoEFile* file = _mgr.FilePtr(); VoECodec* codec = _mgr.CodecPtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile( @@ -3561,10 +3989,8 @@ int VoEExtendedTest::TestFile() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -3963,10 +4389,9 @@ int VoEExtendedTest::TestFile() { TEST_MUSTPASS(ch == -1); TEST_MUSTPASS(voe_base_->StopPlayout(ch)); } - scoped_ptr<VoiceChannelTransport> voice_channel_transport_1( - new VoiceChannelTransport(voe_network, 1)); - voice_channel_transport_1->SetSendDestination("127.0.0.1", 12356); - voice_channel_transport_1->SetLocalReceiver(12356); + + TEST_MUSTPASS(voe_base_->SetSendDestination(1, 12356, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(1, 12356)); TEST_MUSTPASS(voe_base_->StartReceive(1)); TEST_MUSTPASS(voe_base_->StopPlayout(1)); TEST_MUSTPASS(voe_base_->StartSend(1)); @@ -4553,8 +4978,20 @@ int VoEExtendedTest::TestNetEqStats() { int VoEExtendedTest::TestNetwork() { PrepareTest("Network"); +#ifdef WEBRTC_ANDROID + int sleepTime = 200; + int sleepTime2 = 250; +#elif defined(WEBRTC_IOS) // WEBRTC_IOS needs more delay for getSourceInfo() + int sleepTime = 150; + int sleepTime2 = 200; +#else + int sleepTime = 100; + int sleepTime2 = 200; +#endif + VoEBase* voe_base_ = _mgr.BasePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); + VoEFile* file = _mgr.FilePtr(); + VoENetwork* netw = _mgr.NetworkPtr(); #ifdef _USE_EXTENDED_TRACE_ TEST_MUSTPASS(VoiceEngine::SetTraceFile((output_path + @@ -4572,6 +5009,259 @@ int VoEExtendedTest::TestNetwork() { TEST_MUSTPASS(voe_base_->Init()); // ------------------------------------------------------------------------ + // >> GetLocalIP + // + // State: VE initialized, no existing channels + TEST(GetLocalIP); + ANL(); + +#ifdef WEBRTC_IOS + // Should fail + TEST_MUSTPASS(!netw->GetLocalIP(NULL, 0)); MARK(); + TEST_ERROR(VE_FUNC_NOT_SUPPORTED); + + ANL(); + printf("NOTE: Local IP must be set in source code (line %d) \n", + __LINE__ + 1); + const char* localIP = "192.168.1.4"; + +#else + // Must be big enough so that we can print an IPv6 address. + char localIP[256] = {0}; + + // invalid parameter + TEST_MUSTPASS(!netw->GetLocalIP(NULL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // default function calls (IPv4) + TEST_MUSTPASS(netw->GetLocalIP(localIP)); + MARK(); + TEST_LOG("[local IPv4: %s]\n", localIP); + TEST_MUSTPASS(netw->GetLocalIP(localIP)); + MARK(); + +#if !defined(WEBRTC_MAC) && !defined(WEBRTC_ANDROID) + // default function calls (IPv6) + TEST_MUSTPASS(netw->GetLocalIP(localIP, true)); + MARK(); + TEST_LOG("[local IPv6: %s]\n", localIP); + TEST_MUSTPASS(netw->GetLocalIP(localIP, true)); + MARK(); +#endif + + // one last call to ensure that local + TEST_MUSTPASS(netw->GetLocalIP(localIP)); + MARK(); +#endif + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetLocalIP + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetSourceInfo + // + // - VE initialized + // - no existing channels + TEST(GetSourceInfo); + ANL(); + + int rtpPort(0); + int rtcpPort(0); + char ipaddr[64] = { 0 }; + ExtendedTestTransport* ptrTransport(NULL); + + // call without valid channel + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // NULL as input string + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, NULL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // call when external transport is enabled + ptrTransport = new ExtendedTestTransport(netw); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + delete ptrTransport; + + // call when external transport is disabled (no packet received yet) + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + // send and receive packets with default settings for a while + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime2); // does not guarantee RTCP + + // verify remote parameters (exclude RTCP) + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // ensure that valid results are maintained after StopListen + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // verify that results are maintained after new call to SetLocalReceiver + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // STATE: not listening, not sending + // send and receive packets with other settings for a while + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 9005)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // STATE: listening, sending + + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9005); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // restart sending to and from local IP + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 9005, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9005); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); // should not be "127.0.0.1" + + // use non-default source port in outgoing packets + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 9005)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, "127.0.0.1", 9010)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9010); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // STATE: listening and sending using an extra local socket + + // stop/start sending + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify that the unique source port is maintained for the extra socket + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9010); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // set new source port for outgoing packets (9010 -> 9020) + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 9005, "127.0.0.1", 9020)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); +#ifdef WEBRTC_IOS + SleepMs(500); // Need extra pause for some reason +#endif + + // verify that the unique source port is set for the new extra socket + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 9020); + // STATE: listening and sending using an extra local socket + + // remove extra send socket and restart call again + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); // delete channel => destroys the + // extra socket + TEST_MUSTPASS(voe_base_->CreateChannel()); // new channel uses one socket only + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); // use new port as well + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + // verify that remote info is correct + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 8000); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // STATE: listening and sending using shared socket + + // use non-default source port in outgoing packets to create extra send + // socket + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 7000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 7000, "127.0.0.1", 7010)); + // RTP src is 7010 => RTCP src = 7011 + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + // verify new remote parameters + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 7010); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + + // check RTCP port as well (should be 7010 + 1 = 7011) + Sleep(8000, true); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 7010); + TEST_MUSTPASS(rtcpPort != 7011); + TEST_MUSTPASS(strcmp(ipaddr, "127.0.0.1") != 0); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetSourceInfo + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ // >> SetExternalTransport // // - VE initialized @@ -4581,54 +5271,127 @@ int VoEExtendedTest::TestNetwork() { TEST(SetExternalTransport); ANL(); - ExtendedTestTransport* ptrTransport = new ExtendedTestTransport(voe_network); + ptrTransport = new ExtendedTestTransport(netw); // call without valid channel - TEST_MUSTPASS(!voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(!netw->DeRegisterExternalTransport(0)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); // different valid call combinations - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); - TEST_MUSTPASS(!voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); // must deregister first - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); // STATE: external transport is disabled + + // initialize sending and ensure that external transport can't be enabled + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 1234, "127.0.0.2")); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); + MARK(); + TEST_ERROR(VE_SEND_SOCKETS_CONFLICT); + + // restart channel to ensure that "initialized sender" state is cleared + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // initialize receiving and ensure that external transport can't be enabled + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 5678)); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); + MARK(); + TEST_ERROR(VE_RECEIVE_SOCKETS_CONFLICT); + + // restart channel to ensure that "initialized receiver" state is cleared TEST_MUSTPASS(voe_base_->DeleteChannel(0)); TEST_MUSTPASS(voe_base_->CreateChannel()); // enable external transport and verify that "emulated loopback" works - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); TEST_MUSTPASS(voe_base_->StartSend(0)); // should only start recording - TEST_MUSTPASS(!voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); // should fail - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); - TEST_MUSTPASS(voe_network ->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); MARK(); Play(0, 2000, true, true); // play file as mic and verify loopback audio - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); + // STATE: external transport is disabled +#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) + int testError = VE_FUNC_NOT_SUPPORTED; +#else + int testError = VE_EXTERNAL_TRANSPORT_ENABLED; +#endif + + // check all APIs that should fail when external transport is enabled + int DSCP, priority, serviceType, overrideDSCP, nBytes(0); + bool useSetSockopt, enabled; + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); + MARK(); + TEST_MUSTPASS(!voe_base_->SetLocalReceiver(0, 12345)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!voe_base_->GetLocalReceiver(0, rtpPort, rtcpPort, ipaddr)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!voe_base_->GetSendDestination(0, rtpPort, ipaddr, rtpPort, + rtcpPort)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->EnableIPv6(0)) + TEST_ERROR(testError); + TEST_MUSTPASS(netw->IPv6IsEnabled(0) != false) + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345, 12346)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(!netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + // modified i VoE 3.4 (can be called also for external transport) TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StopReceive(0)); +#if (!defined(_WIN32) && !defined(WEBRTC_LINUX) && !defined(WEBRTC_MAC)) || \ + defined(WEBRTC_EXTERNAL_TRANSPORT) + testError = VE_FUNC_NOT_SUPPORTED; +#else + testError = VE_EXTERNAL_TRANSPORT_ENABLED; +#endif + TEST_MUSTPASS(!netw->SetSendTOS(0, 0)); + TEST_ERROR(testError); + TEST_MUSTPASS(!netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_ERROR(testError); +#if !defined(_WIN32) || defined(WEBRTC_EXTERNAL_TRANSPORT) + testError = VE_FUNC_NOT_SUPPORTED; +#else + testError = VE_EXTERNAL_TRANSPORT_ENABLED; +#endif + TEST_MUSTPASS(!netw->SetSendGQoS(0, false, 0)); + TEST_ERROR(testError); + TEST_MUSTPASS(!netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_ERROR(testError); + char dummy[1] = { 'a' }; + TEST_MUSTPASS(!netw->SendUDPPacket(0, dummy, 1, nBytes)); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + // always disable external transport before deleting the Transport object; // will lead to crash for RTCP transmission otherwise - TEST_MUSTPASS(voe_network ->DeRegisterExternalTransport(0)); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); MARK(); delete ptrTransport; @@ -4643,6 +5406,350 @@ int VoEExtendedTest::TestNetwork() { // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ + // >> EnableIPv6 + // + // - VE initialized + // - no existing channels + // - no media + // - NOTE: set _ENABLE_IPV6_TESTS_ to include these tests + // - http://www.microsoft.com/resources/documentation/windows/xp/all/ + // proddocs/en-us/sag_ip_v6_pro_rt_enable.mspx?mfr=true + // >> ipv6 install + // >> ipv6 [-v] if [IfIndex] + // >> ping6 ::1 + // >> ping6 fe80::1 + +#ifdef _ENABLE_IPV6_TESTS_ + + TEST(EnableIPv6); ANL(); + + // call without valid channel + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // call with enabled external transport + ptrTransport = new ExtendedTestTransport(netw); + TEST_MUSTPASS(netw->RegisterExternalTransport(0, *ptrTransport)); + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); + TEST_ERROR(VE_EXTERNAL_TRANSPORT_ENABLED); + TEST_MUSTPASS(netw->DeRegisterExternalTransport(0)); + delete ptrTransport; + + // Test "locking" to IPv4 + TEST_MUSTPASS(netw->IPv6IsEnabled(0)); MARK(); // After this call we cannot + // enable IPv6 + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); // Should fail + + // Check that IPv6 address is invalid + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 8000, "::1")); MARK(); // fail + + // New channel + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // valid default call + TEST_MUSTPASS(netw->EnableIPv6(0)); MARK(); + TEST_MUSTPASS(netw->GetLocalIP(localIP)); MARK(); // should still read IPv4 + TEST_LOG("[local IPv4: %s]", localIP); + + // ensure that Ipv6 is enabled + TEST_MUSTPASS(netw->IPv6IsEnabled(0) != true); + + // check that IPv4 address is invalid + TEST_MUSTPASS(!voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); + TEST_ERROR(VE_INVALID_IP_ADDRESS); + + // verify usage of IPv6 loopback address + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + // IPv6 loopback address is 0:0:0:0:0:0:0:1 + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "::1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(!netw->EnableIPv6(0)); MARK(); // Should fail + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); + ANL(); + + // Restart channel + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); + + TEST_MUSTPASS(netw->EnableIPv6(0)); MARK(); + // ensure that Ipv6 is enabled + TEST_MUSTPASS(netw->IPv6IsEnabled(0) != true); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + // IPv6 loopback address is 0:0:0:0:0:0:0:1 + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "::1")); + TEST_MUSTPASS(voe_base_->StartPlayout(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + file->StartPlayingFileAsMicrophone(0, _mgr.AudioFilename(), true, + true); + SleepMs(500); // ensure that we receieve some packets + + // SetSourceFilter and GetSourceFilter + TEST(SetSourceFilter and GetSourceFilter for IPv6); ANL(); + char sourceIp[64] = + { 0}; + char filterIp[64] = + { 0}; + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, sourceIp)); + TEST_LOG("Source port: %d \n", rtpPort); + TEST_LOG("Source RTCP port: %d \n", rtcpPort); + TEST_LOG("Source IP: %s \n", sourceIp); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_LOG("Filter port RTP: %d \n", rtpPort); + TEST_LOG("Filter port RTCP: %d \n", rtcpPort); + TEST_LOG("Filter IP: %s \n", filterIp); + TEST_MUSTPASS(0 != rtpPort); + TEST_MUSTPASS(0 != rtcpPort); + TEST_MUSTPASS(filterIp[0] != '\0'); + TEST_LOG("Set filter IP to %s => should hear audio\n", sourceIp); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, sourceIp)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(0 != rtpPort); + TEST_MUSTPASS(0 != rtcpPort); + TEST_MUSTPASS(_stricmp(filterIp, sourceIp)); + SleepMs(1500); + TEST_LOG("Set filter IP to ::10:10:10 => should *not* hear audio\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::10:10:10")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(_stricmp(filterIp, "::10:10:10")); + SleepMs(1500); + TEST_LOG("Disable IP filter => should hear audio again\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::0")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(_stricmp(filterIp, "::")); + SleepMs(1500); + TEST_LOG("Set filter IP to ::10:10:10 => should *not* hear audio\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::10:10:10")); + SleepMs(1500); + TEST_LOG("Disable IP filter => should hear audio again\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(filterIp[0] != '\0'); + SleepMs(1500); + TEST_LOG("Set filter IP to ::10:10:10 => should *not* hear audio\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::10:10:10")); + SleepMs(1500); + TEST_LOG("Disable IP filter => should hear audio again\n"); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "::")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, filterIp)); + TEST_MUSTPASS(_stricmp(filterIp, "::")); + SleepMs(1500); + + file->StopPlayingFileAsMicrophone(0); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + +#endif // #ifdef _ENABLE_IPV6_TESTS_ + // >> end of EnableIPv6 + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSourceFilter + // + // - VE initialized + // - no existing channels + // - no media + TEST(SetSourceFilter); + ANL(); + + // call without valid channel + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // invalid parameters + TEST_MUSTPASS(!netw->SetSourceFilter(0, 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345, 65536)); + MARK(); + TEST_ERROR(VE_INVALID_PORT_NMBR); + TEST_MUSTPASS(!netw->SetSourceFilter(0, 12345, 12346, "300.300.300.300")); + MARK(); + TEST_ERROR(VE_INVALID_IP_ADDRESS); + + // STATE: RTP filter port is 12345, RTCP filter port is 12346 + + // disable all filters and ensure that media is received + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + MARK(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 2000); + TEST_MUSTPASS(rtcpPort != 2001); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); + + // clear states and restart loopback session + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); // clear source info state + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // set RTP filter to port 2002 and verify that source 2000 is blocked + TEST_MUSTPASS(netw->SetSourceFilter(0, 2002, 0, NULL));; + MARK(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // ensure that received packets originates from 2002 and that they now pass + // the filter + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + // RTP source is 2002 + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2002, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2002, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 2002); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); + + // clear states and restart loopback session + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); // clear source info state + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // set IP filter to local IP and verify that default loopback stream is + // blocked + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, localIP));; + MARK(); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // ensure that received packets originates from the local IP and that they + // now pass the filter + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + // should pass the filter + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 2000, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 2000, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + SleepMs(sleepTime); + TEST_MUSTPASS(netw->GetSourceInfo(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 2000); + TEST_MUSTPASS(strcmp(ipaddr, localIP) != 0); + + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + + // STATE: no active media, IP filter is active + + // disable all filters + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL));; + MARK(); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of SetSourceFilter + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> GetSourceFilter + // + // - VE initialized + // - no existing channels + // - no media + TEST(GetSourceFilter); + ANL(); + + // call without valid channel + TEST_MUSTPASS(!netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // invalid input parameters + TEST_MUSTPASS(!netw->GetSourceFilter(0, rtpPort, rtcpPort, NULL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // valid call without any filter set + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + // STATE: no active media and no enabled filters + + // set different filters and verify that they "bite" + TEST_MUSTPASS(netw->SetSourceFilter(0, 54321, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 54321); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtpPort != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 15425, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtcpPort != 15425); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(rtcpPort != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "192.168.199.19")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "192.168.199.19") != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, "0.0.0.0")); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "0.0.0.0") != 0); + TEST_MUSTPASS(netw->SetSourceFilter(0, 0, 0, NULL)); + TEST_MUSTPASS(netw->GetSourceFilter(0, rtpPort, rtcpPort, ipaddr)); + MARK(); + TEST_MUSTPASS(strcmp(ipaddr, "") != 0); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); + AOK(); + ANL(); + ANL(); + + // >> end of GetSourceFilter + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ // >> RegisterDeadOrAliveObserver // >> DeRegisterDeadOrAliveObserver // @@ -4655,24 +5762,24 @@ int VoEExtendedTest::TestNetwork() { ANL(); // call without valid channel - TEST_MUSTPASS(!voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(!netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); - TEST_MUSTPASS(voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); - TEST_MUSTPASS(!voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(!netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); // already registered TEST_ERROR(VE_INVALID_OPERATION); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); // OK to do it again - TEST_MUSTPASS(voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); TEST_MUSTPASS(voe_base_->DeleteChannel(0)); @@ -4691,43 +5798,39 @@ int VoEExtendedTest::TestNetwork() { // - no media // call without valid channel - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(0, false)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); // Invalid paramters - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 0)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(0, true, 0)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 151)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(0, true, 151)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); - TEST_MUSTPASS(!voe_network ->SetPeriodicDeadOrAliveStatus(1, true, 10)); + TEST_MUSTPASS(!netw->SetPeriodicDeadOrAliveStatus(1, true, 10)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); int sampleTime(0); - bool enabled; // Valid parameters - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 1)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 1)); MARK(); - TEST_MUSTPASS( - voe_network ->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); + TEST_MUSTPASS(netw->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(sampleTime != 1); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 150)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 150)); MARK(); - TEST_MUSTPASS( - voe_network ->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); + TEST_MUSTPASS(netw->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(sampleTime != 150); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); MARK(); - TEST_MUSTPASS( - voe_network ->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); + TEST_MUSTPASS(netw->GetPeriodicDeadOrAliveStatus(0, enabled, sampleTime)); TEST_MUSTPASS(enabled != false); TEST_MUSTPASS(sampleTime != 150); // ensure last set time isnt modified @@ -4736,25 +5839,25 @@ int VoEExtendedTest::TestNetwork() { // STATE: full duplex media is active // test the dead-or-alive mechanism - TEST_MUSTPASS(voe_network ->RegisterDeadOrAliveObserver(0, *this)); + TEST_MUSTPASS(netw->RegisterDeadOrAliveObserver(0, *this)); MARK(); TEST_LOG("\nVerify that Alive callbacks are received (dT=2sec): "); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 2)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 2)); SleepMs(6000); TEST_LOG("\nChange dT to 1 second: "); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 1)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 1)); SleepMs(6000); TEST_LOG("\nDisable dead-or-alive callbacks: "); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); SleepMs(6000); TEST_LOG("\nStop sending and enable callbacks again.\n"); TEST_LOG("Verify that Dead callbacks are received (dT=2sec): "); fflush(NULL); TEST_MUSTPASS(voe_base_->StopSend(0)); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, true, 2)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, true, 2)); SleepMs(6000); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_LOG("\nRestart sending.\n"); @@ -4763,8 +5866,8 @@ int VoEExtendedTest::TestNetwork() { SleepMs(6000); TEST_LOG("\nDisable dead-or-alive callbacks."); fflush(NULL); - TEST_MUSTPASS(voe_network ->SetPeriodicDeadOrAliveStatus(0, false)); - TEST_MUSTPASS(voe_network ->DeRegisterDeadOrAliveObserver(0)); + TEST_MUSTPASS(netw->SetPeriodicDeadOrAliveStatus(0, false)); + TEST_MUSTPASS(netw->DeRegisterDeadOrAliveObserver(0)); MARK(); StopMedia(0); @@ -4795,47 +5898,47 @@ int VoEExtendedTest::TestNetwork() { ANL(); // call without existing valid channel - TEST_MUSTPASS(!voe_network ->SetPacketTimeoutNotification(0, false)); + TEST_MUSTPASS(!netw->SetPacketTimeoutNotification(0, false)); MARK(); TEST_ERROR(VE_CHANNEL_NOT_VALID); TEST_MUSTPASS(voe_base_->CreateChannel()); // invalid function calls - TEST_MUSTPASS(!voe_network ->SetPacketTimeoutNotification(0, true, 0)); + TEST_MUSTPASS(!netw->SetPacketTimeoutNotification(0, true, 0)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); - TEST_MUSTPASS(!voe_network ->SetPacketTimeoutNotification(0, true, 151)); + TEST_MUSTPASS(!netw->SetPacketTimeoutNotification(0, true, 151)); MARK(); TEST_ERROR(VE_INVALID_ARGUMENT); // valid function calls (no active media) - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, true, 2)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, true, 2)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(timeOut != 2); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, false)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, false)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != false); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, true, 10)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, true, 10)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(timeOut != 10); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, true, 2)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, true, 2)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != true); TEST_MUSTPASS(timeOut != 2); - TEST_MUSTPASS(voe_network ->SetPacketTimeoutNotification(0, false)); + TEST_MUSTPASS(netw->SetPacketTimeoutNotification(0, false)); MARK(); - TEST_MUSTPASS(voe_network ->GetPacketTimeoutNotification(0, enabled, timeOut)); + TEST_MUSTPASS(netw->GetPacketTimeoutNotification(0, enabled, timeOut)); MARK(); TEST_MUSTPASS(enabled != false); @@ -4844,18 +5947,521 @@ int VoEExtendedTest::TestNetwork() { AOK(); ANL(); ANL(); - return 0; -} + // >> end of SetPacketTimeoutNotification // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ + // >> SendUDPPacket + // + // - VE initialized + // - no existing channels + // - no media + + + // >> end of SendUDPPacket + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSendTOS + // + // - VE initialized + // - no existing channels + // - no media + TEST(SetSendTOS); + ANL(); +#if defined(_WIN32) || defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) + + // call without existing valid channel + + TEST_MUSTPASS(!netw->SetSendTOS(0, 0)); MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // trivial invalid function calls + TEST_MUSTPASS(!netw->SetSendTOS(0, -1)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 64)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, -2)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, 8)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendTOS(0, 1)); MARK(); + TEST_ERROR(VE_SOCKET_ERROR); // must create sockets first + +#ifdef _WIN32 + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 3000)); + + // enable ToS using SetSockopt (should work without local binding) + TEST_MUSTPASS(netw->SetSendTOS(0, 1, -1, true)); MARK(); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 1); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != true); + + // try to disable SetSockopt while ToS is enabled (should fail) + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, -1, false)); MARK(); + TEST_ERROR(VE_TOS_INVALID); // must disable ToS before enabling SetSockopt + + // disable ToS to be able to stop using SetSockopt + TEST_MUSTPASS(netw->SetSendTOS(0, 0, -1, true)); MARK(); // disable ToS + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 0); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != true); + + // to use the "non-SetSockopt" method, local binding is required, + // trying without it should fail + TEST_MUSTPASS(!netw->SetSendTOS(0, 1, -1, false)); MARK(); + TEST_ERROR(VE_TOS_ERROR); // must bind to local IP first + + // bind to local IP and try again (should work this time) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345, kVoEDefault, localIP)); + TEST_LOG("\nThis test needs to be run as administrator\n"); + TEST_MUSTPASS(netw->SetSendTOS(0, 1, -1, false)); MARK(); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 1); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != false); + + // STATE: binded to local IP, local port is 12345 and DSCP is 1 (not using + // SetSockopt) + + // verify loopback audio with the current settings + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + +#ifdef _SEND_TO_REMOTE_IP_ + // Send to remote destination and verify the DSCP using Wireshark. + // Use filter ip.src == "RemoteIP". + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP at the " + "remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each DSCP below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + TEST_LOG(" DSCP is set to 0x%02x\n", 1); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 2)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x\n", DSCP); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 63)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x\n", DSCP); + SleepMs(100); + + // stop and resume sending + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x\n", DSCP); + SleepMs(100); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 0)); +#endif // _SEND_TO_REMOTE_IP_ + // Windows priority tests (priority cannot be set using setsockopt on Win) + TEST_LOG("Testing priority\n"); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(!netw->SetSendTOS(0, 0, 3, true)); // Should fail + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(netw->SetSendTOS(0, 0, 3, false)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 1, 3, false)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + TEST_MUSTPASS(voe_base_->CreateChannel()); +#endif // _WIN32 + // STATE: no media, disabled ToS, no defined receiver + + // Repeat tests above but using setsockopt() this time. + // Binding to local IP should not be required. + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345, kVoEDefault)); + TEST_MUSTPASS(netw->SetSendTOS(0, 10, -1, true)); MARK(); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); MARK(); + TEST_MUSTPASS(DSCP != 10); + TEST_MUSTPASS(priority != 0); + TEST_MUSTPASS(useSetSockopt != true); + + // STATE: *not* binded to local IP, local port is 12345 and DSCP is 10 + // (using SetSockopt) + + // verify loopback audio with the current settings + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + +#ifdef _SEND_TO_REMOTE_IP_ + // Send to remote destination and verify the DSCP using Wireshark. + // Use filter ip.src == "RemoteIP". + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP at the" + " remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each DSCP below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 20, -1, true)); // use setsockopt() + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + + // Change the DSCP while sending is active and verify on remote side. + TEST_MUSTPASS(netw->SetSendTOS(0, 61, -1, true)); // use setsockopt() + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + + // stop and resume sending + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + TEST_MUSTPASS(netw->GetSendTOS(0, DSCP, priority, useSetSockopt)); + TEST_LOG(" DSCP is set to 0x%02x (setsockopt)\n", DSCP); + SleepMs(100); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 0, -1, true)); +#endif // _SEND_TO_REMOTE_IP_ +#if defined(WEBRTC_LINUX) + // Linux priority tests (using setsockopt) + TEST_LOG("Testing priority\n"); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 0, 3, true)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(netw->SetSendTOS(0, 1, 3, true)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + Play(0, 2000, true, true); // file should be played out here... +#endif // #if defined(WEBRTC_LINUX) +#if !defined(_WIN32) && !defined(WEBRTC_LINUX) + // Fail tests for other than Wind and Linux + TEST_MUSTPASS(!netw->SetSendTOS(0, 0, 3, false)); // Should fail + TEST_ERROR(VE_INVALID_ARGUMENT); +#endif // #if !defined(_WIN32) && !defined(WEBRTC_LINUX) + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); AOK(); ANL(); ANL(); + + // END #if defined(_WIN32) || defined(WEBRTC_MAC) || defined(WEBRTC_LINUX) +#else + TEST_LOG("Skipping ToS tests - _WIN32, LINUX, MAC is not defined or " + "WEBRTC_ANDROID is defined"); +#endif + + // >> end of SetSendTOS + // ------------------------------------------------------------------------ + + // ------------------------------------------------------------------------ + // >> SetSendGQoS (Windows only) + // + // - VE initialized + // - no existing channels + // - no media + // + // From qos.h: + // + // #define SERVICETYPE_NOTRAFFIC 0x00000000 + // #define SERVICETYPE_BESTEFFORT 0x00000001 (*) + // #define SERVICETYPE_CONTROLLEDLOAD 0x00000002 (*) + // #define SERVICETYPE_GUARANTEED 0x00000003 (*) + // #define SERVICETYPE_NETWORK_UNAVAILABLE 0x00000004 + // #define SERVICETYPE_GENERAL_INFORMATION 0x00000005 + // #define SERVICETYPE_NOCHANGE 0x00000006 + // #define SERVICETYPE_NONCONFORMING 0x00000009 + // #define SERVICETYPE_NETWORK_CONTROL 0x0000000A + // #define SERVICETYPE_QUALITATIVE 0x0000000D (*) + // + // #define SERVICE_BESTEFFORT 0x80010000 + // #define SERVICE_CONTROLLEDLOAD 0x80020000 + // #define SERVICE_GUARANTEED 0x80040000 + // #define SERVICE_QUALITATIVE 0x80200000 + // + // (*) supported in WEBRTC VoE + TEST(SetSendGQoS); + ANL(); +#ifdef _WIN32 + + // call without existing valid channel + TEST_MUSTPASS(!netw->SetSendGQoS(0, false, 0)); MARK(); + TEST_ERROR(VE_CHANNEL_NOT_VALID); + + TEST_MUSTPASS(voe_base_->CreateChannel()); + + // supported service type but no sockets + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_ERROR(VE_SOCKETS_NOT_INITED); + + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + + // supported service type but sender is not initialized + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_ERROR(VE_DESTINATION_NOT_INITED); + + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); + + // invalid service types + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NOTRAFFIC)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NETWORK_UNAVAILABLE)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_GENERAL_INFORMATION)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NOCHANGE)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NONCONFORMING)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_NETWORK_CONTROL)); + MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_BESTEFFORT)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_CONTROLLEDLOAD)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_GUARANTEED)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICE_QUALITATIVE)); MARK(); + TEST_ERROR(VE_INVALID_ARGUMENT); + + // Is ToS enabled here? + + // Settings which don't require binding to local IP + + // set SERVICETYPE_BESTEFFORT + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_BESTEFFORT); + TEST_MUSTPASS(overrideDSCP != false); + + // set SERVICETYPE_CONTROLLEDLOAD + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_CONTROLLEDLOAD)); + MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_CONTROLLEDLOAD); + TEST_MUSTPASS(overrideDSCP != false); + + // set SERVICETYPE_GUARANTEED + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_GUARANTEED)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_GUARANTEED); + TEST_MUSTPASS(overrideDSCP != false); + + // set SERVICETYPE_QUALITATIVE + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_QUALITATIVE)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != true); + TEST_MUSTPASS(serviceType != SERVICETYPE_QUALITATIVE); + TEST_MUSTPASS(overrideDSCP != false); + + // disable GQoS + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); MARK(); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + MARK(); + TEST_MUSTPASS(enabled != false); + TEST_MUSTPASS(serviceType != SERVICETYPE_QUALITATIVE); + TEST_MUSTPASS(overrideDSCP != false); + + // STATE: diabled QGoS, sockets exists, sending side is initialized, no media + + // Loopback tests using the four different GQoS settings + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); MARK(); + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + ANL(); + TEST_LOG("[SERVICETYPE_BESTEFFORT]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_CONTROLLEDLOAD)); MARK(); + ANL(); + TEST_LOG("[SERVICETYPE_CONTROLLEDLOAD]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_GUARANTEED)); MARK(); + ANL(); + TEST_LOG("[SERVICETYPE_GUARANTEED]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_QUALITATIVE)); MARK(); + ANL(); + TEST_LOG("[SERVICETYPE_QUALITATIVE]"); + Play(0, 2000, true, true); // file should be played out here... + +#ifdef _SEND_TO_REMOTE_IP_ + // Send to remote destination and verify the DSCP mapping using Wireshark. + // Use filter ip.src == "RemoteIP". + + // Modify the send destination on the fly + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP mapping at" + " the remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each GQoS setting below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT (0x%02x), should " + "be mapped to DSCP = 0x00\n", serviceType); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_CONTROLLEDLOAD)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_CONTROLLEDLOAD (0x%02x), " + "should be mapped to DSCP = 0x18\n", serviceType); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_LOG(" QoS is disabled, should give DSCP = 0x%02x\n", 0); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_GUARANTEED)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_GUARANTEED (0x%02x), should " + "be mapped to DSCP = 0x28\n", serviceType); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_QUALITATIVE)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_QUALITATIVE (0x%02x), should" + " be mapped to DSCP = 0x00\n", serviceType); + SleepMs(100); +#endif // _SEND_TO_REMOTE_IP_ + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + + // STATE: sockets exists, sending side is initialized, no media + + // Repeat test above but this time using overrideDSCP. + + // Some initial loopack tests. + // NOTE - override DSCP requres binding to local IP. + + // should not work since QoS is enabled + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 3)); + MARK(); + TEST_ERROR(VE_TOS_GQOS_CONFLICT); + + // disble QoS and try to override again (should fail again since local + // binding is not done yet) + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_MUSTPASS(!netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 3)); + MARK(); + TEST_ERROR(VE_GQOS_ERROR); + + // make proper settings and try again (should work this time) + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345, kVoEDefault, localIP)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, localIP)); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 3)); + MARK(); + + // Now, let's try some loopback tests using override DSCP + + TEST_MUSTPASS(voe_base_->StartReceive(0)); + TEST_MUSTPASS(voe_base_->StartSend(0)); + ANL(); + TEST_LOG("[overrideDSCP=3]"); + Play(0, 2000, true, true); // file should be played out here... + + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 17)); + MARK(); + ANL(); + TEST_LOG("[overrideDSCP=17]"); + Play(0, 2000, true, true); // file should be played out here... + + // And finally, send to remote side as well to verify that the new mapping + // works as it should. + +#ifdef _SEND_TO_REMOTE_IP_ + // Modify the send destination on the fly + TEST_MUSTPASS(voe_base_->SetSendDestination(0, RemotePort, RemoteIP)); + + TEST_LOG("\nUse Wireshark and verify a correctly received DSCP mapping at" + " the remote side!\n"); + TEST_LOG("Sending approx. 5 packets to %s:%d for each GQoS setting below:\n", + RemoteIP, RemotePort); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 18)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 62)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 32)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, true, SERVICETYPE_BESTEFFORT, 1)); + TEST_MUSTPASS(netw->GetSendGQoS(0, enabled, serviceType, overrideDSCP)); + TEST_LOG(" serviceType is set to SERVICETYPE_BESTEFFORT, should be " + "overrided to DSCP = 0x%02x\n", overrideDSCP); + SleepMs(100); + TEST_MUSTPASS(netw->SetSendGQoS(0, false, 0)); + TEST_LOG(" QoS is disabled, should give DSCP = 0x%02x\n", 0); + SleepMs(100); +#endif // _SEND_TO_REMOTE_IP_ + TEST_MUSTPASS(voe_base_->StopReceive(0)); + TEST_MUSTPASS(voe_base_->StopSend(0)); + + TEST_MUSTPASS(voe_base_->DeleteChannel(0)); + ANL(); AOK(); ANL(); ANL(); + +#else + TEST_LOG("Skipping GQoS tests - _WIN32 is not defined"); +#endif // #ifdef _WIN32 + // >> end of SetSendGQoS + // ------------------------------------------------------------------------ + + if (file) { + file->StopPlayingFileAsMicrophone(0); + } + voe_base_->StopSend(0); + voe_base_->StopPlayout(0); + voe_base_->StopReceive(0); + voe_base_->DeleteChannel(0); + voe_base_->Terminate(); + + ANL(); + AOK(); + return 0; +} + // ---------------------------------------------------------------------------- // VoEExtendedTest::TestRTP_RTCP // ---------------------------------------------------------------------------- // Used to validate packets during the RTP audio level indication test. class RTPAudioTransport: public Transport { - public: +public: + RTPAudioTransport() : mute_(false) { } @@ -4906,6 +6512,7 @@ class RTPAudioTransport: public Transport { assert(vad == 0 || vad == 1); assert(level >= 0 && level <= 127); } + return 0; } @@ -4914,7 +6521,7 @@ class RTPAudioTransport: public Transport { return 0; } - private: +private: bool mute_; }; @@ -4951,13 +6558,8 @@ int VoEExtendedTest::TestRTP_RTCP() { TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -5060,12 +6662,8 @@ int VoEExtendedTest::TestRTP_RTCP() { TEST_MUSTPASS(voe_base_->DeleteChannel(1)); TEST_MUSTPASS(voe_base_->CreateChannel()); - - voice_channel_transport.reset(new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -5074,7 +6672,7 @@ int VoEExtendedTest::TestRTP_RTCP() { ANL(); // ------------------------------------------------------------------------ - // >> SetLocalSSRC + // >> InsertExtraRTPPacket int i(0); @@ -5092,6 +6690,58 @@ int VoEExtendedTest::TestRTP_RTCP() { true, true)); // ------------------------------------------------------------------------ + // >> InsertExtraRTPPacket + TEST(InsertExtraRTPPacket); + ANL(); + + const char payloadData[8] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }; + + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(-1, 0, false, + payloadData, 8)); + MARK(); // invalid channel + TEST_ERROR(VE_CHANNEL_NOT_VALID); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, -1, false, + payloadData, 8)); + MARK(); // invalid payload type + TEST_ERROR(VE_INVALID_PLTYPE); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 128, false, + payloadData, 8)); + MARK(); // invalid payload type + TEST_ERROR(VE_INVALID_PLTYPE); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 99, false, + NULL, 8)); + MARK(); // invalid pointer + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 99, false, + payloadData, 1500-28+1)); + MARK(); // invalid size + TEST_ERROR(VE_INVALID_ARGUMENT); + TEST_MUSTPASS(voe_base_->StopSend(0)); + TEST_MUSTPASS(-1 != rtp_rtcp->InsertExtraRTPPacket(0, 99, false, + payloadData, 8)); + MARK(); // not sending + TEST_ERROR(VE_NOT_SENDING); + TEST_MUSTPASS(voe_base_->StartSend(0)); + TEST_MUSTPASS(file->StartPlayingFileAsMicrophone(0, _mgr.AudioFilename(), + true, true)); + + SleepMs(1000); + for (int p = 0; p < 128; p++) { + TEST_MUSTPASS(rtp_rtcp->InsertExtraRTPPacket(0, p, false, + payloadData, 8)); + MARK(); + TEST_MUSTPASS(rtp_rtcp->InsertExtraRTPPacket(0, p, true, + payloadData, 8)); + MARK(); + } + + // Ensure we have sent all extra packets before we move forward to avoid + //incorrect error code + SleepMs(1000); + + ANL(); + + // ------------------------------------------------------------------------ // >> RTP dump APIs TEST(Start/StopRtpDump); ANL(); @@ -5229,12 +6879,8 @@ int VoEExtendedTest::TestRTP_RTCP() { SleepMs(100); TEST_MUSTPASS(voe_base_->CreateChannel()); - - voice_channel_transport.reset(new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); @@ -5480,12 +7126,8 @@ int VoEExtendedTest::TestRTP_RTCP() { // We have to re-register the audio codec payload type as stopReceive will // clean the database TEST_MUSTPASS(codec->SetRecPayloadType(0, cinst)); - - voice_channel_transport.reset(new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 8000); - voice_channel_transport->SetLocalReceiver(8000); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 8000)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 8000, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -5521,7 +7163,6 @@ int VoEExtendedTest::TestVideoSync() VoEBase* voe_base_ = _mgr.BasePtr(); VoEVideoSync* vsync = _mgr.VideoSyncPtr(); - VoENetwork* network = _mgr.NetworkPtr(); // check if this interface is supported if (!vsync) @@ -5545,13 +7186,8 @@ int VoEExtendedTest::TestVideoSync() TEST_MUSTPASS(voe_base_->Init()); TEST_MUSTPASS(voe_base_->CreateChannel()); - - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(network, 0)); - - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); - + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); @@ -5629,7 +7265,6 @@ int VoEExtendedTest::TestVolumeControl() VoEBase* voe_base_ = _mgr.BasePtr(); VoEVolumeControl* volume = _mgr.VolumeControlPtr(); - VoENetwork* network = _mgr.NetworkPtr(); #ifdef _TEST_FILE_ VoEFile* file = _mgr.FilePtr(); #endif @@ -5661,10 +7296,8 @@ int VoEExtendedTest::TestVolumeControl() TEST_MUSTPASS(hardware->SetPlayoutDevice(0)); #endif #endif - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(network, 0)); - voice_channel_transport->SetSendDestination("127.0.0.1", 12345); - voice_channel_transport->SetLocalReceiver(12345); + TEST_MUSTPASS(voe_base_->SetLocalReceiver(0, 12345)); + TEST_MUSTPASS(voe_base_->SetSendDestination(0, 12345, "127.0.0.1")); TEST_MUSTPASS(voe_base_->StartReceive(0)); TEST_MUSTPASS(voe_base_->StartPlayout(0)); TEST_MUSTPASS(voe_base_->StartSend(0)); diff --git a/voice_engine/test/auto_test/voe_extended_test.h b/voice_engine/test/auto_test/voe_extended_test.h index af549f81..c685d885 100644 --- a/voice_engine/test/auto_test/voe_extended_test.h +++ b/voice_engine/test/auto_test/voe_extended_test.h @@ -12,14 +12,7 @@ #define WEBRTC_VOICE_ENGINE_VOE_EXTENDED_TEST_H #include "voe_standard_test.h" -#include "webrtc/modules/audio_device/include/audio_device.h" -#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" -#include "webrtc/system_wrappers/interface/event_wrapper.h" -#include "webrtc/system_wrappers/interface/ref_count.h" -#include "webrtc/system_wrappers/interface/sleep.h" -#include "webrtc/system_wrappers/interface/thread_wrapper.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" +#include "modules/audio_device/include/audio_device.h" namespace voetest { @@ -432,22 +425,20 @@ class VoEExtendedTest : public VoiceEngineObserver, int TestRTP_RTCP(); int TestVideoSync(); int TestVolumeControl(); - + public: int ErrorCode() const { return _errCode; } void ClearErrorCode() { _errCode = 0; } - protected: // from VoiceEngineObserver void CallbackOnError(const int errCode, const int channel); void CallbackOnTrace(const TraceLevel level, const char* message, const int length); - + protected: // from VoEConnectionObserver void OnPeriodicDeadOrAlive(const int channel, const bool alive); - private: void Play(int channel, unsigned int timeMillisec, bool addFileAsMicrophone = false, bool addTimeMarker = false); @@ -457,12 +448,12 @@ class VoEExtendedTest : public VoiceEngineObserver, int RunMixingTest(int num_remote_channels, int num_local_channels, int16_t input_value, int16_t max_output_value, int16_t min_output_value); - + private: VoETestManager& _mgr; + private: int _errCode; bool _alive; bool _listening[32]; - scoped_ptr<webrtc::VoiceChannelTransport> voice_channel_transports_[32]; bool _playing[32]; bool _sending[32]; }; diff --git a/voice_engine/test/auto_test/voe_stress_test.cc b/voice_engine/test/auto_test/voe_stress_test.cc index 519bf838..c9219131 100644 --- a/voice_engine/test/auto_test/voe_stress_test.cc +++ b/voice_engine/test/auto_test/voe_stress_test.cc @@ -23,12 +23,10 @@ #endif #include "webrtc/voice_engine/test/auto_test/voe_stress_test.h" +#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/sleep.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" #include "webrtc/voice_engine/voice_engine_defines.h" // defines build macros using namespace webrtc; @@ -124,7 +122,6 @@ int VoEStressTest::StartStopTest() { // Get sub-API pointers VoEBase* base = _mgr.BasePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); // Set trace // VALIDATE_STRESS(base->SetTraceFileName( @@ -150,12 +147,9 @@ int VoEStressTest::StartStopTest() { printf("Test will take approximately %d minutes. \n", numberOfLoops * loopSleep / 1000 / 60 + 1); - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(voe_network, 0)); - for (i = 0; i < numberOfLoops; ++i) { - voice_channel_transport->SetSendDestination("127.0.0.1", 4800); - voice_channel_transport->SetLocalReceiver(4800); + VALIDATE_STRESS(base->SetLocalReceiver(0, 4800)); + VALIDATE_STRESS(base->SetSendDestination(0, 4800, "127.0.0.1")); VALIDATE_STRESS(base->StartReceive(0)); VALIDATE_STRESS(base->StartPlayout(0)); VALIDATE_STRESS(base->StartSend(0)); @@ -168,9 +162,8 @@ int VoEStressTest::StartStopTest() { } ANL(); - VALIDATE_STRESS(voice_channel_transport->SetSendDestination("127.0.0.1", - 4800)); - VALIDATE_STRESS(voice_channel_transport->SetLocalReceiver(4800)); + VALIDATE_STRESS(base->SetLocalReceiver(0, 4800)); + VALIDATE_STRESS(base->SetSendDestination(0, 4800, "127.0.0.1")); VALIDATE_STRESS(base->StartReceive(0)); VALIDATE_STRESS(base->StartPlayout(0)); VALIDATE_STRESS(base->StartSend(0)); diff --git a/voice_engine/test/auto_test/voe_unit_test.cc b/voice_engine/test/auto_test/voe_unit_test.cc index 8c4a7fbf..b152aabf 100644 --- a/voice_engine/test/auto_test/voe_unit_test.cc +++ b/voice_engine/test/auto_test/voe_unit_test.cc @@ -248,17 +248,13 @@ int VoEUnitTest::StartMedia(int channel, int rtpPort, bool listen, bool playout, bool send, bool fileAsMic, bool localFile) { VoEBase* base = _mgr.BasePtr(); VoEFile* file = _mgr.FilePtr(); - VoENetwork* voe_network = _mgr.NetworkPtr(); _listening[channel] = false; _playing[channel] = false; _sending[channel] = false; - voice_channel_transports_[channel].reset( - new VoiceChannelTransport(voe_network, channel)); - - CHECK(voice_channel_transports_[channel]->SetLocalReceiver(rtpPort)); - CHECK(voice_channel_transports_[channel]->SetSendDestination("127.0.0.1", - rtpPort)); + + CHECK(base->SetLocalReceiver(channel, rtpPort)); + CHECK(base->SetSendDestination(channel, rtpPort, "127.0.0.1")); if (listen) { _listening[channel] = true; CHECK(base->StartReceive(channel)); diff --git a/voice_engine/test/auto_test/voe_unit_test.h b/voice_engine/test/auto_test/voe_unit_test.h index 8db8d676..346713a1 100644 --- a/voice_engine/test/auto_test/voe_unit_test.h +++ b/voice_engine/test/auto_test/voe_unit_test.h @@ -11,9 +11,7 @@ #ifndef WEBRTC_VOICE_ENGINE_VOE_UNIT_TEST_H #define WEBRTC_VOICE_ENGINE_VOE_UNIT_TEST_H -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/voice_engine/test/auto_test/voe_standard_test.h" +#include "voice_engine/test/auto_test/voe_standard_test.h" namespace voetest { @@ -59,7 +57,6 @@ class VoEUnitTest : public Encryption { bool _listening[32]; bool _playing[32]; bool _sending[32]; - scoped_ptr<webrtc::VoiceChannelTransport> voice_channel_transports_[32]; private: bool _extOnOff; diff --git a/voice_engine/test/cmd_test/voe_cmd_test.cc b/voice_engine/test/cmd_test/voe_cmd_test.cc index d4bfc4b2..2035e4ee 100644 --- a/voice_engine/test/cmd_test/voe_cmd_test.cc +++ b/voice_engine/test/cmd_test/voe_cmd_test.cc @@ -18,6 +18,8 @@ #include <vector> #include "gtest/gtest.h" +#include "test/testsupport/fileutils.h" + #include "voe_errors.h" #include "voe_base.h" #include "voe_codec.h" @@ -33,15 +35,14 @@ #include "voe_network.h" #include "voe_neteq_stats.h" #include "engine_configurations.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/test/udp_transport/include/channel_transport.h" -#include "webrtc/test/testsupport/fileutils.h" // Enable this this flag to run this test with hard coded // IP/Port/codec and start test automatically with key input // it could be useful in repeat tests. //#define DEBUG +// #define EXTERNAL_TRANSPORT + using namespace webrtc; #define VALIDATE \ @@ -69,6 +70,29 @@ VoENetEqStats* neteqst = NULL; void RunTest(std::string out_path); +#ifdef EXTERNAL_TRANSPORT + +class my_transportation : public Transport +{ + int SendPacket(int channel,const void *data,int len); + int SendRTCPPacket(int channel, const void *data, int len); +}; + +int my_transportation::SendPacket(int channel,const void *data,int len) +{ + netw->ReceivedRTPPacket(channel, data, len); + return 0; +} + +int my_transportation::SendRTCPPacket(int channel, const void *data, int len) +{ + netw->ReceivedRTCPPacket(channel, data, len); + return 0; +} + +my_transportation my_transport; +#endif + class MyObserver : public VoiceEngineObserver { public: virtual void CallbackOnError(const int channel, const int err_code); @@ -246,24 +270,44 @@ void RunTest(std::string out_path) { cnt++; int j = 0; +#ifdef EXTERNAL_TRANSPORT + my_transportation ch0transport; + printf("Enabling external transport \n"); + netw->RegisterExternalTransport(0, ch0transport); +#else char ip[64]; #ifdef DEBUG strcpy(ip, "127.0.0.1"); #else + char localip[64]; + netw->GetLocalIP(localip); + printf("local IP:%s\n", localip); + printf("1. 127.0.0.1 \n"); printf("2. Specify IP \n"); ASSERT_EQ(1, scanf("%i", &i)); - if (1 == i) { + if (1 == i) strcpy(ip, "127.0.0.1"); - } else { + else { printf("Specify remote IP: "); ASSERT_EQ(1, scanf("%s", ip)); } #endif - int rPort = 8500; -#ifndef DEBUG + int colons(0); + while (ip[j] != '\0' && j < 64 && !(colons = (ip[j++] == ':'))) + ; + if (colons) { + printf("Enabling IPv6\n"); + res = netw->EnableIPv6(0); + VALIDATE; + } + + int rPort; +#ifdef DEBUG + rPort=8500; +#else printf("Specify remote port (1=1234): "); ASSERT_EQ(1, scanf("%i", &rPort)); if (1 == rPort) @@ -271,24 +315,23 @@ void RunTest(std::string out_path) { printf("Set Send port \n"); #endif - scoped_ptr<VoiceChannelTransport> voice_channel_transport( - new VoiceChannelTransport(netw, chan)); - printf("Set Send IP \n"); - res = voice_channel_transport->SetSendDestination(ip, rPort); + res = base1->SetSendDestination(chan, rPort, ip); VALIDATE; - int lPort = 8500; -#ifndef DEBUG + int lPort; +#ifdef DEBUG + lPort=8500; +#else printf("Specify local port (1=1234): "); ASSERT_EQ(1, scanf("%i", &lPort)); if (1 == lPort) lPort = 1234; printf("Set Rec Port \n"); #endif - - res = voice_channel_transport->SetLocalReceiver(lPort); + res = base1->SetLocalReceiver(chan, lPort); VALIDATE; +#endif printf("\n"); for (i = 0; i < codec->NumOfCodecs(); i++) { @@ -324,19 +367,12 @@ void RunTest(std::string out_path) { #endif int channel_index = 0; std::vector<int> channels(kMaxNumChannels); - std::vector<scoped_ptr<VoiceChannelTransport> > voice_channel_transports; - for (i = 0; i < kMaxNumChannels; ++i) { channels[i] = base1->CreateChannel(); int port = rPort + (i + 1) * 2; - - voice_channel_transports[i].reset( - new VoiceChannelTransport(netw, channels[i])); - - printf("Set Send IP \n"); - res = voice_channel_transports[i]->SetSendDestination(ip, port); + res = base1->SetSendDestination(channels[i], port, ip); VALIDATE; - res = voice_channel_transports[i]->SetLocalReceiver(port); + res = base1->SetLocalReceiver(channels[i], port); VALIDATE; res = codec->SetSendCodec(channels[i], cinst); VALIDATE; diff --git a/voice_engine/test/voice_engine_tests.gypi b/voice_engine/test/voice_engine_tests.gypi index af6cb932..d02ef08f 100644 --- a/voice_engine/test/voice_engine_tests.gypi +++ b/voice_engine/test/voice_engine_tests.gypi @@ -20,7 +20,6 @@ '<(DEPTH)/testing/gmock.gyp:gmock', '<(DEPTH)/third_party/google-gflags/google-gflags.gyp:google-gflags', '<(webrtc_root)/test/libtest/libtest.gyp:libtest', - '<(webrtc_root)/test/udp_transport.gyp:udp_transport', ], 'include_dirs': [ 'auto_test', @@ -60,6 +59,7 @@ 'auto_test/standard/mixing_test.cc', 'auto_test/standard/neteq_stats_test.cc', 'auto_test/standard/neteq_test.cc', + 'auto_test/standard/network_before_streaming_test.cc', 'auto_test/standard/network_test.cc', 'auto_test/standard/rtp_rtcp_before_streaming_test.cc', 'auto_test/standard/rtp_rtcp_test.cc', @@ -102,7 +102,6 @@ '<(DEPTH)/testing/gtest.gyp:gtest', 'voice_engine_core', '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', - '<(webrtc_root)/test/udp_transport.gyp:udp_transport', ], 'sources': [ 'cmd_test/voe_cmd_test.cc', diff --git a/voice_engine/voe_base_impl.cc b/voice_engine/voe_base_impl.cc index 7446c224..864b6da3 100644 --- a/voice_engine/voe_base_impl.cc +++ b/voice_engine/voe_base_impl.cc @@ -683,9 +683,265 @@ int VoEBaseImpl::DeleteChannel(int channel) { return -1; } + return 0; } +int VoEBaseImpl::SetLocalReceiver(int channel, int port, int RTCPport, + const char ipAddr[64], + const char multiCastAddr[64]) +{ + // Inititialize local receive sockets (RTP and RTCP). + // + // The sockets are always first closed and then created again by this + // function call. The created sockets are by default also used for + // transmission (unless source port is set in SetSendDestination). + // + // Note that, sockets can also be created automatically if a user calls + // SetSendDestination and StartSend without having called SetLocalReceiver + // first. The sockets are then created at the first packet transmission. + + CriticalSectionScoped cs(_shared->crit_sec()); + if (ipAddr == NULL && multiCastAddr == NULL) + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d)", + channel, port, RTCPport); + } + else if (ipAddr != NULL && multiCastAddr == NULL) + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d, ipAddr=%s)", + channel, port, RTCPport, ipAddr); + } + else if (ipAddr == NULL && multiCastAddr != NULL) + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d, " + "multiCastAddr=%s)", channel, port, RTCPport, multiCastAddr); + } + else + { + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetLocalReceiver(channel=%d, port=%d, RTCPport=%d, " + "ipAddr=%s, multiCastAddr=%s)", channel, port, RTCPport, ipAddr, + multiCastAddr); + } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if ((port < 0) || (port > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetLocalReceiver() invalid RTP port"); + return -1; + } + if (((RTCPport != kVoEDefault) && (RTCPport < 0)) || ((RTCPport + != kVoEDefault) && (RTCPport > 65535))) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetLocalReceiver() invalid RTCP port"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetLocalReceiver() failed to locate channel"); + return -1; + } + + // Cast RTCP port. In the RTP module 0 corresponds to RTP port + 1 in + // the module, which is the default. + WebRtc_UWord16 rtcpPortUW16(0); + if (RTCPport != kVoEDefault) + { + rtcpPortUW16 = static_cast<WebRtc_UWord16> (RTCPport); + } + + return channelPtr->SetLocalReceiver(port, rtcpPortUW16, ipAddr, + multiCastAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, + kTraceWarning, "SetLocalReceiver() VoE is built for external " + "transport"); + return -1; +#endif +} + +int VoEBaseImpl::GetLocalReceiver(int channel, int& port, int& RTCPport, + char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetLocalReceiver(channel=%d, ipAddr[]=?)", channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetLocalReceiver() failed to locate channel"); + return -1; + } + WebRtc_Word32 ret = channelPtr->GetLocalReceiver(port, RTCPport, ipAddr); + if (ipAddr != NULL) + { + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetLocalReceiver() => port=%d, RTCPport=%d, ipAddr=%s", + port, RTCPport, ipAddr); + } + else + { + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetLocalReceiver() => port=%d, RTCPport=%d", port, RTCPport); + } + return ret; +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetLocalReceiver() VoE is built for external transport"); + return -1; +#endif +} + +int VoEBaseImpl::SetSendDestination(int channel, int port, const char* ipaddr, + int sourcePort, int RTCPport) +{ + WEBRTC_TRACE( + kTraceApiCall, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetSendDestination(channel=%d, port=%d, ipaddr=%s," + "sourcePort=%d, RTCPport=%d)", + channel, port, ipaddr, sourcePort, RTCPport); + CriticalSectionScoped cs(_shared->crit_sec()); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSendDestination() failed to locate channel"); + return -1; + } + if ((port < 0) || (port > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSendDestination() invalid RTP port"); + return -1; + } + if (((RTCPport != kVoEDefault) && (RTCPport < 0)) || ((RTCPport + != kVoEDefault) && (RTCPport > 65535))) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSendDestination() invalid RTCP port"); + return -1; + } + if (((sourcePort != kVoEDefault) && (sourcePort < 0)) || ((sourcePort + != kVoEDefault) && (sourcePort > 65535))) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSendDestination() invalid source port"); + return -1; + } + + // Cast RTCP port. In the RTP module 0 corresponds to RTP port + 1 in the + // module, which is the default. + WebRtc_UWord16 rtcpPortUW16(0); + if (RTCPport != kVoEDefault) + { + rtcpPortUW16 = static_cast<WebRtc_UWord16> (RTCPport); + WEBRTC_TRACE( + kTraceInfo, + kTraceVoice, + VoEId(_shared->instance_id(), channel), + "SetSendDestination() non default RTCP port %u will be " + "utilized", + rtcpPortUW16); + } + + return channelPtr->SetSendDestination(port, ipaddr, sourcePort, + rtcpPortUW16); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSendDestination() VoE is built for external transport"); + return -1; +#endif +} + +int VoEBaseImpl::GetSendDestination(int channel, int& port, char ipAddr[64], + int& sourcePort, int& RTCPport) +{ + WEBRTC_TRACE( + kTraceApiCall, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetSendDestination(channel=%d, ipAddr[]=?, sourcePort=?," + "RTCPport=?)", + channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSendDestination() failed to locate channel"); + return -1; + } + WebRtc_Word32 ret = channelPtr->GetSendDestination(port, ipAddr, + sourcePort, RTCPport); + if (ipAddr != NULL) + { + WEBRTC_TRACE( + kTraceStateInfo, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetSendDestination() => port=%d, RTCPport=%d, ipAddr=%s, " + "sourcePort=%d, RTCPport=%d", + port, RTCPport, ipAddr, sourcePort, RTCPport); + } + else + { + WEBRTC_TRACE( + kTraceStateInfo, + kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetSendDestination() => port=%d, RTCPport=%d, " + "sourcePort=%d, RTCPport=%d", + port, RTCPport, sourcePort, RTCPport); + } + return ret; +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSendDestination() VoE is built for external transport"); + return -1; +#endif +} + int VoEBaseImpl::StartReceive(int channel) { WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), @@ -808,6 +1064,15 @@ int VoEBaseImpl::StartSend(int channel) { return 0; } +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!channelPtr->ExternalTransport() + && !channelPtr->SendSocketsInitialized()) + { + _shared->SetLastError(VE_DESTINATION_NOT_INITED, kTraceError, + "StartSend() must set send destination first"); + return -1; + } +#endif if (StartSend() != 0) { _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError, @@ -880,6 +1145,16 @@ int VoEBaseImpl::GetVersion(char version[1024]) accLen += len; assert(accLen < kVoiceEngineVersionMaxMessageSize); +#ifdef WEBRTC_EXTERNAL_TRANSPORT + len = AddExternalTransportBuild(versionPtr); + if (len == -1) + { + return -1; + } + versionPtr += len; + accLen += len; + assert(accLen < kVoiceEngineVersionMaxMessageSize); +#endif #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT len = AddExternalRecAndPlayoutBuild(versionPtr); if (len == -1) @@ -932,6 +1207,13 @@ WebRtc_Word32 VoEBaseImpl::AddVoEVersion(char* str) const return sprintf(str, "VoiceEngine 4.1.0\n"); } +#ifdef WEBRTC_EXTERNAL_TRANSPORT +WebRtc_Word32 VoEBaseImpl::AddExternalTransportBuild(char* str) const +{ + return sprintf(str, "External transport build\n"); +} +#endif + #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT WebRtc_Word32 VoEBaseImpl::AddExternalRecAndPlayoutBuild(char* str) const { diff --git a/voice_engine/voe_base_impl.h b/voice_engine/voe_base_impl.h index 92f1539d..17c6ed3d 100644 --- a/voice_engine/voe_base_impl.h +++ b/voice_engine/voe_base_impl.h @@ -44,6 +44,25 @@ public: virtual int DeleteChannel(int channel); + virtual int SetLocalReceiver(int channel, int port, + int RTCPport = kVoEDefault, + const char ipAddr[64] = NULL, + const char multiCastAddr[64] = NULL); + + virtual int GetLocalReceiver(int channel, int& port, int& RTCPport, + char ipAddr[64]); + + virtual int SetSendDestination(int channel, int port, + const char ipAddr[64], + int sourcePort = kVoEDefault, + int RTCPport = kVoEDefault); + + virtual int GetSendDestination(int channel, + int& port, + char ipAddr[64], + int& sourcePort, + int& RTCPport); + virtual int StartReceive(int channel); virtual int StartPlayout(int channel); @@ -106,6 +125,9 @@ private: WebRtc_Word32 AddBuildInfo(char* str) const; WebRtc_Word32 AddVoEVersion(char* str) const; +#ifdef WEBRTC_EXTERNAL_TRANSPORT + WebRtc_Word32 AddExternalTransportBuild(char* str) const; +#endif #ifdef WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT WebRtc_Word32 AddExternalRecAndPlayoutBuild(char* str) const; #endif @@ -117,6 +139,7 @@ private: WebRtc_UWord32 _oldMicLevel; AudioFrame _audioFrame; voe::SharedData* _shared; + }; } // namespace webrtc diff --git a/voice_engine/voe_network_impl.cc b/voice_engine/voe_network_impl.cc index 6c4cfc2b..c5639008 100644 --- a/voice_engine/voe_network_impl.cc +++ b/voice_engine/voe_network_impl.cc @@ -170,6 +170,504 @@ int VoENetworkImpl::ReceivedRTCPPacket(int channel, const void* data, return channelPtr->ReceivedRTCPPacket((const WebRtc_Word8*) data, length); } +int VoENetworkImpl::GetSourceInfo(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSourceInfo(channel=%d, rtpPort=?, rtcpPort=?, ipAddr[]=?)", + channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == ipAddr) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetSourceInfo() invalid IP-address buffer"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSourceInfo() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSourceInfo() external transport is enabled"); + return -1; + } + return channelPtr->GetSourceInfo(rtpPort, rtcpPort, ipAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSourceInfo() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetLocalIP(char ipAddr[64], bool ipv6) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetLocalIP(ipAddr[]=?, ipv6=%d)", ipv6); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == ipAddr) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetLocalIP() invalid IP-address buffer"); + return -1; + } + + // Create a temporary socket module to ensure that this method can be + // called also when no channels are created. + WebRtc_UWord8 numSockThreads(1); + UdpTransport* socketPtr = + UdpTransport::Create( + -1, + numSockThreads); + if (NULL == socketPtr) + { + _shared->SetLastError(VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError, + "GetLocalIP() failed to create socket module"); + return -1; + } + + // Use a buffer big enough for IPv6 addresses and initialize it with zeros. + char localIPAddr[256] = {0}; + + if (ipv6) + { + char localIP[16]; + if (socketPtr->LocalHostAddressIPV6(localIP) != 0) + { + _shared->SetLastError(VE_INVALID_IP_ADDRESS, kTraceError, + "GetLocalIP() failed to retrieve local IP - 1"); + UdpTransport::Destroy(socketPtr); + return -1; + } + // Convert 128-bit address to character string (a:b:c:d:e:f:g:h) + sprintf(localIPAddr, + "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x" + "%.2x:%.2x%.2x", + localIP[0], localIP[1], localIP[2], localIP[3], localIP[4], + localIP[5], localIP[6], localIP[7], localIP[8], localIP[9], + localIP[10], localIP[11], localIP[12], localIP[13], + localIP[14], localIP[15]); + } + else + { + WebRtc_UWord32 localIP(0); + // Read local IP (as 32-bit address) from the socket module + if (socketPtr->LocalHostAddress(localIP) != 0) + { + _shared->SetLastError(VE_INVALID_IP_ADDRESS, kTraceError, + "GetLocalIP() failed to retrieve local IP - 2"); + UdpTransport::Destroy(socketPtr); + return -1; + } + // Convert 32-bit address to character string (x.y.z.w) + sprintf(localIPAddr, "%d.%d.%d.%d", (int) ((localIP >> 24) & 0x0ff), + (int) ((localIP >> 16) & 0x0ff), + (int) ((localIP >> 8) & 0x0ff), + (int) (localIP & 0x0ff)); + } + + strcpy(ipAddr, localIPAddr); + + UdpTransport::Destroy(socketPtr); + + WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "GetLocalIP() => ipAddr=%s", ipAddr); + return 0; +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetLocalIP() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::EnableIPv6(int channel) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "EnableIPv6(channel=%d)", channel); + ANDROID_NOT_SUPPORTED(_shared->statistics()); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "EnableIPv6() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "EnableIPv6() external transport is enabled"); + return -1; + } + return channelPtr->EnableIPv6(); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "EnableIPv6() VoE is built for external transport"); + return -1; +#endif +} + +bool VoENetworkImpl::IPv6IsEnabled(int channel) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "IPv6IsEnabled(channel=%d)", channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return false; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "IPv6IsEnabled() failed to locate channel"); + return false; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "IPv6IsEnabled() external transport is enabled"); + return false; + } + return channelPtr->IPv6IsEnabled(); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "IPv6IsEnabled() VoE is built for external transport"); + return false; +#endif +} + +int VoENetworkImpl::SetSourceFilter(int channel, + int rtpPort, + int rtcpPort, + const char ipAddr[64]) +{ + (ipAddr == NULL) ? WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetSourceFilter(channel=%d, rtpPort=%d," + " rtcpPort=%d)", + channel, rtpPort, rtcpPort) + : WEBRTC_TRACE(kTraceApiCall, kTraceVoice, + VoEId(_shared->instance_id(), -1), + "SetSourceFilter(channel=%d, rtpPort=%d," + " rtcpPort=%d, ipAddr=%s)", + channel, rtpPort, rtcpPort, ipAddr); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if ((rtpPort < 0) || (rtpPort > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSourceFilter() invalid RTP port"); + return -1; + } + if ((rtcpPort < 0) || (rtcpPort > 65535)) + { + _shared->SetLastError(VE_INVALID_PORT_NMBR, kTraceError, + "SetSourceFilter() invalid RTCP port"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSourceFilter() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSourceFilter() external transport is enabled"); + return -1; + } + return channelPtr->SetSourceFilter(rtpPort, rtcpPort, ipAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSourceFilter() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetSourceFilter(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSourceFilter(channel=%d, rtpPort=?, rtcpPort=?, " + "ipAddr[]=?)", + channel); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == ipAddr) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "GetSourceFilter() invalid IP-address buffer"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSourceFilter() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSourceFilter() external transport is enabled"); + return -1; + } + return channelPtr->GetSourceFilter(rtpPort, rtcpPort, ipAddr); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSourceFilter() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::SetSendTOS(int channel, + int DSCP, + int priority, + bool useSetSockopt) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SetSendTOS(channel=%d, DSCP=%d, useSetSockopt=%d)", + channel, DSCP, useSetSockopt); + +#if !defined(_WIN32) && !defined(WEBRTC_LINUX) && !defined(WEBRTC_MAC) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "SetSendTOS() is not supported on this platform"); + return -1; +#endif + +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if ((DSCP < 0) || (DSCP > 63)) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() Invalid DSCP value"); + return -1; + } +#if defined(_WIN32) || defined(WEBRTC_LINUX) + if ((priority < -1) || (priority > 7)) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() Invalid priority value"); + return -1; + } +#else + if (-1 != priority) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() priority not supported"); + return -1; + } +#endif +#if defined(_WIN32) + if ((priority >= 0) && useSetSockopt) + { + // On Windows, priority and useSetSockopt cannot be combined + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SetSendTOS() priority and useSetSockopt conflict"); + return -1; + } +#endif + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSendTOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSendTOS() external transport is enabled"); + return -1; + } +#if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) + useSetSockopt = true; + WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1), + " force useSetSockopt=true since there is no alternative" + " implementation"); +#endif + + return channelPtr->SetSendTOS(DSCP, priority, useSetSockopt); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSendTOS() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetSendTOS(int channel, + int& DSCP, + int& priority, + bool& useSetSockopt) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSendTOS(channel=%d)", channel); + +#if !defined(_WIN32) && !defined(WEBRTC_LINUX) && !defined(WEBRTC_MAC) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "GetSendTOS() is not supported on this platform"); + return -1; +#endif +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSendTOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSendTOS() external transport is enabled"); + return -1; + } + return channelPtr->GetSendTOS(DSCP, priority, useSetSockopt); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSendTOS() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::SetSendGQoS(int channel, + bool enable, + int serviceType, + int overrideDSCP) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SetSendGQOS(channel=%d, enable=%d, serviceType=%d," + " overrideDSCP=%d)", + channel, (int) enable, serviceType, overrideDSCP); + ANDROID_NOT_SUPPORTED(_shared->statistics()); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#if !defined(_WIN32) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "SetSendGQOS() is not supported on this platform"); + return -1; +#elif !defined(WEBRTC_EXTERNAL_TRANSPORT) + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SetSendGQOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "SetSendGQOS() external transport is enabled"); + return -1; + } + return channelPtr->SetSendGQoS(enable, serviceType, overrideDSCP); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SetSendGQOS() VoE is built for external transport"); + return -1; +#endif +} + +int VoENetworkImpl::GetSendGQoS(int channel, + bool& enabled, + int& serviceType, + int& overrideDSCP) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "GetSendGQOS(channel=%d)", channel); + ANDROID_NOT_SUPPORTED(_shared->statistics()); + IPHONE_NOT_SUPPORTED(_shared->statistics()); +#if !defined(_WIN32) + _shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceWarning, + "GetSendGQOS() is not supported on this platform"); + return -1; +#elif !defined(WEBRTC_EXTERNAL_TRANSPORT) + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "GetSendGQOS() failed to locate channel"); + return -1; + } + if (channelPtr->ExternalTransport()) + { + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError, + "GetSendGQOS() external transport is enabled"); + return -1; + } + return channelPtr->GetSendGQoS(enabled, serviceType, overrideDSCP); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "GetSendGQOS() VoE is built for external transport"); + return -1; +#endif +} + int VoENetworkImpl::SetPacketTimeoutNotification(int channel, bool enable, int timeoutSeconds) @@ -323,6 +821,52 @@ int VoENetworkImpl::GetPeriodicDeadOrAliveStatus(int channel, sampleTimeSeconds); } +int VoENetworkImpl::SendUDPPacket(int channel, + const void* data, + unsigned int length, + int& transmittedBytes, + bool useRtcpSocket) +{ + WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1), + "SendUDPPacket(channel=%d, data=0x%x, length=%u, useRTCP=%d)", + channel, data, length, useRtcpSocket); +#ifndef WEBRTC_EXTERNAL_TRANSPORT + if (!_shared->statistics().Initialized()) + { + _shared->SetLastError(VE_NOT_INITED, kTraceError); + return -1; + } + if (NULL == data) + { + _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError, + "SendUDPPacket() invalid data buffer"); + return -1; + } + if (0 == length) + { + _shared->SetLastError(VE_INVALID_PACKET, kTraceError, + "SendUDPPacket() invalid packet size"); + return -1; + } + voe::ScopedChannel sc(_shared->channel_manager(), channel); + voe::Channel* channelPtr = sc.ChannelPtr(); + if (channelPtr == NULL) + { + _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError, + "SendUDPPacket() failed to locate channel"); + return -1; + } + return channelPtr->SendUDPPacket(data, + length, + transmittedBytes, + useRtcpSocket); +#else + _shared->SetLastError(VE_EXTERNAL_TRANSPORT_ENABLED, kTraceWarning, + "SendUDPPacket() VoE is built for external transport"); + return -1; +#endif +} + #endif // WEBRTC_VOICE_ENGINE_NETWORK_API } // namespace webrtc diff --git a/voice_engine/voe_network_impl.h b/voice_engine/voe_network_impl.h index 4dbe4f32..b159c81b 100644 --- a/voice_engine/voe_network_impl.h +++ b/voice_engine/voe_network_impl.h @@ -34,6 +34,47 @@ public: const void* data, unsigned int length); + virtual int GetSourceInfo(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]); + + virtual int GetLocalIP(char ipAddr[64], bool ipv6 = false); + + virtual int EnableIPv6(int channel); + + virtual bool IPv6IsEnabled(int channel); + + virtual int SetSourceFilter(int channel, + int rtpPort, + int rtcpPort, + const char ipAddr[64] = 0); + + virtual int GetSourceFilter(int channel, + int& rtpPort, + int& rtcpPort, + char ipAddr[64]); + + virtual int SetSendTOS(int channel, + int DSCP, + int priority = -1, + bool useSetSockopt = false); + + virtual int GetSendTOS(int channel, + int& DSCP, + int& priority, + bool& useSetSockopt); + + virtual int SetSendGQoS(int channel, + bool enable, + int serviceType, + int overrideDSCP); + + virtual int GetSendGQoS(int channel, + bool& enabled, + int& serviceType, + int& overrideDSCP); + virtual int SetPacketTimeoutNotification(int channel, bool enable, int timeoutSeconds = 2); @@ -55,6 +96,12 @@ public: bool& enabled, int& sampleTimeSeconds); + virtual int SendUDPPacket(int channel, + const void* data, + unsigned int length, + int& transmittedBytes, + bool useRtcpSocket = false); + protected: VoENetworkImpl(voe::SharedData* shared); virtual ~VoENetworkImpl(); diff --git a/voice_engine/voice_engine_core.gypi b/voice_engine/voice_engine_core.gypi index 21bfca41..1c28c0d4 100644 --- a/voice_engine/voice_engine_core.gypi +++ b/voice_engine/voice_engine_core.gypi @@ -20,6 +20,7 @@ '<(webrtc_root)/modules/modules.gyp:audio_processing', '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', + '<(webrtc_root)/modules/modules.gyp:udp_transport', '<(webrtc_root)/modules/modules.gyp:webrtc_utility', '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', ], @@ -133,6 +134,7 @@ '<(webrtc_root)/modules/modules.gyp:audio_conference_mixer', '<(webrtc_root)/modules/modules.gyp:media_file', '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', + '<(webrtc_root)/modules/modules.gyp:udp_transport', '<(webrtc_root)/modules/modules.gyp:webrtc_utility', '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', ], |