Creating a copy of Udp transport under webrtc/test
Adding a test namespace, updating the include paths and renamed folder name. Review URL: https://webrtc-codereview.appspot.com/1203004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3701 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
2cec0b1670
commit
999e900fb6
@ -31,6 +31,7 @@
|
||||
'dependencies': [
|
||||
'webrtc/test/metrics.gyp:*',
|
||||
'webrtc/test/test.gyp:*',
|
||||
'webrtc/test/channel_transport.gyp:*',
|
||||
'webrtc/tools/tools.gyp:*',
|
||||
'tools/e2e_quality/e2e_quality.gyp:*',
|
||||
],
|
||||
|
67
webrtc/test/channel_transport.gyp
Normal file
67
webrtc/test/channel_transport.gyp
Normal file
@ -0,0 +1,67 @@
|
||||
# Copyright (c) 2013 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.
|
||||
|
||||
{
|
||||
'includes': [
|
||||
'../build/common.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'channel_transport',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
|
||||
],
|
||||
'sources': [
|
||||
# PLATFORM INDEPENDENT SOURCE FILES
|
||||
'channel_transport/channel_transport.cc',
|
||||
'channel_transport/include/channel_transport.h',
|
||||
'channel_transport/udp_transport.h',
|
||||
'channel_transport/udp_transport_impl.cc',
|
||||
'channel_transport/udp_socket_wrapper.cc',
|
||||
'channel_transport/udp_socket_manager_wrapper.cc',
|
||||
'channel_transport/udp_transport_impl.h',
|
||||
'channel_transport/udp_socket_wrapper.h',
|
||||
'channel_transport/udp_socket_manager_wrapper.h',
|
||||
# PLATFORM SPECIFIC SOURCE FILES - Will be filtered below
|
||||
# Posix (Linux/Mac)
|
||||
'channel_transport/udp_socket_posix.cc',
|
||||
'channel_transport/udp_socket_posix.h',
|
||||
'channel_transport/udp_socket_manager_posix.cc',
|
||||
'channel_transport/udp_socket_manager_posix.h',
|
||||
# win
|
||||
'channel_transport/udp_socket2_manager_win.cc',
|
||||
'channel_transport/udp_socket2_manager_win.h',
|
||||
'channel_transport/udp_socket2_win.cc',
|
||||
'channel_transport/udp_socket2_win.h',
|
||||
'channel_transport/traffic_control_win.cc',
|
||||
'channel_transport/traffic_control_win.h',
|
||||
], # source
|
||||
},
|
||||
{
|
||||
'target_name': 'channel_transport_unittests',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'channel_transport',
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
'<(DEPTH)/testing/gmock.gyp:gmock',
|
||||
'<(webrtc_root)/test/test.gyp:test_support_main',
|
||||
],
|
||||
'sources': [
|
||||
'channel_transport/udp_transport_unittest.cc',
|
||||
'channel_transport/udp_socket_manager_unittest.cc',
|
||||
'channel_transport/udp_socket_wrapper_unittest.cc',
|
||||
],
|
||||
# Disable warnings to enable Win64 build, issue 1323.
|
||||
'msvs_disabled_warnings': [
|
||||
4267, # size_t to int truncation.
|
||||
],
|
||||
}, # channel_transport_unittests
|
||||
], # targets
|
||||
}
|
113
webrtc/test/channel_transport/channel_transport.cc
Normal file
113
webrtc/test/channel_transport/channel_transport.cc
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/test/channel_transport/include/channel_transport.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "webrtc/test/channel_transport/udp_transport.h"
|
||||
#include "webrtc/video_engine/include/vie_network.h"
|
||||
#include "webrtc/voice_engine/include/voe_network.h"
|
||||
#include "webrtc/video_engine/vie_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
VoiceChannelTransport::VoiceChannelTransport(VoENetwork* voe_network,
|
||||
int channel)
|
||||
: channel_(channel),
|
||||
voe_network_(voe_network) {
|
||||
WebRtc_UWord8 socket_threads = 1;
|
||||
socket_transport_ = UdpTransport::Create(channel, socket_threads);
|
||||
EXPECT_EQ(0, voe_network_->RegisterExternalTransport(channel,
|
||||
*socket_transport_));
|
||||
}
|
||||
|
||||
VoiceChannelTransport::~VoiceChannelTransport() {
|
||||
voe_network_->DeRegisterExternalTransport(channel_);
|
||||
UdpTransport::Destroy(socket_transport_);
|
||||
}
|
||||
|
||||
void VoiceChannelTransport::IncomingRTPPacket(
|
||||
const WebRtc_Word8* incoming_rtp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/) {
|
||||
voe_network_->ReceivedRTPPacket(channel_, incoming_rtp_packet, packet_length);
|
||||
}
|
||||
|
||||
void VoiceChannelTransport::IncomingRTCPPacket(
|
||||
const WebRtc_Word8* incoming_rtcp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/) {
|
||||
voe_network_->ReceivedRTCPPacket(channel_, incoming_rtcp_packet,
|
||||
packet_length);
|
||||
}
|
||||
|
||||
int VoiceChannelTransport::SetLocalReceiver(WebRtc_UWord16 rtp_port) {
|
||||
return socket_transport_->InitializeReceiveSockets(this, rtp_port);
|
||||
}
|
||||
|
||||
int VoiceChannelTransport::SetSendDestination(const char* ip_address,
|
||||
WebRtc_UWord16 rtp_port) {
|
||||
return socket_transport_->InitializeSendSockets(ip_address, rtp_port);
|
||||
}
|
||||
|
||||
|
||||
VideoChannelTransport::VideoChannelTransport(ViENetwork* vie_network,
|
||||
int channel)
|
||||
: channel_(channel),
|
||||
vie_network_(vie_network) {
|
||||
WebRtc_UWord8 socket_threads = 1;
|
||||
socket_transport_ = UdpTransport::Create(channel, socket_threads);
|
||||
EXPECT_EQ(0, vie_network_->RegisterSendTransport(channel,
|
||||
*socket_transport_));
|
||||
}
|
||||
|
||||
VideoChannelTransport::~VideoChannelTransport() {
|
||||
vie_network_->DeregisterSendTransport(channel_);
|
||||
UdpTransport::Destroy(socket_transport_);
|
||||
}
|
||||
|
||||
void VideoChannelTransport::IncomingRTPPacket(
|
||||
const WebRtc_Word8* incoming_rtp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/) {
|
||||
vie_network_->ReceivedRTPPacket(channel_, incoming_rtp_packet, packet_length);
|
||||
}
|
||||
|
||||
void VideoChannelTransport::IncomingRTCPPacket(
|
||||
const WebRtc_Word8* incoming_rtcp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/) {
|
||||
vie_network_->ReceivedRTCPPacket(channel_, incoming_rtcp_packet,
|
||||
packet_length);
|
||||
}
|
||||
|
||||
int VideoChannelTransport::SetLocalReceiver(WebRtc_UWord16 rtp_port) {
|
||||
int return_value = socket_transport_->InitializeReceiveSockets(this,
|
||||
rtp_port);
|
||||
if (return_value == 0) {
|
||||
return socket_transport_->StartReceiving(kViENumReceiveSocketBuffers);
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
int VideoChannelTransport::SetSendDestination(const char* ip_address,
|
||||
WebRtc_UWord16 rtp_port) {
|
||||
return socket_transport_->InitializeSendSockets(ip_address, rtp_port);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
89
webrtc/test/channel_transport/include/channel_transport.h
Normal file
89
webrtc/test/channel_transport/include/channel_transport.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_INCLUDE_CHANNEL_TRANSPORT_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_INCLUDE_CHANNEL_TRANSPORT_H_
|
||||
|
||||
#include "webrtc/test/channel_transport/udp_transport.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ViENetwork;
|
||||
class VoENetwork;
|
||||
|
||||
namespace test {
|
||||
|
||||
// Helper class for VoiceEngine tests.
|
||||
class VoiceChannelTransport : public UdpTransportData {
|
||||
public:
|
||||
VoiceChannelTransport(VoENetwork* voe_network, int channel);
|
||||
|
||||
virtual ~VoiceChannelTransport();
|
||||
|
||||
// Start implementation of UdpTransportData.
|
||||
void IncomingRTPPacket(const WebRtc_Word8* incoming_rtp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/);
|
||||
|
||||
void IncomingRTCPPacket(const WebRtc_Word8* incoming_rtcp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/);
|
||||
// End implementation of UdpTransportData.
|
||||
|
||||
// Specifies the ports to receive RTP packets on.
|
||||
int SetLocalReceiver(WebRtc_UWord16 rtp_port);
|
||||
|
||||
// Specifies the destination port and IP address for a specified channel.
|
||||
int SetSendDestination(const char* ip_address, WebRtc_UWord16 rtp_port);
|
||||
|
||||
private:
|
||||
int channel_;
|
||||
VoENetwork* voe_network_;
|
||||
UdpTransport* socket_transport_;
|
||||
};
|
||||
|
||||
// Helper class for VideoEngine tests.
|
||||
class VideoChannelTransport : public UdpTransportData {
|
||||
public:
|
||||
VideoChannelTransport(ViENetwork* vie_network, int channel);
|
||||
|
||||
virtual ~VideoChannelTransport();
|
||||
|
||||
// Start implementation of UdpTransportData.
|
||||
void IncomingRTPPacket(const WebRtc_Word8* incoming_rtp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/);
|
||||
|
||||
void IncomingRTCPPacket(const WebRtc_Word8* incoming_rtcp_packet,
|
||||
const WebRtc_Word32 packet_length,
|
||||
const char* /*from_ip*/,
|
||||
const WebRtc_UWord16 /*from_port*/);
|
||||
// End implementation of UdpTransportData.
|
||||
|
||||
// Specifies the ports to receive RTP packets on.
|
||||
int SetLocalReceiver(WebRtc_UWord16 rtp_port);
|
||||
|
||||
// Specifies the destination port and IP address for a specified channel.
|
||||
int SetSendDestination(const char* ip_address, WebRtc_UWord16 rtp_port);
|
||||
|
||||
private:
|
||||
int channel_;
|
||||
ViENetwork* vie_network_;
|
||||
UdpTransport* socket_transport_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_INCLUDE_CHANNEL_TRANSPORT_H_
|
||||
|
257
webrtc/test/channel_transport/traffic_control_win.cc
Normal file
257
webrtc/test/channel_transport/traffic_control_win.cc
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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 "webrtc/test/channel_transport/traffic_control_win.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
TrafficControlWindows* TrafficControlWindows::instance = NULL;
|
||||
WebRtc_UWord32 TrafficControlWindows::refCounter = 0;
|
||||
|
||||
TrafficControlWindows::TrafficControlWindows(const WebRtc_Word32 id) : _id(id)
|
||||
{
|
||||
}
|
||||
|
||||
TrafficControlWindows* TrafficControlWindows::GetInstance(
|
||||
const WebRtc_Word32 id)
|
||||
{
|
||||
if(instance != NULL)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceDebug,
|
||||
kTraceTransport,
|
||||
id,
|
||||
"TrafficControlWindows - Returning already created object");
|
||||
refCounter++;
|
||||
return instance;
|
||||
}
|
||||
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
|
||||
"TrafficControlWindows - Creating new object");
|
||||
instance = new TrafficControlWindows(id);
|
||||
if(instance == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
|
||||
"TrafficControlWindows - Error allocating memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
instance->tcRegister = NULL;
|
||||
instance->tcDeregister = NULL;
|
||||
|
||||
instance->tcEnumerate = NULL;
|
||||
instance->tcOpenInterface = NULL;
|
||||
instance->tcCloseInterface = NULL;
|
||||
|
||||
instance->tcAddFlow = NULL;
|
||||
instance->tcDeleteFlow = NULL;
|
||||
|
||||
instance->tcAddFilter = NULL;
|
||||
instance->tcDeleteFilter = NULL;
|
||||
|
||||
HMODULE trafficLib = LoadLibrary(TEXT("traffic.dll"));
|
||||
if(trafficLib == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceWarning,
|
||||
kTraceTransport,
|
||||
id,
|
||||
"TrafficControlWindows - No QOS support, LoadLibrary returned NULL,\
|
||||
last error: %d\n",
|
||||
GetLastError());
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
instance->tcRegister = (registerFn)GetProcAddress(trafficLib,
|
||||
"TcRegisterClient");
|
||||
instance->tcDeregister = (deregisterFn)GetProcAddress(trafficLib,
|
||||
"TcDeregisterClient");
|
||||
instance->tcEnumerate = (enumerateFn)GetProcAddress(
|
||||
trafficLib,
|
||||
"TcEnumerateInterfaces");
|
||||
instance->tcOpenInterface = (openInterfaceFn)GetProcAddress(
|
||||
trafficLib,
|
||||
"TcOpenInterfaceW");
|
||||
instance->tcCloseInterface = (closeInterfaceFn)GetProcAddress(
|
||||
trafficLib,
|
||||
"TcCloseInterface");
|
||||
instance->tcAddFlow = (flowAddFn)GetProcAddress(trafficLib,
|
||||
"TcAddFlow");
|
||||
instance->tcDeleteFlow = (flowDeleteFn)GetProcAddress(trafficLib,
|
||||
"TcDeleteFlow");
|
||||
|
||||
instance->tcAddFilter = (filterAddFn)GetProcAddress(trafficLib,
|
||||
"TcAddFilter");
|
||||
instance->tcDeleteFilter = (filterDeleteFn)GetProcAddress(trafficLib,
|
||||
"TcDeleteFilter");
|
||||
|
||||
if(instance->tcRegister == NULL ||
|
||||
instance->tcDeregister == NULL ||
|
||||
instance->tcEnumerate == NULL ||
|
||||
instance->tcOpenInterface == NULL ||
|
||||
instance->tcCloseInterface == NULL ||
|
||||
instance->tcAddFlow == NULL ||
|
||||
instance->tcAddFilter == NULL ||
|
||||
instance->tcDeleteFlow == NULL ||
|
||||
instance->tcDeleteFilter == NULL)
|
||||
{
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
id,
|
||||
"TrafficControlWindows - Could not find function pointer for\
|
||||
traffic control functions");
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
id,
|
||||
"Tcregister : %x, tcDeregister: %x, tcEnumerate: %x,\
|
||||
tcOpenInterface: %x, tcCloseInterface: %x, tcAddFlow: %x, tcAddFilter: %x,\
|
||||
tcDeleteFlow: %x, tcDeleteFilter: %x",
|
||||
instance->tcRegister,
|
||||
instance->tcDeregister,
|
||||
instance->tcEnumerate,
|
||||
instance->tcOpenInterface,
|
||||
instance->tcCloseInterface,
|
||||
instance->tcAddFlow,
|
||||
instance->tcAddFilter,
|
||||
instance->tcDeleteFlow,
|
||||
instance->tcDeleteFilter );
|
||||
return NULL;
|
||||
}
|
||||
refCounter++;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void TrafficControlWindows::Release(TrafficControlWindows* gtc)
|
||||
{
|
||||
if (0 == refCounter)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceError, kTraceTransport, -1,
|
||||
"TrafficControlWindows - Cannot release, refCounter is 0");
|
||||
return;
|
||||
}
|
||||
if (NULL == gtc)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, -1,
|
||||
"TrafficControlWindows - Not releasing, gtc is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, gtc->_id,
|
||||
"TrafficControlWindows - Releasing object");
|
||||
refCounter--;
|
||||
if ((0 == refCounter) && instance)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, gtc->_id,
|
||||
"TrafficControlWindows - Deleting object");
|
||||
delete instance;
|
||||
instance = NULL;
|
||||
}
|
||||
}
|
||||
WebRtc_Word32 TrafficControlWindows::ChangeUniqueId(const WebRtc_Word32 id)
|
||||
{
|
||||
_id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ULONG TrafficControlWindows::TcRegisterClient(
|
||||
ULONG TciVersion,
|
||||
HANDLE ClRegCtx,
|
||||
PTCI_CLIENT_FUNC_LIST ClientHandlerList,
|
||||
PHANDLE pClientHandle)
|
||||
{
|
||||
assert(tcRegister != NULL);
|
||||
|
||||
return tcRegister(TciVersion, ClRegCtx, ClientHandlerList, pClientHandle);
|
||||
}
|
||||
|
||||
ULONG TrafficControlWindows::TcDeregisterClient(HANDLE clientHandle)
|
||||
{
|
||||
assert(tcDeregister != NULL);
|
||||
|
||||
return tcDeregister(clientHandle);
|
||||
}
|
||||
|
||||
|
||||
ULONG TrafficControlWindows::TcEnumerateInterfaces(
|
||||
HANDLE ClientHandle,
|
||||
PULONG pBufferSize,
|
||||
PTC_IFC_DESCRIPTOR interfaceBuffer)
|
||||
{
|
||||
assert(tcEnumerate != NULL);
|
||||
|
||||
return tcEnumerate(ClientHandle, pBufferSize, interfaceBuffer);
|
||||
}
|
||||
|
||||
|
||||
ULONG TrafficControlWindows::TcOpenInterfaceW(LPWSTR pInterfaceName,
|
||||
HANDLE ClientHandle,
|
||||
HANDLE ClIfcCtx,
|
||||
PHANDLE pIfcHandle)
|
||||
{
|
||||
assert(tcOpenInterface != NULL);
|
||||
|
||||
return tcOpenInterface(pInterfaceName, ClientHandle, ClIfcCtx, pIfcHandle);
|
||||
|
||||
}
|
||||
|
||||
ULONG TrafficControlWindows::TcCloseInterface(HANDLE IfcHandle)
|
||||
{
|
||||
assert(tcCloseInterface != NULL);
|
||||
|
||||
return tcCloseInterface(IfcHandle);
|
||||
}
|
||||
|
||||
ULONG TrafficControlWindows::TcAddFlow(HANDLE IfcHandle, HANDLE ClFlowCtx,
|
||||
ULONG Flags, PTC_GEN_FLOW pGenericFlow,
|
||||
PHANDLE pFlowHandle)
|
||||
{
|
||||
assert(tcAddFlow != NULL);
|
||||
return tcAddFlow(IfcHandle, ClFlowCtx, Flags, pGenericFlow, pFlowHandle);
|
||||
}
|
||||
|
||||
ULONG TrafficControlWindows::TcAddFilter(HANDLE FlowHandle,
|
||||
PTC_GEN_FILTER pGenericFilter,
|
||||
PHANDLE pFilterHandle)
|
||||
{
|
||||
assert(tcAddFilter != NULL);
|
||||
return tcAddFilter(FlowHandle, pGenericFilter, pFilterHandle);
|
||||
}
|
||||
|
||||
ULONG TrafficControlWindows::TcDeleteFlow(HANDLE FlowHandle)
|
||||
{
|
||||
assert(tcDeleteFlow != NULL);
|
||||
return tcDeleteFlow(FlowHandle);
|
||||
|
||||
}
|
||||
|
||||
ULONG TrafficControlWindows::TcDeleteFilter(HANDLE FilterHandle)
|
||||
{
|
||||
assert(tcDeleteFilter != NULL);
|
||||
return tcDeleteFilter(FilterHandle);
|
||||
}
|
||||
|
||||
void MyClNotifyHandler(HANDLE ClRegCtx, HANDLE ClIfcCtx, ULONG Event,
|
||||
HANDLE SubCode, ULONG BufSize, PVOID Buffer)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
102
webrtc/test/channel_transport/traffic_control_win.h
Normal file
102
webrtc/test/channel_transport/traffic_control_win.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_TRAFFIC_CONTROL_WINDOWS_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_TRAFFIC_CONTROL_WINDOWS_H_
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
// Disable deprication warning from traffic.h
|
||||
#pragma warning(disable : 4995)
|
||||
|
||||
#include <windows.h>
|
||||
#include <qos.h>
|
||||
#include <ntddndis.h>
|
||||
#include <traffic.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
void MyClNotifyHandler(HANDLE ClRegCtx, HANDLE ClIfcCtx, ULONG Event,
|
||||
HANDLE SubCode, ULONG BufSize, PVOID Buffer);
|
||||
|
||||
|
||||
typedef ULONG (WINAPI *registerFn)(ULONG, HANDLE, PTCI_CLIENT_FUNC_LIST,
|
||||
PHANDLE);
|
||||
typedef ULONG (WINAPI *deregisterFn)(HANDLE);
|
||||
typedef ULONG (WINAPI *enumerateFn)(HANDLE, PULONG, PTC_IFC_DESCRIPTOR);
|
||||
typedef ULONG (WINAPI *openInterfaceFn)(LPWSTR, HANDLE, HANDLE, PHANDLE);
|
||||
typedef ULONG (WINAPI *closeInterfaceFn)(HANDLE);
|
||||
typedef ULONG (WINAPI *flowAddFn)(HANDLE, HANDLE, ULONG, PTC_GEN_FLOW, PHANDLE);
|
||||
typedef ULONG (WINAPI *filterAddFn)(HANDLE, PTC_GEN_FILTER, PHANDLE);
|
||||
typedef ULONG (WINAPI *flowDeleteFn)(HANDLE);
|
||||
typedef ULONG (WINAPI *filterDeleteFn)(HANDLE);
|
||||
|
||||
class TrafficControlWindows
|
||||
{
|
||||
public:
|
||||
// Factory method. Constructor disabled.
|
||||
static TrafficControlWindows* GetInstance(const WebRtc_Word32 id);
|
||||
static void Release(TrafficControlWindows* gtc);
|
||||
|
||||
WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id);
|
||||
|
||||
ULONG TcRegisterClient(ULONG TciVersion, HANDLE ClRegCtx,
|
||||
PTCI_CLIENT_FUNC_LIST ClientHandlerList,
|
||||
PHANDLE pClientHandle);
|
||||
|
||||
ULONG TcDeregisterClient(HANDLE clientHandle);
|
||||
|
||||
ULONG TcEnumerateInterfaces(HANDLE ClientHandle, PULONG pBufferSize,
|
||||
PTC_IFC_DESCRIPTOR interfaceBuffer);
|
||||
|
||||
ULONG TcOpenInterfaceW(LPWSTR pInterfaceName, HANDLE ClientHandle,
|
||||
HANDLE ClIfcCtx, PHANDLE pIfcHandle);
|
||||
|
||||
ULONG TcCloseInterface(HANDLE IfcHandle);
|
||||
|
||||
ULONG TcAddFlow(HANDLE IfcHandle, HANDLE ClFlowCtx, ULONG Flags,
|
||||
PTC_GEN_FLOW pGenericFlow, PHANDLE pFlowHandle);
|
||||
|
||||
ULONG TcAddFilter(HANDLE FlowHandle, PTC_GEN_FILTER pGenericFilter,
|
||||
PHANDLE pFilterHandle);
|
||||
|
||||
ULONG TcDeleteFlow(HANDLE FlowHandle);
|
||||
ULONG TcDeleteFilter(HANDLE FilterHandle);
|
||||
private:
|
||||
TrafficControlWindows(const WebRtc_Word32 id);
|
||||
WebRtc_Word32 _id;
|
||||
TCI_CLIENT_FUNC_LIST QoSFunctions;
|
||||
|
||||
static TrafficControlWindows* instance;
|
||||
|
||||
registerFn tcRegister;
|
||||
deregisterFn tcDeregister;
|
||||
|
||||
enumerateFn tcEnumerate;
|
||||
openInterfaceFn tcOpenInterface;
|
||||
closeInterfaceFn tcCloseInterface;
|
||||
|
||||
flowAddFn tcAddFlow;
|
||||
flowDeleteFn tcDeleteFlow;
|
||||
|
||||
filterAddFn tcAddFilter;
|
||||
filterDeleteFn tcDeleteFilter;
|
||||
|
||||
static WebRtc_UWord32 refCounter;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_TRAFFIC_CONTROL_WINDOWS_H_
|
661
webrtc/test/channel_transport/udp_socket2_manager_win.cc
Normal file
661
webrtc/test/channel_transport/udp_socket2_manager_win.cc
Normal file
@ -0,0 +1,661 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/test/channel_transport/udp_socket2_manager_win.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/aligned_malloc.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket2_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
WebRtc_UWord32 UdpSocket2ManagerWindows::_numOfActiveManagers = 0;
|
||||
bool UdpSocket2ManagerWindows::_wsaInit = false;
|
||||
|
||||
UdpSocket2ManagerWindows::UdpSocket2ManagerWindows()
|
||||
: UdpSocketManager(),
|
||||
_id(-1),
|
||||
_stopped(false),
|
||||
_init(false),
|
||||
_pCrit(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_ioCompletionHandle(NULL),
|
||||
_numActiveSockets(0),
|
||||
_event(EventWrapper::Create())
|
||||
{
|
||||
_managerNumber = _numOfActiveManagers++;
|
||||
|
||||
if(_numOfActiveManagers == 1)
|
||||
{
|
||||
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||
WSADATA wsaData;
|
||||
_wsaInit = WSAStartup(wVersionRequested, &wsaData) == 0;
|
||||
// TODO (hellner): seems safer to use RAII for this. E.g. what happens
|
||||
// if a UdpSocket2ManagerWindows() created and destroyed
|
||||
// without being initialized.
|
||||
}
|
||||
}
|
||||
|
||||
UdpSocket2ManagerWindows::~UdpSocket2ManagerWindows()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocket2ManagerWindows(%d)::~UdpSocket2ManagerWindows()",
|
||||
_managerNumber);
|
||||
|
||||
if(_init)
|
||||
{
|
||||
_pCrit->Enter();
|
||||
if(_numActiveSockets)
|
||||
{
|
||||
_pCrit->Leave();
|
||||
_event->Wait(INFINITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pCrit->Leave();
|
||||
}
|
||||
StopWorkerThreads();
|
||||
|
||||
// All threads are stopped. Safe to delete them.
|
||||
ListItem* pItem = NULL;
|
||||
while((pItem = _workerThreadsList.First()) != NULL)
|
||||
{
|
||||
delete static_cast<UdpSocket2WorkerWindows*>(pItem->GetItem());
|
||||
_workerThreadsList.PopFront();
|
||||
}
|
||||
|
||||
_ioContextPool.Free();
|
||||
|
||||
_numOfActiveManagers--;
|
||||
if(_ioCompletionHandle)
|
||||
{
|
||||
CloseHandle(_ioCompletionHandle);
|
||||
}
|
||||
if (_numOfActiveManagers == 0)
|
||||
{
|
||||
if(_wsaInit)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_pCrit)
|
||||
{
|
||||
delete _pCrit;
|
||||
}
|
||||
if(_event)
|
||||
{
|
||||
delete _event;
|
||||
}
|
||||
}
|
||||
|
||||
bool UdpSocket2ManagerWindows::Init(WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads) {
|
||||
CriticalSectionScoped cs(_pCrit);
|
||||
if ((_id != -1) || (_numOfWorkThreads != 0)) {
|
||||
assert(_id != -1);
|
||||
assert(_numOfWorkThreads != 0);
|
||||
return false;
|
||||
}
|
||||
_id = id;
|
||||
_numOfWorkThreads = numOfWorkThreads;
|
||||
return true;
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocket2ManagerWindows::ChangeUniqueId(const WebRtc_Word32 id)
|
||||
{
|
||||
_id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UdpSocket2ManagerWindows::Start()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocket2ManagerWindows(%d)::Start()",_managerNumber);
|
||||
if(!_init)
|
||||
{
|
||||
StartWorkerThreads();
|
||||
}
|
||||
|
||||
if(!_init)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_pCrit->Enter();
|
||||
// Start worker threads.
|
||||
_stopped = false;
|
||||
WebRtc_Word32 error = 0;
|
||||
ListItem* pItem = _workerThreadsList.First();
|
||||
UdpSocket2WorkerWindows* pWorker;
|
||||
while(pItem != NULL && !error)
|
||||
{
|
||||
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
|
||||
if(!pWorker->Start())
|
||||
error = 1;
|
||||
pItem = _workerThreadsList.Next(pItem);
|
||||
}
|
||||
if(error)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::Start() error starting worker\
|
||||
threads",
|
||||
_managerNumber);
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
_pCrit->Leave();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSocket2ManagerWindows::StartWorkerThreads()
|
||||
{
|
||||
if(!_init)
|
||||
{
|
||||
_pCrit->Enter();
|
||||
|
||||
_ioCompletionHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,
|
||||
0, 0);
|
||||
if(_ioCompletionHandle == NULL)
|
||||
{
|
||||
WebRtc_Word32 error = GetLastError();
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::StartWorkerThreads()"
|
||||
"_ioCompletioHandle == NULL: error:%d",
|
||||
_managerNumber,error);
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create worker threads.
|
||||
WebRtc_UWord32 i = 0;
|
||||
bool error = false;
|
||||
while(i < _numOfWorkThreads && !error)
|
||||
{
|
||||
UdpSocket2WorkerWindows* pWorker =
|
||||
new UdpSocket2WorkerWindows(_ioCompletionHandle);
|
||||
if(pWorker->Init() != 0)
|
||||
{
|
||||
error = true;
|
||||
delete pWorker;
|
||||
break;
|
||||
}
|
||||
_workerThreadsList.PushFront(pWorker);
|
||||
i++;
|
||||
}
|
||||
if(error)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::StartWorkerThreads() error "
|
||||
"creating work threads",
|
||||
_managerNumber);
|
||||
// Delete worker threads.
|
||||
ListItem* pItem = NULL;
|
||||
while((pItem = _workerThreadsList.First()) != NULL)
|
||||
{
|
||||
delete static_cast<UdpSocket2WorkerWindows*>(pItem->GetItem());
|
||||
_workerThreadsList.PopFront();
|
||||
}
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
if(_ioContextPool.Init())
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::StartWorkerThreads() error "
|
||||
"initiating _ioContextPool",
|
||||
_managerNumber);
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
_init = true;
|
||||
WEBRTC_TRACE(
|
||||
kTraceDebug,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows::StartWorkerThreads %d number of work "
|
||||
"threads created and initialized",
|
||||
_numOfWorkThreads);
|
||||
_pCrit->Leave();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSocket2ManagerWindows::Stop()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocket2ManagerWindows(%d)::Stop()",_managerNumber);
|
||||
|
||||
if(!_init)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_pCrit->Enter();
|
||||
_stopped = true;
|
||||
if(_numActiveSockets)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::Stop() there is still active\
|
||||
sockets",
|
||||
_managerNumber);
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
// No active sockets. Stop all worker threads.
|
||||
bool result = StopWorkerThreads();
|
||||
_pCrit->Leave();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool UdpSocket2ManagerWindows::StopWorkerThreads()
|
||||
{
|
||||
WebRtc_Word32 error = 0;
|
||||
WEBRTC_TRACE(
|
||||
kTraceDebug,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::StopWorkerThreads() Worker\
|
||||
threadsStoped, numActicve Sockets=%d",
|
||||
_managerNumber,
|
||||
_numActiveSockets);
|
||||
UdpSocket2WorkerWindows* pWorker;
|
||||
ListItem* pItem = _workerThreadsList.First();
|
||||
|
||||
// Set worker threads to not alive so that they will stop calling
|
||||
// UdpSocket2WorkerWindows::Run().
|
||||
while(pItem != NULL)
|
||||
{
|
||||
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
|
||||
pWorker->SetNotAlive();
|
||||
pItem = _workerThreadsList.Next(pItem);
|
||||
}
|
||||
// Release all threads waiting for GetQueuedCompletionStatus(..).
|
||||
if(_ioCompletionHandle)
|
||||
{
|
||||
WebRtc_UWord32 i = 0;
|
||||
for(i = 0; i < _workerThreadsList.GetSize(); i++)
|
||||
{
|
||||
PostQueuedCompletionStatus(_ioCompletionHandle, 0 ,0 , NULL);
|
||||
}
|
||||
}
|
||||
pItem = _workerThreadsList.First();
|
||||
|
||||
while(pItem != NULL)
|
||||
{
|
||||
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
|
||||
if(pWorker->Stop() == false)
|
||||
{
|
||||
error = -1;
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
|
||||
"failed to stop worker thread");
|
||||
}
|
||||
pItem = _workerThreadsList.Next(pItem);
|
||||
}
|
||||
|
||||
if(error)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::StopWorkerThreads() error stopping\
|
||||
worker threads",
|
||||
_managerNumber);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSocket2ManagerWindows::AddSocketPrv(UdpSocket2Windows* s)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocket2ManagerWindows(%d)::AddSocketPrv()",_managerNumber);
|
||||
if(!_init)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::AddSocketPrv() manager not\
|
||||
initialized",
|
||||
_managerNumber);
|
||||
return false;
|
||||
}
|
||||
_pCrit->Enter();
|
||||
if(s == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::AddSocketPrv() socket == NULL",
|
||||
_managerNumber);
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
if(s->GetFd() == NULL || s->GetFd() == INVALID_SOCKET)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::AddSocketPrv() socket->GetFd() ==\
|
||||
%d",
|
||||
_managerNumber,
|
||||
(WebRtc_Word32)s->GetFd());
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
|
||||
}
|
||||
_ioCompletionHandle = CreateIoCompletionPort((HANDLE)s->GetFd(),
|
||||
_ioCompletionHandle,
|
||||
(ULONG_PTR)(s), 0);
|
||||
if(_ioCompletionHandle == NULL)
|
||||
{
|
||||
WebRtc_Word32 error = GetLastError();
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::AddSocketPrv() Error adding to IO\
|
||||
completion: %d",
|
||||
_managerNumber,
|
||||
error);
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
_numActiveSockets++;
|
||||
_pCrit->Leave();
|
||||
return true;
|
||||
}
|
||||
bool UdpSocket2ManagerWindows::RemoveSocketPrv(UdpSocket2Windows* s)
|
||||
{
|
||||
if(!_init)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_pCrit->Enter();
|
||||
_numActiveSockets--;
|
||||
if(_numActiveSockets == 0)
|
||||
{
|
||||
_event->Set();
|
||||
}
|
||||
_pCrit->Leave();
|
||||
return true;
|
||||
}
|
||||
|
||||
PerIoContext* UdpSocket2ManagerWindows::PopIoContext()
|
||||
{
|
||||
if(!_init)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PerIoContext* pIoC = NULL;
|
||||
if(!_stopped)
|
||||
{
|
||||
pIoC = _ioContextPool.PopIoContext();
|
||||
}else
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocket2ManagerWindows(%d)::PopIoContext() Manager Not started",
|
||||
_managerNumber);
|
||||
}
|
||||
return pIoC;
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocket2ManagerWindows::PushIoContext(PerIoContext* pIoContext)
|
||||
{
|
||||
return _ioContextPool.PushIoContext(pIoContext);
|
||||
}
|
||||
|
||||
IoContextPool::IoContextPool()
|
||||
: _pListHead(NULL),
|
||||
_init(false),
|
||||
_size(0),
|
||||
_inUse(0)
|
||||
{
|
||||
}
|
||||
|
||||
IoContextPool::~IoContextPool()
|
||||
{
|
||||
Free();
|
||||
assert(_size.Value() == 0);
|
||||
AlignedFree(_pListHead);
|
||||
}
|
||||
|
||||
WebRtc_Word32 IoContextPool::Init(WebRtc_UWord32 /*increaseSize*/)
|
||||
{
|
||||
if(_init)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
_pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER),
|
||||
MEMORY_ALLOCATION_ALIGNMENT);
|
||||
if(_pListHead == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
InitializeSListHead(_pListHead);
|
||||
_init = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PerIoContext* IoContextPool::PopIoContext()
|
||||
{
|
||||
if(!_init)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead);
|
||||
if(pListEntry == NULL)
|
||||
{
|
||||
IoContextPoolItem* item = (IoContextPoolItem*)
|
||||
AlignedMalloc(
|
||||
sizeof(IoContextPoolItem),
|
||||
MEMORY_ALLOCATION_ALIGNMENT);
|
||||
if(item == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(&item->payload.ioContext,0,sizeof(PerIoContext));
|
||||
item->payload.base = item;
|
||||
pListEntry = &(item->itemEntry);
|
||||
++_size;
|
||||
}
|
||||
++_inUse;
|
||||
return &((IoContextPoolItem*)pListEntry)->payload.ioContext;
|
||||
}
|
||||
|
||||
WebRtc_Word32 IoContextPool::PushIoContext(PerIoContext* pIoContext)
|
||||
{
|
||||
// TODO (hellner): Overlapped IO should be completed at this point. Perhaps
|
||||
// add an assert?
|
||||
const bool overlappedIOCompleted = HasOverlappedIoCompleted(
|
||||
(LPOVERLAPPED)pIoContext);
|
||||
|
||||
IoContextPoolItem* item = ((IoContextPoolItemPayload*)pIoContext)->base;
|
||||
|
||||
const WebRtc_Word32 usedItems = --_inUse;
|
||||
const WebRtc_Word32 totalItems = _size.Value();
|
||||
const WebRtc_Word32 freeItems = totalItems - usedItems;
|
||||
if(freeItems < 0)
|
||||
{
|
||||
assert(false);
|
||||
AlignedFree(item);
|
||||
return -1;
|
||||
}
|
||||
if((freeItems >= totalItems>>1) &&
|
||||
overlappedIOCompleted)
|
||||
{
|
||||
AlignedFree(item);
|
||||
--_size;
|
||||
return 0;
|
||||
}
|
||||
InterlockedPushEntrySList(_pListHead, &(item->itemEntry));
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 IoContextPool::Free()
|
||||
{
|
||||
if(!_init)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 itemsFreed = 0;
|
||||
PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead);
|
||||
while(pListEntry != NULL)
|
||||
{
|
||||
IoContextPoolItem* item = ((IoContextPoolItem*)pListEntry);
|
||||
AlignedFree(item);
|
||||
--_size;
|
||||
itemsFreed++;
|
||||
pListEntry = InterlockedPopEntrySList(_pListHead);
|
||||
}
|
||||
return itemsFreed;
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocket2WorkerWindows::_numOfWorkers = 0;
|
||||
|
||||
UdpSocket2WorkerWindows::UdpSocket2WorkerWindows(HANDLE ioCompletionHandle)
|
||||
: _ioCompletionHandle(ioCompletionHandle),
|
||||
_pThread(NULL),
|
||||
_init(false)
|
||||
{
|
||||
_workerNumber = _numOfWorkers++;
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1,
|
||||
"UdpSocket2WorkerWindows created");
|
||||
}
|
||||
|
||||
UdpSocket2WorkerWindows::~UdpSocket2WorkerWindows()
|
||||
{
|
||||
if(_pThread)
|
||||
{
|
||||
delete _pThread;
|
||||
}
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1,
|
||||
"UdpSocket2WorkerWindows deleted");
|
||||
}
|
||||
|
||||
bool UdpSocket2WorkerWindows::Start()
|
||||
{
|
||||
unsigned int id = 0;
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1,
|
||||
"Start UdpSocket2WorkerWindows");
|
||||
return _pThread->Start(id);
|
||||
}
|
||||
|
||||
bool UdpSocket2WorkerWindows::Stop()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1,
|
||||
"Stop UdpSocket2WorkerWindows");
|
||||
return _pThread->Stop();
|
||||
}
|
||||
|
||||
void UdpSocket2WorkerWindows::SetNotAlive()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1,
|
||||
"SetNotAlive UdpSocket2WorkerWindows");
|
||||
_pThread->SetNotAlive();
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocket2WorkerWindows::Init()
|
||||
{
|
||||
if(!_init)
|
||||
{
|
||||
const char* threadName = "UdpSocket2ManagerWindows_thread";
|
||||
_pThread = ThreadWrapper::CreateThread(Run, this, kRealtimePriority,
|
||||
threadName);
|
||||
if(_pThread == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
-1,
|
||||
"UdpSocket2WorkerWindows(%d)::Init(), error creating thread!",
|
||||
_workerNumber);
|
||||
return -1;
|
||||
}
|
||||
_init = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UdpSocket2WorkerWindows::Run(ThreadObj obj)
|
||||
{
|
||||
UdpSocket2WorkerWindows* pWorker =
|
||||
static_cast<UdpSocket2WorkerWindows*>(obj);
|
||||
return pWorker->Process();
|
||||
}
|
||||
|
||||
// Process should always return true. Stopping the worker threads is done in
|
||||
// the UdpSocket2ManagerWindows::StopWorkerThreads() function.
|
||||
bool UdpSocket2WorkerWindows::Process()
|
||||
{
|
||||
WebRtc_Word32 success = 0;
|
||||
DWORD ioSize = 0;
|
||||
UdpSocket2Windows* pSocket = NULL;
|
||||
PerIoContext* pIOContext = 0;
|
||||
OVERLAPPED* pOverlapped = 0;
|
||||
success = GetQueuedCompletionStatus(_ioCompletionHandle,
|
||||
&ioSize,
|
||||
(ULONG_PTR*)&pSocket, &pOverlapped, 200);
|
||||
|
||||
WebRtc_UWord32 error = 0;
|
||||
if(!success)
|
||||
{
|
||||
error = GetLastError();
|
||||
if(error == WAIT_TIMEOUT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// This may happen if e.g. PostQueuedCompletionStatus() has been called.
|
||||
// The IO context still needs to be reclaimed or re-used which is done
|
||||
// in UdpSocket2Windows::IOCompleted(..).
|
||||
}
|
||||
if(pSocket == NULL)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceDebug,
|
||||
kTraceTransport,
|
||||
-1,
|
||||
"UdpSocket2WorkerWindows(%d)::Process(), pSocket == 0, end thread",
|
||||
_workerNumber);
|
||||
return true;
|
||||
}
|
||||
pIOContext = (PerIoContext*)pOverlapped;
|
||||
pSocket->IOCompleted(pIOContext,ioSize,error);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
167
webrtc/test/channel_transport/udp_socket2_manager_win.h
Normal file
167
webrtc/test/channel_transport/udp_socket2_manager_win.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/list_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket2_win.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
|
||||
#define MAX_IO_BUFF_SIZE 1600
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
enum IO_OPERATION {
|
||||
OP_READ,
|
||||
OP_WRITE
|
||||
};
|
||||
|
||||
class UdpSocket2Windows;
|
||||
|
||||
// Struct used for all socket I/O operations.
|
||||
struct PerIoContext {
|
||||
WSAOVERLAPPED overlapped;
|
||||
char buffer[MAX_IO_BUFF_SIZE];
|
||||
WSABUF wsabuf;
|
||||
int nTotalBytes;
|
||||
int nSentBytes;
|
||||
int bytes;
|
||||
IO_OPERATION ioOperation;
|
||||
SocketAddress from;
|
||||
int fromLen;
|
||||
// Should be set to true if the I/O context was passed to the system by
|
||||
// a thread not controlled by the socket implementation.
|
||||
bool ioInitiatedByThreadWrapper;
|
||||
// TODO (hellner): Not used. Delete it.
|
||||
PerIoContext* pNextFree;
|
||||
};
|
||||
|
||||
struct IoContextPoolItem;
|
||||
struct IoContextPoolItemPayload
|
||||
{
|
||||
PerIoContext ioContext;
|
||||
IoContextPoolItem* base;
|
||||
};
|
||||
|
||||
struct IoContextPoolItem
|
||||
{
|
||||
// Atomic single linked list entry header.
|
||||
SLIST_ENTRY itemEntry;
|
||||
// Atomic single linked list payload
|
||||
IoContextPoolItemPayload payload;
|
||||
};
|
||||
|
||||
class IoContextPool
|
||||
{
|
||||
public:
|
||||
IoContextPool();
|
||||
virtual ~IoContextPool();
|
||||
virtual WebRtc_Word32 Init(WebRtc_UWord32 increaseSize = 128);
|
||||
// Re-use an old unused IO context or create a new one.
|
||||
virtual PerIoContext* PopIoContext();
|
||||
virtual WebRtc_Word32 PushIoContext(PerIoContext* pIoContext);
|
||||
virtual inline WebRtc_Word32 GetSize(WebRtc_UWord32* inUse = 0)
|
||||
{return _size.Value();}
|
||||
virtual WebRtc_Word32 Free();
|
||||
private:
|
||||
// Sample code for use of msfts single linked atomic list can be found here:
|
||||
// http://msdn.microsoft.com/en-us/library/ms686962(VS.85).aspx
|
||||
|
||||
// Atomic single linked list head.
|
||||
PSLIST_HEADER _pListHead;
|
||||
|
||||
bool _init;
|
||||
Atomic32 _size;
|
||||
Atomic32 _inUse;
|
||||
};
|
||||
|
||||
|
||||
class UdpSocket2ManagerWindows : public UdpSocketManager
|
||||
{
|
||||
public:
|
||||
UdpSocket2ManagerWindows();
|
||||
virtual ~UdpSocket2ManagerWindows();
|
||||
|
||||
virtual bool Init(WebRtc_Word32 id, WebRtc_UWord8& numOfWorkThreads);
|
||||
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id);
|
||||
|
||||
virtual bool Start();
|
||||
virtual bool Stop();
|
||||
|
||||
virtual inline bool AddSocket(UdpSocketWrapper* s)
|
||||
{if(s) return AddSocketPrv(reinterpret_cast<UdpSocket2Windows*>(s));
|
||||
return false;}
|
||||
virtual bool RemoveSocket(UdpSocketWrapper* s)
|
||||
{if(s) return RemoveSocketPrv(reinterpret_cast<UdpSocket2Windows*>(s));
|
||||
return false;}
|
||||
|
||||
PerIoContext* PopIoContext(void);
|
||||
WebRtc_Word32 PushIoContext(PerIoContext* pIoContext);
|
||||
|
||||
private:
|
||||
bool StopWorkerThreads();
|
||||
bool StartWorkerThreads();
|
||||
bool AddSocketPrv(UdpSocket2Windows* s);
|
||||
bool RemoveSocketPrv(UdpSocket2Windows* s);
|
||||
|
||||
static WebRtc_UWord32 _numOfActiveManagers;
|
||||
static bool _wsaInit;
|
||||
|
||||
WebRtc_Word32 _id;
|
||||
CriticalSectionWrapper* _pCrit;
|
||||
WebRtc_Word32 _managerNumber;
|
||||
volatile bool _stopped;
|
||||
bool _init;
|
||||
WebRtc_Word32 _numActiveSockets;
|
||||
ListWrapper _workerThreadsList;
|
||||
EventWrapper* _event;
|
||||
|
||||
HANDLE _ioCompletionHandle;
|
||||
IoContextPool _ioContextPool;
|
||||
};
|
||||
|
||||
class UdpSocket2WorkerWindows
|
||||
{
|
||||
public:
|
||||
UdpSocket2WorkerWindows(HANDLE ioCompletionHandle);
|
||||
virtual ~UdpSocket2WorkerWindows();
|
||||
|
||||
virtual bool Start();
|
||||
virtual bool Stop();
|
||||
virtual WebRtc_Word32 Init();
|
||||
virtual void SetNotAlive();
|
||||
protected:
|
||||
static bool Run(ThreadObj obj);
|
||||
bool Process();
|
||||
private:
|
||||
HANDLE _ioCompletionHandle;
|
||||
ThreadWrapper*_pThread;
|
||||
static WebRtc_Word32 _numOfWorkers;
|
||||
WebRtc_Word32 _workerNumber;
|
||||
volatile bool _stop;
|
||||
bool _init;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
|
1390
webrtc/test/channel_transport/udp_socket2_win.cc
Normal file
1390
webrtc/test/channel_transport/udp_socket2_win.cc
Normal file
File diff suppressed because it is too large
Load Diff
176
webrtc/test/channel_transport/udp_socket2_win.h
Normal file
176
webrtc/test/channel_transport/udp_socket2_win.h
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_WINDOWS_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_WINDOWS_H_
|
||||
|
||||
// Disable deprication warning from traffic.h
|
||||
#pragma warning(disable : 4995)
|
||||
|
||||
// Don't change include order for these header files.
|
||||
#include <Winsock2.h>
|
||||
#include <Ntddndis.h>
|
||||
#include <traffic.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/list_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket2_manager_win.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class UdpSocket2ManagerWindows;
|
||||
class TrafficControlWindows;
|
||||
struct PerIoContext;
|
||||
|
||||
class UdpSocket2Windows : public UdpSocketWrapper
|
||||
{
|
||||
public:
|
||||
UdpSocket2Windows(const WebRtc_Word32 id, UdpSocketManager* mgr,
|
||||
bool ipV6Enable = false, bool disableGQOS = false);
|
||||
virtual ~UdpSocket2Windows();
|
||||
|
||||
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id);
|
||||
|
||||
virtual bool ValidHandle();
|
||||
|
||||
virtual bool SetCallback(CallbackObj, IncomingSocketCallback);
|
||||
|
||||
virtual bool Bind(const SocketAddress& name);
|
||||
virtual bool SetSockopt(WebRtc_Word32 level, WebRtc_Word32 optname,
|
||||
const WebRtc_Word8* optval, WebRtc_Word32 optlen);
|
||||
|
||||
virtual bool StartReceiving(const WebRtc_UWord32 receiveBuffers);
|
||||
virtual inline bool StartReceiving() {return StartReceiving(8);}
|
||||
virtual bool StopReceiving();
|
||||
|
||||
virtual WebRtc_Word32 SendTo(const WebRtc_Word8* buf, WebRtc_Word32 len,
|
||||
const SocketAddress& to);
|
||||
|
||||
virtual void CloseBlocking();
|
||||
|
||||
virtual SOCKET GetFd() { return _socket;}
|
||||
virtual bool SetQos(WebRtc_Word32 serviceType, WebRtc_Word32 tokenRate,
|
||||
WebRtc_Word32 bucketSize, WebRtc_Word32 peekBandwith,
|
||||
WebRtc_Word32 minPolicedSize, WebRtc_Word32 maxSduSize,
|
||||
const SocketAddress &stRemName,
|
||||
WebRtc_Word32 overrideDSCP = 0);
|
||||
|
||||
virtual WebRtc_Word32 SetTOS(const WebRtc_Word32 serviceType);
|
||||
virtual WebRtc_Word32 SetPCP(const WebRtc_Word32 pcp);
|
||||
|
||||
virtual WebRtc_UWord32 ReceiveBuffers(){return _receiveBuffers.Value();}
|
||||
|
||||
protected:
|
||||
void IOCompleted(PerIoContext* pIOContext, WebRtc_UWord32 ioSize,
|
||||
WebRtc_UWord32 error);
|
||||
|
||||
WebRtc_Word32 PostRecv();
|
||||
// Use pIoContext to post a new WSARecvFrom(..).
|
||||
WebRtc_Word32 PostRecv(PerIoContext* pIoContext);
|
||||
|
||||
private:
|
||||
friend class UdpSocket2WorkerWindows;
|
||||
|
||||
// Set traffic control (TC) flow adding it the interface that matches this
|
||||
// sockets address.
|
||||
// A filter is created and added to the flow.
|
||||
// The flow consists of:
|
||||
// (1) QoS send and receive information (flow specifications).
|
||||
// (2) A DS object (for specifying exact DSCP value).
|
||||
// (3) Possibly a traffic object (for specifying exact 802.1p priority (PCP)
|
||||
// value).
|
||||
//
|
||||
// dscp values:
|
||||
// -1 don't change the current dscp value.
|
||||
// 0 don't add any flow to TC, unless pcp is specified.
|
||||
// 1-63 Add a flow to TC with the specified dscp value.
|
||||
// pcp values:
|
||||
// -2 Don't add pcp info to the flow, (3) will not be added.
|
||||
// -1 Don't change the current value.
|
||||
// 0-7 Add pcp info to the flow with the specified value,
|
||||
// (3) will be added.
|
||||
//
|
||||
// If both dscp and pcp are -1 no flow will be created or added to TC.
|
||||
// If dscp is 0 and pcp is 0-7 (1), (2) and (3) will be created.
|
||||
// Note: input parameter values are assumed to be in valid range, checks
|
||||
// must be done by caller.
|
||||
WebRtc_Word32 SetTrafficControl(WebRtc_Word32 dscp, WebRtc_Word32 pcp,
|
||||
const struct sockaddr_in* name,
|
||||
FLOWSPEC* send = NULL,
|
||||
FLOWSPEC* recv = NULL);
|
||||
WebRtc_Word32 CreateFlowSpec(WebRtc_Word32 serviceType,
|
||||
WebRtc_Word32 tokenRate,
|
||||
WebRtc_Word32 bucketSize,
|
||||
WebRtc_Word32 peekBandwith,
|
||||
WebRtc_Word32 minPolicedSize,
|
||||
WebRtc_Word32 maxSduSize, FLOWSPEC *f);
|
||||
|
||||
WebRtc_Word32 _id;
|
||||
RWLockWrapper* _ptrCbRWLock;
|
||||
IncomingSocketCallback _incomingCb;
|
||||
CallbackObj _obj;
|
||||
bool _qos;
|
||||
|
||||
SocketAddress _remoteAddr;
|
||||
SOCKET _socket;
|
||||
WebRtc_Word32 _iProtocol;
|
||||
UdpSocket2ManagerWindows* _mgr;
|
||||
|
||||
CriticalSectionWrapper* _pCrit;
|
||||
Atomic32 _outstandingCalls;
|
||||
Atomic32 _outstandingCallComplete;
|
||||
volatile bool _terminate;
|
||||
volatile bool _addedToMgr;
|
||||
|
||||
CriticalSectionWrapper* _ptrDeleteCrit;
|
||||
ConditionVariableWrapper* _ptrDeleteCond;
|
||||
bool _safeTodelete;
|
||||
|
||||
RWLockWrapper* _ptrDestRWLock;
|
||||
bool _outstandingCallsDisabled;
|
||||
bool NewOutstandingCall();
|
||||
void OutstandingCallCompleted();
|
||||
void DisableNewOutstandingCalls();
|
||||
void WaitForOutstandingCalls();
|
||||
|
||||
void RemoveSocketFromManager();
|
||||
|
||||
// RWLockWrapper is used as a reference counter for the socket. Write lock
|
||||
// is used for creating and deleting socket. Read lock is used for
|
||||
// accessing the socket.
|
||||
RWLockWrapper* _ptrSocketRWLock;
|
||||
bool AquireSocket();
|
||||
void ReleaseSocket();
|
||||
bool InvalidateSocket();
|
||||
|
||||
// Traffic control handles and structure pointers.
|
||||
HANDLE _clientHandle;
|
||||
HANDLE _flowHandle;
|
||||
HANDLE _filterHandle;
|
||||
PTC_GEN_FLOW _flow;
|
||||
// TrafficControlWindows implements TOS and PCP.
|
||||
TrafficControlWindows* _gtc;
|
||||
// Holds the current pcp value. Can be -2 or 0 - 7.
|
||||
int _pcp;
|
||||
|
||||
Atomic32 _receiveBuffers;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_WINDOWS_H_
|
431
webrtc/test/channel_transport/udp_socket_manager_posix.cc
Normal file
431
webrtc/test/channel_transport/udp_socket_manager_posix.cc
Normal file
@ -0,0 +1,431 @@
|
||||
/*
|
||||
* 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 "webrtc/test/channel_transport/udp_socket_manager_posix.h"
|
||||
|
||||
#include <strings.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_posix.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
UdpSocketManagerPosix::UdpSocketManagerPosix()
|
||||
: UdpSocketManager(),
|
||||
_id(-1),
|
||||
_critSect(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_numberOfSocketMgr(-1),
|
||||
_incSocketMgrNextTime(0),
|
||||
_nextSocketMgrToAssign(0),
|
||||
_socketMgr()
|
||||
{
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosix::Init(WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads) {
|
||||
CriticalSectionScoped cs(_critSect);
|
||||
if ((_id != -1) || (_numOfWorkThreads != 0)) {
|
||||
assert(_id != -1);
|
||||
assert(_numOfWorkThreads != 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
_id = id;
|
||||
_numberOfSocketMgr = numOfWorkThreads;
|
||||
_numOfWorkThreads = numOfWorkThreads;
|
||||
|
||||
if(MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX < _numberOfSocketMgr)
|
||||
{
|
||||
_numberOfSocketMgr = MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX;
|
||||
}
|
||||
for(int i = 0;i < _numberOfSocketMgr; i++)
|
||||
{
|
||||
_socketMgr[i] = new UdpSocketManagerPosixImpl();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
UdpSocketManagerPosix::~UdpSocketManagerPosix()
|
||||
{
|
||||
Stop();
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketManagerPosix(%d)::UdpSocketManagerPosix()",
|
||||
_numberOfSocketMgr);
|
||||
|
||||
for(int i = 0;i < _numberOfSocketMgr; i++)
|
||||
{
|
||||
delete _socketMgr[i];
|
||||
}
|
||||
delete _critSect;
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocketManagerPosix::ChangeUniqueId(const WebRtc_Word32 id)
|
||||
{
|
||||
_id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosix::Start()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketManagerPosix(%d)::Start()",
|
||||
_numberOfSocketMgr);
|
||||
|
||||
_critSect->Enter();
|
||||
bool retVal = true;
|
||||
for(int i = 0;i < _numberOfSocketMgr && retVal; i++)
|
||||
{
|
||||
retVal = _socketMgr[i]->Start();
|
||||
}
|
||||
if(!retVal)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocketManagerPosix(%d)::Start() error starting socket managers",
|
||||
_numberOfSocketMgr);
|
||||
}
|
||||
_critSect->Leave();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosix::Stop()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketManagerPosix(%d)::Stop()",_numberOfSocketMgr);
|
||||
|
||||
_critSect->Enter();
|
||||
bool retVal = true;
|
||||
for(int i = 0; i < _numberOfSocketMgr && retVal; i++)
|
||||
{
|
||||
retVal = _socketMgr[i]->Stop();
|
||||
}
|
||||
if(!retVal)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocketManagerPosix(%d)::Stop() there are still active socket "
|
||||
"managers",
|
||||
_numberOfSocketMgr);
|
||||
}
|
||||
_critSect->Leave();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosix::AddSocket(UdpSocketWrapper* s)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketManagerPosix(%d)::AddSocket()",_numberOfSocketMgr);
|
||||
|
||||
_critSect->Enter();
|
||||
bool retVal = _socketMgr[_nextSocketMgrToAssign]->AddSocket(s);
|
||||
if(!retVal)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocketManagerPosix(%d)::AddSocket() failed to add socket to\
|
||||
manager",
|
||||
_numberOfSocketMgr);
|
||||
}
|
||||
|
||||
// Distribute sockets on UdpSocketManagerPosixImpls in a round-robin
|
||||
// fashion.
|
||||
if(_incSocketMgrNextTime == 0)
|
||||
{
|
||||
_incSocketMgrNextTime++;
|
||||
} else {
|
||||
_incSocketMgrNextTime = 0;
|
||||
_nextSocketMgrToAssign++;
|
||||
if(_nextSocketMgrToAssign >= _numberOfSocketMgr)
|
||||
{
|
||||
_nextSocketMgrToAssign = 0;
|
||||
}
|
||||
}
|
||||
_critSect->Leave();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosix::RemoveSocket(UdpSocketWrapper* s)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketManagerPosix(%d)::RemoveSocket()",
|
||||
_numberOfSocketMgr);
|
||||
|
||||
_critSect->Enter();
|
||||
bool retVal = false;
|
||||
for(int i = 0;i < _numberOfSocketMgr && (retVal == false); i++)
|
||||
{
|
||||
retVal = _socketMgr[i]->RemoveSocket(s);
|
||||
}
|
||||
if(!retVal)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
_id,
|
||||
"UdpSocketManagerPosix(%d)::RemoveSocket() failed to remove socket\
|
||||
from manager",
|
||||
_numberOfSocketMgr);
|
||||
}
|
||||
_critSect->Leave();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
UdpSocketManagerPosixImpl::UdpSocketManagerPosixImpl()
|
||||
{
|
||||
_critSectList = CriticalSectionWrapper::CreateCriticalSection();
|
||||
_thread = ThreadWrapper::CreateThread(UdpSocketManagerPosixImpl::Run, this,
|
||||
kRealtimePriority,
|
||||
"UdpSocketManagerPosixImplThread");
|
||||
FD_ZERO(&_readFds);
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1,
|
||||
"UdpSocketManagerPosix created");
|
||||
}
|
||||
|
||||
UdpSocketManagerPosixImpl::~UdpSocketManagerPosixImpl()
|
||||
{
|
||||
if(_thread != NULL)
|
||||
{
|
||||
delete _thread;
|
||||
}
|
||||
|
||||
if (_critSectList != NULL)
|
||||
{
|
||||
UpdateSocketMap();
|
||||
|
||||
_critSectList->Enter();
|
||||
|
||||
MapItem* item = _socketMap.First();
|
||||
while(item)
|
||||
{
|
||||
UdpSocketPosix* s = static_cast<UdpSocketPosix*>(item->GetItem());
|
||||
_socketMap.Erase(item);
|
||||
item = _socketMap.First();
|
||||
delete s;
|
||||
}
|
||||
_critSectList->Leave();
|
||||
|
||||
delete _critSectList;
|
||||
}
|
||||
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1,
|
||||
"UdpSocketManagerPosix deleted");
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosixImpl::Start()
|
||||
{
|
||||
unsigned int id = 0;
|
||||
if (_thread == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1,
|
||||
"Start UdpSocketManagerPosix");
|
||||
return _thread->Start(id);
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosixImpl::Stop()
|
||||
{
|
||||
if (_thread == NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1,
|
||||
"Stop UdpSocketManagerPosix");
|
||||
return _thread->Stop();
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosixImpl::Process()
|
||||
{
|
||||
bool doSelect = false;
|
||||
// Timeout = 1 second.
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 10000;
|
||||
MapItem* it;
|
||||
|
||||
FD_ZERO(&_readFds);
|
||||
|
||||
UpdateSocketMap();
|
||||
|
||||
unsigned int maxFd = 0;
|
||||
for (it = _socketMap.First(); it != NULL; it=_socketMap.Next(it))
|
||||
{
|
||||
doSelect = true;
|
||||
maxFd = maxFd > it->GetUnsignedId() ? maxFd : it->GetUnsignedId();
|
||||
FD_SET(it->GetUnsignedId(), &_readFds);
|
||||
}
|
||||
|
||||
int num = 0;
|
||||
if (doSelect)
|
||||
{
|
||||
num = select(maxFd+1, &_readFds, NULL, NULL, &timeout);
|
||||
|
||||
if (num == SOCKET_ERROR)
|
||||
{
|
||||
// Timeout = 10 ms.
|
||||
timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = 10000*1000;
|
||||
nanosleep(&t, NULL);
|
||||
return true;
|
||||
}
|
||||
}else
|
||||
{
|
||||
// Timeout = 10 ms.
|
||||
timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = 10000*1000;
|
||||
nanosleep(&t, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (it = _socketMap.First(); it != NULL && num > 0;
|
||||
it = _socketMap.Next(it))
|
||||
{
|
||||
UdpSocketPosix* s = static_cast<UdpSocketPosix*>(it->GetItem());
|
||||
if (FD_ISSET(it->GetUnsignedId(), &_readFds))
|
||||
{
|
||||
s->HasIncoming();
|
||||
num--;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosixImpl::Run(ThreadObj obj)
|
||||
{
|
||||
UdpSocketManagerPosixImpl* mgr =
|
||||
static_cast<UdpSocketManagerPosixImpl*>(obj);
|
||||
return mgr->Process();
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosixImpl::AddSocket(UdpSocketWrapper* s)
|
||||
{
|
||||
UdpSocketPosix* sl = static_cast<UdpSocketPosix*>(s);
|
||||
if(sl->GetFd() == INVALID_SOCKET || !(sl->GetFd() < FD_SETSIZE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_critSectList->Enter();
|
||||
_addList.PushBack(s);
|
||||
_critSectList->Leave();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSocketManagerPosixImpl::RemoveSocket(UdpSocketWrapper* s)
|
||||
{
|
||||
// Put in remove list if this is the correct UdpSocketManagerPosixImpl.
|
||||
_critSectList->Enter();
|
||||
|
||||
// If the socket is in the add list it's safe to remove and delete it.
|
||||
ListItem* addListItem = _addList.First();
|
||||
while(addListItem)
|
||||
{
|
||||
UdpSocketPosix* addSocket = (UdpSocketPosix*)addListItem->GetItem();
|
||||
unsigned int addFD = addSocket->GetFd();
|
||||
unsigned int removeFD = static_cast<UdpSocketPosix*>(s)->GetFd();
|
||||
if(removeFD == addFD)
|
||||
{
|
||||
_removeList.PushBack(removeFD);
|
||||
_critSectList->Leave();
|
||||
return true;
|
||||
}
|
||||
addListItem = _addList.Next(addListItem);
|
||||
}
|
||||
|
||||
// Checking the socket map is safe since all Erase and Insert calls to this
|
||||
// map are also protected by _critSectList.
|
||||
if(_socketMap.Find(static_cast<UdpSocketPosix*>(s)->GetFd()) != NULL)
|
||||
{
|
||||
_removeList.PushBack(static_cast<UdpSocketPosix*>(s)->GetFd());
|
||||
_critSectList->Leave();
|
||||
return true;
|
||||
}
|
||||
_critSectList->Leave();
|
||||
return false;
|
||||
}
|
||||
|
||||
void UdpSocketManagerPosixImpl::UpdateSocketMap()
|
||||
{
|
||||
// Remove items in remove list.
|
||||
_critSectList->Enter();
|
||||
while(!_removeList.Empty())
|
||||
{
|
||||
UdpSocketPosix* deleteSocket = NULL;
|
||||
unsigned int removeFD = _removeList.First()->GetUnsignedItem();
|
||||
|
||||
// If the socket is in the add list it hasn't been added to the socket
|
||||
// map yet. Just remove the socket from the add list.
|
||||
ListItem* addListItem = _addList.First();
|
||||
while(addListItem)
|
||||
{
|
||||
UdpSocketPosix* addSocket = (UdpSocketPosix*)addListItem->GetItem();
|
||||
unsigned int addFD = addSocket->GetFd();
|
||||
if(removeFD == addFD)
|
||||
{
|
||||
deleteSocket = addSocket;
|
||||
_addList.Erase(addListItem);
|
||||
break;
|
||||
}
|
||||
addListItem = _addList.Next(addListItem);
|
||||
}
|
||||
|
||||
// Find and remove socket from _socketMap.
|
||||
MapItem* it = _socketMap.Find(removeFD);
|
||||
if(it != NULL)
|
||||
{
|
||||
UdpSocketPosix* socket =
|
||||
static_cast<UdpSocketPosix*>(it->GetItem());
|
||||
if(socket)
|
||||
{
|
||||
deleteSocket = socket;
|
||||
}
|
||||
_socketMap.Erase(it);
|
||||
}
|
||||
if(deleteSocket)
|
||||
{
|
||||
deleteSocket->ReadyForDeletion();
|
||||
delete deleteSocket;
|
||||
}
|
||||
_removeList.PopFront();
|
||||
}
|
||||
|
||||
// Add sockets from add list.
|
||||
while(!_addList.Empty())
|
||||
{
|
||||
UdpSocketPosix* s =
|
||||
static_cast<UdpSocketPosix*>(_addList.First()->GetItem());
|
||||
if(s)
|
||||
{
|
||||
_socketMap.Insert(s->GetFd(), s);
|
||||
}
|
||||
_addList.PopFront();
|
||||
}
|
||||
_critSectList->Leave();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
89
webrtc/test/channel_transport/udp_socket_manager_posix.h
Normal file
89
webrtc/test/channel_transport/udp_socket_manager_posix.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_MANAGER_POSIX_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_MANAGER_POSIX_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/list_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/map_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ConditionVariableWrapper;
|
||||
|
||||
namespace test {
|
||||
|
||||
class UdpSocketManagerPosixImpl;
|
||||
#define MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX 8
|
||||
|
||||
class UdpSocketManagerPosix : public UdpSocketManager
|
||||
{
|
||||
public:
|
||||
UdpSocketManagerPosix();
|
||||
virtual ~UdpSocketManagerPosix();
|
||||
|
||||
virtual bool Init(WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads);
|
||||
|
||||
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id);
|
||||
|
||||
virtual bool Start();
|
||||
virtual bool Stop();
|
||||
|
||||
virtual bool AddSocket(UdpSocketWrapper* s);
|
||||
virtual bool RemoveSocket(UdpSocketWrapper* s);
|
||||
private:
|
||||
WebRtc_Word32 _id;
|
||||
CriticalSectionWrapper* _critSect;
|
||||
WebRtc_UWord8 _numberOfSocketMgr;
|
||||
WebRtc_UWord8 _incSocketMgrNextTime;
|
||||
WebRtc_UWord8 _nextSocketMgrToAssign;
|
||||
UdpSocketManagerPosixImpl* _socketMgr[MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX];
|
||||
};
|
||||
|
||||
class UdpSocketManagerPosixImpl
|
||||
{
|
||||
public:
|
||||
UdpSocketManagerPosixImpl();
|
||||
virtual ~UdpSocketManagerPosixImpl();
|
||||
|
||||
virtual bool Start();
|
||||
virtual bool Stop();
|
||||
|
||||
virtual bool AddSocket(UdpSocketWrapper* s);
|
||||
virtual bool RemoveSocket(UdpSocketWrapper* s);
|
||||
|
||||
protected:
|
||||
static bool Run(ThreadObj obj);
|
||||
bool Process();
|
||||
void UpdateSocketMap();
|
||||
|
||||
private:
|
||||
ThreadWrapper* _thread;
|
||||
CriticalSectionWrapper* _critSectList;
|
||||
|
||||
fd_set _readFds;
|
||||
|
||||
MapWrapper _socketMap;
|
||||
ListWrapper _addList;
|
||||
ListWrapper _removeList;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_MANAGER_POSIX_H_
|
84
webrtc/test/channel_transport/udp_socket_manager_unittest.cc
Normal file
84
webrtc/test/channel_transport/udp_socket_manager_unittest.cc
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Tests for the UdpSocketManager interface.
|
||||
// Note: This tests UdpSocketManager together with UdpSocketWrapper,
|
||||
// due to the way the code is full of static-casts to the platform dependent
|
||||
// subtypes.
|
||||
// It also uses the static UdpSocketManager object.
|
||||
// The most important property of these tests is that they do not leak memory.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
TEST(UdpSocketManager, CreateCallsInitAndDoesNotLeakMemory) {
|
||||
WebRtc_Word32 id = 42;
|
||||
WebRtc_UWord8 threads = 1;
|
||||
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
|
||||
// Create is supposed to have called init on the object.
|
||||
EXPECT_FALSE(mgr->Init(id, threads))
|
||||
<< "Init should return false since Create is supposed to call it.";
|
||||
UdpSocketManager::Return();
|
||||
}
|
||||
|
||||
// Creates a socket and adds it to the socket manager, and then removes it
|
||||
// before destroying the socket manager.
|
||||
TEST(UdpSocketManager, AddAndRemoveSocketDoesNotLeakMemory) {
|
||||
WebRtc_Word32 id = 42;
|
||||
WebRtc_UWord8 threads = 1;
|
||||
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
|
||||
UdpSocketWrapper* socket =
|
||||
UdpSocketWrapper::CreateSocket(id,
|
||||
mgr,
|
||||
NULL, // CallbackObj
|
||||
NULL, // IncomingSocketCallback
|
||||
false, // ipV6Enable
|
||||
false); // disableGQOS
|
||||
// The constructor will do AddSocket on the manager.
|
||||
// RemoveSocket indirectly calls Delete.
|
||||
EXPECT_EQ(true, mgr->RemoveSocket(socket));
|
||||
UdpSocketManager::Return();
|
||||
}
|
||||
|
||||
// Creates a socket and add it to the socket manager, but does not remove it
|
||||
// before destroying the socket manager.
|
||||
// On Posix, this destroys the socket.
|
||||
// On Winsock2 Windows, it enters an infinite wait for all the sockets
|
||||
// to go away.
|
||||
TEST(UdpSocketManager, UnremovedSocketsGetCollectedAtManagerDeletion) {
|
||||
#if defined(_WIN32)
|
||||
// It's hard to test an infinite wait, so we don't.
|
||||
#else
|
||||
WebRtc_Word32 id = 42;
|
||||
WebRtc_UWord8 threads = 1;
|
||||
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
|
||||
UdpSocketWrapper* unused_socket = UdpSocketWrapper::CreateSocket(
|
||||
id,
|
||||
mgr,
|
||||
NULL, // CallbackObj
|
||||
NULL, // IncomingSocketCallback
|
||||
false, // ipV6Enable
|
||||
false); // disableGQOS
|
||||
// The constructor will do AddSocket on the manager.
|
||||
// Call a member funtion to work around "set but not used" compliation
|
||||
// error on ChromeOS ARM.
|
||||
unused_socket->SetEventToNull();
|
||||
unused_socket = NULL;
|
||||
UdpSocketManager::Return();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
72
webrtc/test/channel_transport/udp_socket_manager_wrapper.cc
Normal file
72
webrtc/test/channel_transport/udp_socket_manager_wrapper.cc
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "webrtc/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket2_manager_win.h"
|
||||
#else
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_posix.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
UdpSocketManager* UdpSocketManager::CreateInstance()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return static_cast<UdpSocketManager*>(new UdpSocket2ManagerWindows());
|
||||
#else
|
||||
return new UdpSocketManagerPosix();
|
||||
#endif
|
||||
}
|
||||
|
||||
UdpSocketManager* UdpSocketManager::StaticInstance(
|
||||
CountOperation count_operation,
|
||||
const WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads)
|
||||
{
|
||||
UdpSocketManager* impl =
|
||||
GetStaticInstance<UdpSocketManager>(count_operation);
|
||||
if (count_operation == kAddRef && impl != NULL) {
|
||||
if (impl->Init(id, numOfWorkThreads)) {
|
||||
impl->Start();
|
||||
}
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
UdpSocketManager* UdpSocketManager::Create(const WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads)
|
||||
{
|
||||
return UdpSocketManager::StaticInstance(kAddRef, id, numOfWorkThreads);
|
||||
}
|
||||
|
||||
void UdpSocketManager::Return()
|
||||
{
|
||||
WebRtc_UWord8 numOfWorkThreads = 0;
|
||||
UdpSocketManager::StaticInstance(kRelease, -1,
|
||||
numOfWorkThreads);
|
||||
}
|
||||
|
||||
UdpSocketManager::UdpSocketManager() : _numOfWorkThreads(0)
|
||||
{
|
||||
}
|
||||
|
||||
WebRtc_UWord8 UdpSocketManager::WorkThreads() const
|
||||
{
|
||||
return _numOfWorkThreads;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
73
webrtc/test/channel_transport/udp_socket_manager_wrapper.h
Normal file
73
webrtc/test/channel_transport/udp_socket_manager_wrapper.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_MANAGER_WRAPPER_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_MANAGER_WRAPPER_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/static_instance.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class UdpSocketWrapper;
|
||||
|
||||
class UdpSocketManager
|
||||
{
|
||||
public:
|
||||
static UdpSocketManager* Create(const WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads);
|
||||
static void Return();
|
||||
|
||||
// Initializes the socket manager. Returns true if the manager wasn't
|
||||
// already initialized.
|
||||
virtual bool Init(WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads) = 0;
|
||||
|
||||
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id) = 0;
|
||||
|
||||
// Start listening to sockets that have been registered via the
|
||||
// AddSocket(..) API.
|
||||
virtual bool Start() = 0;
|
||||
// Stop listening to sockets.
|
||||
virtual bool Stop() = 0;
|
||||
|
||||
virtual WebRtc_UWord8 WorkThreads() const;
|
||||
|
||||
// Register a socket with the socket manager.
|
||||
virtual bool AddSocket(UdpSocketWrapper* s) = 0;
|
||||
// Unregister a socket from the manager.
|
||||
virtual bool RemoveSocket(UdpSocketWrapper* s) = 0;
|
||||
|
||||
protected:
|
||||
UdpSocketManager();
|
||||
virtual ~UdpSocketManager() {}
|
||||
|
||||
WebRtc_UWord8 _numOfWorkThreads;
|
||||
|
||||
// Factory method.
|
||||
static UdpSocketManager* CreateInstance();
|
||||
|
||||
private:
|
||||
// Friend function to allow the UDP destructor to be accessed from the
|
||||
// instance template.
|
||||
friend UdpSocketManager* webrtc::GetStaticInstance<UdpSocketManager>(
|
||||
CountOperation count_operation);
|
||||
|
||||
static UdpSocketManager* StaticInstance(
|
||||
CountOperation count_operation,
|
||||
const WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numOfWorkThreads);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_MANAGER_WRAPPER_H_
|
281
webrtc/test/channel_transport/udp_socket_posix.cc
Normal file
281
webrtc/test/channel_transport/udp_socket_posix.cc
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/test/channel_transport/udp_socket_posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
UdpSocketPosix::UdpSocketPosix(const WebRtc_Word32 id, UdpSocketManager* mgr,
|
||||
bool ipV6Enable)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
|
||||
"UdpSocketPosix::UdpSocketPosix()");
|
||||
|
||||
_wantsIncoming = false;
|
||||
_error = 0;
|
||||
_mgr = mgr;
|
||||
|
||||
_id = id;
|
||||
_obj = NULL;
|
||||
_incomingCb = NULL;
|
||||
_readyForDeletionCond = ConditionVariableWrapper::CreateConditionVariable();
|
||||
_closeBlockingCompletedCond =
|
||||
ConditionVariableWrapper::CreateConditionVariable();
|
||||
_cs = CriticalSectionWrapper::CreateCriticalSection();
|
||||
_readyForDeletion = false;
|
||||
_closeBlockingActive = false;
|
||||
_closeBlockingCompleted= false;
|
||||
if(ipV6Enable)
|
||||
{
|
||||
_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
}
|
||||
else {
|
||||
_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
}
|
||||
|
||||
// Set socket to nonblocking mode.
|
||||
int enable_non_blocking = 1;
|
||||
if(ioctl(_socket, FIONBIO, &enable_non_blocking) == -1)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceTransport, id,
|
||||
"Failed to make socket nonblocking");
|
||||
}
|
||||
// Enable close on fork for file descriptor so that it will not block until
|
||||
// forked process terminates.
|
||||
if(fcntl(_socket, F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceTransport, id,
|
||||
"Failed to set FD_CLOEXEC for socket");
|
||||
}
|
||||
}
|
||||
|
||||
UdpSocketPosix::~UdpSocketPosix()
|
||||
{
|
||||
if(_socket != INVALID_SOCKET)
|
||||
{
|
||||
close(_socket);
|
||||
_socket = INVALID_SOCKET;
|
||||
}
|
||||
if(_readyForDeletionCond)
|
||||
{
|
||||
delete _readyForDeletionCond;
|
||||
}
|
||||
|
||||
if(_closeBlockingCompletedCond)
|
||||
{
|
||||
delete _closeBlockingCompletedCond;
|
||||
}
|
||||
|
||||
if(_cs)
|
||||
{
|
||||
delete _cs;
|
||||
}
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocketPosix::ChangeUniqueId(const WebRtc_Word32 id)
|
||||
{
|
||||
_id = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UdpSocketPosix::SetCallback(CallbackObj obj, IncomingSocketCallback cb)
|
||||
{
|
||||
_obj = obj;
|
||||
_incomingCb = cb;
|
||||
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketPosix(%p)::SetCallback", this);
|
||||
|
||||
if (_mgr->AddSocket(this))
|
||||
{
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketPosix(%p)::SetCallback socket added to manager",
|
||||
this);
|
||||
return true; // socket is now ready for action
|
||||
}
|
||||
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"UdpSocketPosix(%p)::SetCallback error adding me to mgr",
|
||||
this);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UdpSocketPosix::SetSockopt(WebRtc_Word32 level, WebRtc_Word32 optname,
|
||||
const WebRtc_Word8* optval, WebRtc_Word32 optlen)
|
||||
{
|
||||
if(0 == setsockopt(_socket, level, optname, optval, optlen ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_error = errno;
|
||||
WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
|
||||
"UdpSocketPosix::SetSockopt(), error:%d", _error);
|
||||
return false;
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocketPosix::SetTOS(WebRtc_Word32 serviceType)
|
||||
{
|
||||
if (SetSockopt(IPPROTO_IP, IP_TOS ,(WebRtc_Word8*)&serviceType ,4) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UdpSocketPosix::Bind(const SocketAddress& name)
|
||||
{
|
||||
int size = sizeof(sockaddr);
|
||||
if (0 == bind(_socket, reinterpret_cast<const sockaddr*>(&name),size))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
_error = errno;
|
||||
WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
|
||||
"UdpSocketPosix::Bind() error: %d",_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
WebRtc_Word32 UdpSocketPosix::SendTo(const WebRtc_Word8* buf, WebRtc_Word32 len,
|
||||
const SocketAddress& to)
|
||||
{
|
||||
int size = sizeof(sockaddr);
|
||||
int retVal = sendto(_socket,buf, len, 0,
|
||||
reinterpret_cast<const sockaddr*>(&to), size);
|
||||
if(retVal == SOCKET_ERROR)
|
||||
{
|
||||
_error = errno;
|
||||
WEBRTC_TRACE(kTraceError, kTraceTransport, _id,
|
||||
"UdpSocketPosix::SendTo() error: %d", _error);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool UdpSocketPosix::ValidHandle()
|
||||
{
|
||||
return _socket != INVALID_SOCKET;
|
||||
}
|
||||
|
||||
void UdpSocketPosix::HasIncoming()
|
||||
{
|
||||
// replace 2048 with a mcro define and figure out
|
||||
// where 2048 comes from
|
||||
WebRtc_Word8 buf[2048];
|
||||
int retval;
|
||||
SocketAddress from;
|
||||
#if defined(WEBRTC_MAC)
|
||||
sockaddr sockaddrfrom;
|
||||
memset(&from, 0, sizeof(from));
|
||||
memset(&sockaddrfrom, 0, sizeof(sockaddrfrom));
|
||||
socklen_t fromlen = sizeof(sockaddrfrom);
|
||||
#else
|
||||
memset(&from, 0, sizeof(from));
|
||||
socklen_t fromlen = sizeof(from);
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_MAC)
|
||||
retval = recvfrom(_socket,buf, sizeof(buf), 0,
|
||||
reinterpret_cast<sockaddr*>(&sockaddrfrom), &fromlen);
|
||||
memcpy(&from, &sockaddrfrom, fromlen);
|
||||
from._sockaddr_storage.sin_family = sockaddrfrom.sa_family;
|
||||
#else
|
||||
retval = recvfrom(_socket,buf, sizeof(buf), 0,
|
||||
reinterpret_cast<sockaddr*>(&from), &fromlen);
|
||||
#endif
|
||||
|
||||
switch(retval)
|
||||
{
|
||||
case 0:
|
||||
// The peer has performed an orderly shutdown.
|
||||
break;
|
||||
case SOCKET_ERROR:
|
||||
break;
|
||||
default:
|
||||
if (_wantsIncoming && _incomingCb)
|
||||
{
|
||||
_incomingCb(_obj, buf, retval, &from);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UdpSocketPosix::CloseBlocking()
|
||||
{
|
||||
_cs->Enter();
|
||||
_closeBlockingActive = true;
|
||||
if(!CleanUp())
|
||||
{
|
||||
_closeBlockingActive = false;
|
||||
_cs->Leave();
|
||||
return;
|
||||
}
|
||||
|
||||
while(!_readyForDeletion)
|
||||
{
|
||||
_readyForDeletionCond->SleepCS(*_cs);
|
||||
}
|
||||
_closeBlockingCompleted = true;
|
||||
_closeBlockingCompletedCond->Wake();
|
||||
_cs->Leave();
|
||||
}
|
||||
|
||||
void UdpSocketPosix::ReadyForDeletion()
|
||||
{
|
||||
_cs->Enter();
|
||||
if(!_closeBlockingActive)
|
||||
{
|
||||
_cs->Leave();
|
||||
return;
|
||||
}
|
||||
close(_socket);
|
||||
_socket = INVALID_SOCKET;
|
||||
_readyForDeletion = true;
|
||||
_readyForDeletionCond->Wake();
|
||||
while(!_closeBlockingCompleted)
|
||||
{
|
||||
_closeBlockingCompletedCond->SleepCS(*_cs);
|
||||
}
|
||||
_cs->Leave();
|
||||
}
|
||||
|
||||
bool UdpSocketPosix::CleanUp()
|
||||
{
|
||||
_wantsIncoming = false;
|
||||
|
||||
if (_socket == INVALID_SOCKET)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
|
||||
"calling UdpSocketManager::RemoveSocket()...");
|
||||
_mgr->RemoveSocket(this);
|
||||
// After this, the socket should may be or will be as deleted. Return
|
||||
// immediately.
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
95
webrtc/test/channel_transport/udp_socket_posix.h
Normal file
95
webrtc/test/channel_transport/udp_socket_posix.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_POSIX_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_POSIX_H_
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
#define SOCKET_ERROR -1
|
||||
|
||||
class UdpSocketPosix : public UdpSocketWrapper
|
||||
{
|
||||
public:
|
||||
UdpSocketPosix(const WebRtc_Word32 id, UdpSocketManager* mgr,
|
||||
bool ipV6Enable = false);
|
||||
|
||||
virtual ~UdpSocketPosix();
|
||||
|
||||
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id);
|
||||
|
||||
virtual bool SetCallback(CallbackObj obj, IncomingSocketCallback cb);
|
||||
|
||||
virtual bool Bind(const SocketAddress& name);
|
||||
|
||||
virtual bool SetSockopt(WebRtc_Word32 level, WebRtc_Word32 optname,
|
||||
const WebRtc_Word8* optval, WebRtc_Word32 optlen);
|
||||
|
||||
virtual WebRtc_Word32 SetTOS(const WebRtc_Word32 serviceType);
|
||||
|
||||
virtual WebRtc_Word32 SendTo(const WebRtc_Word8* buf, WebRtc_Word32 len,
|
||||
const SocketAddress& to);
|
||||
|
||||
// Deletes socket in addition to closing it.
|
||||
// TODO (hellner): make destructor protected.
|
||||
virtual void CloseBlocking();
|
||||
|
||||
virtual SOCKET GetFd() {return _socket;}
|
||||
virtual WebRtc_Word32 GetError() {return _error;}
|
||||
|
||||
virtual bool ValidHandle();
|
||||
|
||||
virtual bool SetQos(WebRtc_Word32 /*serviceType*/,
|
||||
WebRtc_Word32 /*tokenRate*/,
|
||||
WebRtc_Word32 /*bucketSize*/,
|
||||
WebRtc_Word32 /*peekBandwith*/,
|
||||
WebRtc_Word32 /*minPolicedSize*/,
|
||||
WebRtc_Word32 /*maxSduSize*/,
|
||||
const SocketAddress& /*stRemName*/,
|
||||
WebRtc_Word32 /*overrideDSCP*/) {return false;}
|
||||
|
||||
bool CleanUp();
|
||||
void HasIncoming();
|
||||
bool WantsIncoming() {return _wantsIncoming;}
|
||||
void ReadyForDeletion();
|
||||
private:
|
||||
friend class UdpSocketManagerPosix;
|
||||
|
||||
WebRtc_Word32 _id;
|
||||
IncomingSocketCallback _incomingCb;
|
||||
CallbackObj _obj;
|
||||
WebRtc_Word32 _error;
|
||||
|
||||
SOCKET _socket;
|
||||
UdpSocketManager* _mgr;
|
||||
ConditionVariableWrapper* _closeBlockingCompletedCond;
|
||||
ConditionVariableWrapper* _readyForDeletionCond;
|
||||
|
||||
bool _closeBlockingActive;
|
||||
bool _closeBlockingCompleted;
|
||||
bool _readyForDeletion;
|
||||
|
||||
CriticalSectionWrapper* _cs;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_POSIX_H_
|
151
webrtc/test/channel_transport/udp_socket_wrapper.cc
Normal file
151
webrtc/test/channel_transport/udp_socket_wrapper.cc
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/event_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "webrtc/test/channel_transport/udp_socket2_win.h"
|
||||
#else
|
||||
#include "webrtc/test/channel_transport/udp_socket_posix.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
bool UdpSocketWrapper::_initiated = false;
|
||||
|
||||
// Temporary Android hack. The value 1024 is taken from
|
||||
// <ndk>/build/platforms/android-1.5/arch-arm/usr/include/linux/posix_types.h
|
||||
// TODO (tomasl): can we remove this now?
|
||||
#ifndef FD_SETSIZE
|
||||
#define FD_SETSIZE 1024
|
||||
#endif
|
||||
|
||||
UdpSocketWrapper::UdpSocketWrapper()
|
||||
: _wantsIncoming(false),
|
||||
_deleteEvent(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
UdpSocketWrapper::~UdpSocketWrapper()
|
||||
{
|
||||
if(_deleteEvent)
|
||||
{
|
||||
_deleteEvent->Set();
|
||||
_deleteEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void UdpSocketWrapper::SetEventToNull()
|
||||
{
|
||||
if (_deleteEvent)
|
||||
{
|
||||
_deleteEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
UdpSocketWrapper* UdpSocketWrapper::CreateSocket(const WebRtc_Word32 id,
|
||||
UdpSocketManager* mgr,
|
||||
CallbackObj obj,
|
||||
IncomingSocketCallback cb,
|
||||
bool ipV6Enable,
|
||||
bool disableGQOS)
|
||||
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceTransport, id,
|
||||
"UdpSocketWrapper::CreateSocket");
|
||||
|
||||
UdpSocketWrapper* s = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!_initiated)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
WORD wVersionRequested = MAKEWORD( 2, 2 );
|
||||
WebRtc_Word32 err = WSAStartup( wVersionRequested, &wsaData);
|
||||
if (err != 0)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
id,
|
||||
"UdpSocketWrapper::CreateSocket failed to initialize sockets\
|
||||
WSAStartup error:%d",
|
||||
err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_initiated = true;
|
||||
}
|
||||
|
||||
s = new UdpSocket2Windows(id, mgr, ipV6Enable, disableGQOS);
|
||||
|
||||
#else
|
||||
if (!_initiated)
|
||||
{
|
||||
_initiated = true;
|
||||
}
|
||||
s = new UdpSocketPosix(id, mgr, ipV6Enable);
|
||||
if (s)
|
||||
{
|
||||
UdpSocketPosix* sl = static_cast<UdpSocketPosix*>(s);
|
||||
if (sl->GetFd() != INVALID_SOCKET && sl->GetFd() < FD_SETSIZE)
|
||||
{
|
||||
// ok
|
||||
} else
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
id,
|
||||
"UdpSocketWrapper::CreateSocket failed to initialize socket");
|
||||
delete s;
|
||||
s = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (s)
|
||||
{
|
||||
s->_deleteEvent = NULL;
|
||||
if (!s->SetCallback(obj, cb))
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceError,
|
||||
kTraceTransport,
|
||||
id,
|
||||
"UdpSocketWrapper::CreateSocket failed to ser callback");
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool UdpSocketWrapper::StartReceiving()
|
||||
{
|
||||
_wantsIncoming = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSocketWrapper::StopReceiving()
|
||||
{
|
||||
_wantsIncoming = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
118
webrtc/test/channel_transport/udp_socket_wrapper.h
Normal file
118
webrtc/test/channel_transport/udp_socket_wrapper.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_WRAPPER_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_WRAPPER_H_
|
||||
|
||||
#include "webrtc/test/channel_transport/udp_transport.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class EventWrapper;
|
||||
|
||||
namespace test {
|
||||
|
||||
class UdpSocketManager;
|
||||
|
||||
#define SOCKET_ERROR_NO_QOS -1000
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef int SOCKET;
|
||||
#endif
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
|
||||
#ifndef AF_INET
|
||||
#define AF_INET 2
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef void* CallbackObj;
|
||||
typedef void(*IncomingSocketCallback)(CallbackObj obj, const WebRtc_Word8* buf,
|
||||
WebRtc_Word32 len,
|
||||
const SocketAddress* from);
|
||||
|
||||
class UdpSocketWrapper
|
||||
{
|
||||
public:
|
||||
static UdpSocketWrapper* CreateSocket(const WebRtc_Word32 id,
|
||||
UdpSocketManager* mgr,
|
||||
CallbackObj obj,
|
||||
IncomingSocketCallback cb,
|
||||
bool ipV6Enable = false,
|
||||
bool disableGQOS = false);
|
||||
|
||||
// Set the unique identifier of this class to id.
|
||||
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id) = 0;
|
||||
|
||||
// Register cb for receiving callbacks when there are incoming packets.
|
||||
// Register obj so that it will be passed in calls to cb.
|
||||
virtual bool SetCallback(CallbackObj obj, IncomingSocketCallback cb) = 0;
|
||||
|
||||
// Socket to local address specified by name.
|
||||
virtual bool Bind(const SocketAddress& name) = 0;
|
||||
|
||||
// Start receiving UDP data.
|
||||
virtual bool StartReceiving();
|
||||
virtual inline bool StartReceiving(const WebRtc_UWord32 /*receiveBuffers*/)
|
||||
{return StartReceiving();}
|
||||
// Stop receiving UDP data.
|
||||
virtual bool StopReceiving();
|
||||
|
||||
virtual bool ValidHandle() = 0;
|
||||
|
||||
// Set socket options.
|
||||
virtual bool SetSockopt(WebRtc_Word32 level, WebRtc_Word32 optname,
|
||||
const WebRtc_Word8* optval,
|
||||
WebRtc_Word32 optlen) = 0;
|
||||
|
||||
// Set TOS for outgoing packets.
|
||||
virtual WebRtc_Word32 SetTOS(const WebRtc_Word32 serviceType) = 0;
|
||||
|
||||
// Set 802.1Q PCP field (802.1p) for outgoing VLAN traffic.
|
||||
virtual WebRtc_Word32 SetPCP(const WebRtc_Word32 /*pcp*/) {return -1;}
|
||||
|
||||
// Send buf of length len to the address specified by to.
|
||||
virtual WebRtc_Word32 SendTo(const WebRtc_Word8* buf, WebRtc_Word32 len,
|
||||
const SocketAddress& to) = 0;
|
||||
|
||||
virtual void SetEventToNull();
|
||||
|
||||
// Close socket and don't return until completed.
|
||||
virtual void CloseBlocking() {}
|
||||
|
||||
// tokenRate is in bit/s. peakBandwidt is in byte/s
|
||||
virtual bool SetQos(WebRtc_Word32 serviceType, WebRtc_Word32 tokenRate,
|
||||
WebRtc_Word32 bucketSize, WebRtc_Word32 peekBandwith,
|
||||
WebRtc_Word32 minPolicedSize, WebRtc_Word32 maxSduSize,
|
||||
const SocketAddress &stRemName,
|
||||
WebRtc_Word32 overrideDSCP = 0) = 0;
|
||||
|
||||
virtual WebRtc_UWord32 ReceiveBuffers() {return 0;};
|
||||
|
||||
protected:
|
||||
// Creating the socket is done via CreateSocket().
|
||||
UdpSocketWrapper();
|
||||
// Destroying the socket is done via CloseBlocking().
|
||||
virtual ~UdpSocketWrapper();
|
||||
|
||||
bool _wantsIncoming;
|
||||
EventWrapper* _deleteEvent;
|
||||
|
||||
private:
|
||||
static bool _initiated;
|
||||
};
|
||||
|
||||
} // namespac test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET_WRAPPER_H_
|
68
webrtc/test/channel_transport/udp_socket_wrapper_unittest.cc
Normal file
68
webrtc/test/channel_transport/udp_socket_wrapper_unittest.cc
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Tests for the UdpSocketWrapper interface.
|
||||
// This will test the UdpSocket implementations on various platforms.
|
||||
// Note that this test is using a real SocketManager, which starts up
|
||||
// an extra worker thread, making the testing more complex than it
|
||||
// should be.
|
||||
// This is because on Posix, the CloseBlocking function waits for the
|
||||
// ReadyForDeletion function to be called, which has to be called after
|
||||
// CloseBlocking, and thus has to be called from another thread.
|
||||
// The manager is the one actually doing the deleting.
|
||||
// This is done differently in the Winsock2 code, but that code
|
||||
// will also hang if the destructor is called directly.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class MockSocketManager : public UdpSocketManager {
|
||||
public:
|
||||
MockSocketManager() {}
|
||||
// Access to protected destructor.
|
||||
void Destroy() {
|
||||
delete this;
|
||||
}
|
||||
MOCK_METHOD2(Init, bool(WebRtc_Word32, WebRtc_UWord8&));
|
||||
MOCK_METHOD1(ChangeUniqueId, WebRtc_Word32(const WebRtc_Word32));
|
||||
MOCK_METHOD0(Start, bool());
|
||||
MOCK_METHOD0(Stop, bool());
|
||||
MOCK_METHOD1(AddSocket, bool(UdpSocketWrapper*));
|
||||
MOCK_METHOD1(RemoveSocket, bool(UdpSocketWrapper*));
|
||||
};
|
||||
|
||||
// Creates a socket using the static constructor method and verifies that
|
||||
// it's added to the socket manager.
|
||||
TEST(UdpSocketWrapper, CreateSocket) {
|
||||
WebRtc_Word32 id = 42;
|
||||
// We can't test deletion of sockets without a socket manager.
|
||||
WebRtc_UWord8 threads = 1;
|
||||
UdpSocketManager* mgr = UdpSocketManager::Create(id, threads);
|
||||
UdpSocketWrapper* socket =
|
||||
UdpSocketWrapper::CreateSocket(id,
|
||||
mgr,
|
||||
NULL, // CallbackObj
|
||||
NULL, // IncomingSocketCallback
|
||||
false, // ipV6Enable
|
||||
false); // disableGQOS
|
||||
socket->CloseBlocking();
|
||||
UdpSocketManager::Return();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
386
webrtc/test/channel_transport/udp_transport.h
Normal file
386
webrtc/test/channel_transport/udp_transport.h
Normal file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
/*
|
||||
* WARNING
|
||||
* This code is not use in production/testing and might have security issues
|
||||
* for example: http://code.google.com/p/webrtc/issues/detail?id=1028
|
||||
*
|
||||
*/
|
||||
|
||||
#define SS_MAXSIZE 128
|
||||
#define SS_ALIGNSIZE (sizeof (WebRtc_UWord64))
|
||||
#define SS_PAD1SIZE (SS_ALIGNSIZE - sizeof(WebRtc_Word16))
|
||||
#define SS_PAD2SIZE (SS_MAXSIZE - (sizeof(WebRtc_Word16) + SS_PAD1SIZE +\
|
||||
SS_ALIGNSIZE))
|
||||
|
||||
// BSD requires use of HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
struct SocketAddressIn {
|
||||
// sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6)
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
WebRtc_Word8 sin_length;
|
||||
WebRtc_Word8 sin_family;
|
||||
#else
|
||||
WebRtc_Word16 sin_family;
|
||||
#endif
|
||||
WebRtc_UWord16 sin_port;
|
||||
WebRtc_UWord32 sin_addr;
|
||||
WebRtc_Word8 sin_zero[8];
|
||||
};
|
||||
|
||||
struct Version6InAddress {
|
||||
union {
|
||||
WebRtc_UWord8 _s6_u8[16];
|
||||
WebRtc_UWord32 _s6_u32[4];
|
||||
WebRtc_UWord64 _s6_u64[2];
|
||||
} Version6AddressUnion;
|
||||
};
|
||||
|
||||
struct SocketAddressInVersion6 {
|
||||
// sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6)
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
WebRtc_Word8 sin_length;
|
||||
WebRtc_Word8 sin_family;
|
||||
#else
|
||||
WebRtc_Word16 sin_family;
|
||||
#endif
|
||||
// Transport layer port number.
|
||||
WebRtc_UWord16 sin6_port;
|
||||
// IPv6 traffic class and flow info or ip4 address.
|
||||
WebRtc_UWord32 sin6_flowinfo;
|
||||
// IPv6 address
|
||||
struct Version6InAddress sin6_addr;
|
||||
// Set of interfaces for a scope.
|
||||
WebRtc_UWord32 sin6_scope_id;
|
||||
};
|
||||
|
||||
struct SocketAddressStorage {
|
||||
// sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6)
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
WebRtc_Word8 sin_length;
|
||||
WebRtc_Word8 sin_family;
|
||||
#else
|
||||
WebRtc_Word16 sin_family;
|
||||
#endif
|
||||
WebRtc_Word8 __ss_pad1[SS_PAD1SIZE];
|
||||
WebRtc_UWord64 __ss_align;
|
||||
WebRtc_Word8 __ss_pad2[SS_PAD2SIZE];
|
||||
};
|
||||
|
||||
struct SocketAddress {
|
||||
union {
|
||||
struct SocketAddressIn _sockaddr_in;
|
||||
struct SocketAddressInVersion6 _sockaddr_in6;
|
||||
struct SocketAddressStorage _sockaddr_storage;
|
||||
};
|
||||
};
|
||||
|
||||
// Callback class that receives packets from UdpTransport.
|
||||
class UdpTransportData {
|
||||
public:
|
||||
virtual ~UdpTransportData() {};
|
||||
|
||||
virtual void IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket,
|
||||
const WebRtc_Word32 rtpPacketLength,
|
||||
const char* fromIP,
|
||||
const WebRtc_UWord16 fromPort) = 0;
|
||||
|
||||
virtual void IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket,
|
||||
const WebRtc_Word32 rtcpPacketLength,
|
||||
const char* fromIP,
|
||||
const WebRtc_UWord16 fromPort) = 0;
|
||||
};
|
||||
|
||||
class UdpTransport : public Transport {
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kIpAddressVersion6Length = 64,
|
||||
kIpAddressVersion4Length = 16
|
||||
};
|
||||
enum ErrorCode
|
||||
{
|
||||
kNoSocketError = 0,
|
||||
kFailedToBindPort = 1,
|
||||
kIpAddressInvalid = 2,
|
||||
kAddressInvalid = 3,
|
||||
kSocketInvalid = 4,
|
||||
kPortInvalid = 5,
|
||||
kTosInvalid = 6,
|
||||
kMulticastAddressInvalid = 7,
|
||||
kQosError = 8,
|
||||
kSocketAlreadyInitialized = 9,
|
||||
kIpVersion6Error = 10,
|
||||
FILTER_ERROR = 11,
|
||||
kStartReceiveError = 12,
|
||||
kStopReceiveError = 13,
|
||||
kCannotFindLocalIp = 14,
|
||||
kTosError = 16,
|
||||
kNotInitialized = 17,
|
||||
kPcpError = 18
|
||||
};
|
||||
|
||||
// Factory method. Constructor disabled.
|
||||
static UdpTransport* Create(const WebRtc_Word32 id,
|
||||
WebRtc_UWord8& numSocketThreads);
|
||||
static void Destroy(UdpTransport* module);
|
||||
|
||||
// Prepares the class for sending RTP packets to ipAddr:rtpPort and RTCP
|
||||
// packets to ipAddr:rtpPort+1 if rtcpPort is zero. Otherwise to
|
||||
// ipAddr:rtcpPort.
|
||||
virtual WebRtc_Word32 InitializeSendSockets(
|
||||
const char* ipAddr,
|
||||
const WebRtc_UWord16 rtpPort,
|
||||
const WebRtc_UWord16 rtcpPort = 0) = 0;
|
||||
|
||||
// Register packetCallback for receiving incoming packets. Set the local
|
||||
// RTP port to rtpPort. Bind local IP address to ipAddr. If ipAddr is NULL
|
||||
// bind to local IP ANY. Set the local rtcp port to rtcpPort or rtpPort + 1
|
||||
// if rtcpPort is 0.
|
||||
virtual WebRtc_Word32 InitializeReceiveSockets(
|
||||
UdpTransportData* const packetCallback,
|
||||
const WebRtc_UWord16 rtpPort,
|
||||
const char* ipAddr = NULL,
|
||||
const char* multicastIpAddr = NULL,
|
||||
const WebRtc_UWord16 rtcpPort = 0) = 0;
|
||||
|
||||
// Set local RTP port to rtpPort and RTCP port to rtcpPort or rtpPort + 1 if
|
||||
// rtcpPort is 0. These ports will be used for sending instead of the local
|
||||
// ports set by InitializeReceiveSockets(..).
|
||||
virtual WebRtc_Word32 InitializeSourcePorts(
|
||||
const WebRtc_UWord16 rtpPort,
|
||||
const WebRtc_UWord16 rtcpPort = 0) = 0;
|
||||
|
||||
// Retrieve local ports used for sending if other than the ports specified
|
||||
// by InitializeReceiveSockets(..). rtpPort is set to the RTP port.
|
||||
// rtcpPort is set to the RTCP port.
|
||||
virtual WebRtc_Word32 SourcePorts(WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort) const = 0;
|
||||
|
||||
// Set ipAddr to the IP address that is currently being listened on. rtpPort
|
||||
// to the RTP port listened to. rtcpPort to the RTCP port listened on.
|
||||
// multicastIpAddr to the multicast IP address group joined (the address
|
||||
// is NULL terminated).
|
||||
virtual WebRtc_Word32 ReceiveSocketInformation(
|
||||
char ipAddr[kIpAddressVersion6Length],
|
||||
WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort,
|
||||
char multicastIpAddr[kIpAddressVersion6Length]) const = 0;
|
||||
|
||||
// Set ipAddr to the IP address being sent from. rtpPort to the local RTP
|
||||
// port used for sending and rtcpPort to the local RTCP port used for
|
||||
// sending.
|
||||
virtual WebRtc_Word32 SendSocketInformation(
|
||||
char ipAddr[kIpAddressVersion6Length],
|
||||
WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort) const = 0;
|
||||
|
||||
// Put the IP address, RTP port and RTCP port from the last received packet
|
||||
// into ipAddr, rtpPort and rtcpPort respectively.
|
||||
virtual WebRtc_Word32 RemoteSocketInformation(
|
||||
char ipAddr[kIpAddressVersion6Length],
|
||||
WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort) const = 0;
|
||||
|
||||
// Enable/disable quality of service if QoS is true or false respectively.
|
||||
// Set the type of service to serviceType, max bitrate in kbit/s to
|
||||
// maxBitrate and override DSCP if overrideDSCP is not 0.
|
||||
// Note: Must be called both InitializeSendSockets() and
|
||||
// InitializeReceiveSockets() has been called.
|
||||
virtual WebRtc_Word32 SetQoS(const bool QoS,
|
||||
const WebRtc_Word32 serviceType,
|
||||
const WebRtc_UWord32 maxBitrate = 0,
|
||||
const WebRtc_Word32 overrideDSCP = 0,
|
||||
const bool audio = false) = 0;
|
||||
|
||||
// Set QoS to true if quality of service has been turned on. If QoS is true,
|
||||
// also set serviceType to type of service and overrideDSCP to override
|
||||
// DSCP.
|
||||
virtual WebRtc_Word32 QoS(bool& QoS,
|
||||
WebRtc_Word32& serviceType,
|
||||
WebRtc_Word32& overrideDSCP) const = 0;
|
||||
|
||||
// Set type of service.
|
||||
virtual WebRtc_Word32 SetToS(const WebRtc_Word32 DSCP,
|
||||
const bool useSetSockOpt = false) = 0;
|
||||
|
||||
// Get type of service configuration.
|
||||
virtual WebRtc_Word32 ToS(WebRtc_Word32& DSCP,
|
||||
bool& useSetSockOpt) const = 0;
|
||||
|
||||
// Set Priority Code Point (IEEE 802.1Q)
|
||||
// Note: for Linux this function will set the priority for the socket,
|
||||
// which then can be mapped to a PCP value with vconfig.
|
||||
virtual WebRtc_Word32 SetPCP(const WebRtc_Word32 PCP) = 0;
|
||||
|
||||
// Get Priority Code Point
|
||||
virtual WebRtc_Word32 PCP(WebRtc_Word32& PCP) const = 0;
|
||||
|
||||
// Enable IPv6.
|
||||
// Note: this API must be called before any call to
|
||||
// InitializeReceiveSockets() or InitializeSendSockets(). It is not
|
||||
// possible to go back to IPv4 (default) after this call.
|
||||
virtual WebRtc_Word32 EnableIpV6() = 0;
|
||||
|
||||
// Return true if IPv6 has been enabled.
|
||||
virtual bool IpV6Enabled() const = 0;
|
||||
|
||||
// Only allow packets received from filterIPAddress to be processed.
|
||||
// Note: must be called after EnableIPv6(), if IPv6 is used.
|
||||
virtual WebRtc_Word32 SetFilterIP(
|
||||
const char filterIPAddress[kIpAddressVersion6Length]) = 0;
|
||||
|
||||
// Write the filter IP address (if any) to filterIPAddress.
|
||||
virtual WebRtc_Word32 FilterIP(
|
||||
char filterIPAddress[kIpAddressVersion6Length]) const = 0;
|
||||
|
||||
// Only allow RTP packets from rtpFilterPort and RTCP packets from
|
||||
// rtcpFilterPort be processed.
|
||||
// Note: must be called after EnableIPv6(), if IPv6 is used.
|
||||
virtual WebRtc_Word32 SetFilterPorts(
|
||||
const WebRtc_UWord16 rtpFilterPort,
|
||||
const WebRtc_UWord16 rtcpFilterPort) = 0;
|
||||
|
||||
// Set rtpFilterPort to the filter RTP port and rtcpFilterPort to the
|
||||
// filter RTCP port (if filtering based on port is enabled).
|
||||
virtual WebRtc_Word32 FilterPorts(WebRtc_UWord16& rtpFilterPort,
|
||||
WebRtc_UWord16& rtcpFilterPort) const = 0;
|
||||
|
||||
// Set the number of buffers that the socket implementation may use for
|
||||
// receiving packets to numberOfSocketBuffers. I.e. the number of packets
|
||||
// that can be received in parallell.
|
||||
// Note: this API only has effect on Windows.
|
||||
virtual WebRtc_Word32 StartReceiving(
|
||||
const WebRtc_UWord32 numberOfSocketBuffers) = 0;
|
||||
|
||||
// Stop receive incoming packets.
|
||||
virtual WebRtc_Word32 StopReceiving() = 0;
|
||||
|
||||
// Return true incoming packets are received.
|
||||
virtual bool Receiving() const = 0;
|
||||
|
||||
// Return true if send sockets have been initialized.
|
||||
virtual bool SendSocketsInitialized() const = 0;
|
||||
|
||||
// Return true if local ports for sending has been set.
|
||||
virtual bool SourcePortsInitialized() const = 0;
|
||||
|
||||
// Return true if receive sockets have been initialized.
|
||||
virtual bool ReceiveSocketsInitialized() const = 0;
|
||||
|
||||
// Send data with size length to ip:portnr. The same port as the set
|
||||
// with InitializeSendSockets(..) is used if portnr is 0. The same IP
|
||||
// address as set with InitializeSendSockets(..) is used if ip is NULL.
|
||||
// If isRTCP is true the port used will be the RTCP port.
|
||||
virtual WebRtc_Word32 SendRaw(const WebRtc_Word8* data,
|
||||
WebRtc_UWord32 length,
|
||||
WebRtc_Word32 isRTCP,
|
||||
WebRtc_UWord16 portnr = 0,
|
||||
const char* ip = NULL) = 0;
|
||||
|
||||
// Send RTP data with size length to the address specified by to.
|
||||
virtual WebRtc_Word32 SendRTPPacketTo(const WebRtc_Word8* data,
|
||||
WebRtc_UWord32 length,
|
||||
const SocketAddress& to) = 0;
|
||||
|
||||
|
||||
// Send RTCP data with size length to the address specified by to.
|
||||
virtual WebRtc_Word32 SendRTCPPacketTo(const WebRtc_Word8* data,
|
||||
WebRtc_UWord32 length,
|
||||
const SocketAddress& to) = 0;
|
||||
|
||||
// Send RTP data with size length to ip:rtpPort where ip is the ip set by
|
||||
// the InitializeSendSockets(..) call.
|
||||
virtual WebRtc_Word32 SendRTPPacketTo(const WebRtc_Word8* data,
|
||||
WebRtc_UWord32 length,
|
||||
WebRtc_UWord16 rtpPort) = 0;
|
||||
|
||||
|
||||
// Send RTCP data with size length to ip:rtcpPort where ip is the ip set by
|
||||
// the InitializeSendSockets(..) call.
|
||||
virtual WebRtc_Word32 SendRTCPPacketTo(const WebRtc_Word8* data,
|
||||
WebRtc_UWord32 length,
|
||||
WebRtc_UWord16 rtcpPort) = 0;
|
||||
|
||||
// Set the IP address to which packets are sent to ipaddr.
|
||||
virtual WebRtc_Word32 SetSendIP(
|
||||
const char ipaddr[kIpAddressVersion6Length]) = 0;
|
||||
|
||||
// Set the send RTP and RTCP port to rtpPort and rtcpPort respectively.
|
||||
virtual WebRtc_Word32 SetSendPorts(const WebRtc_UWord16 rtpPort,
|
||||
const WebRtc_UWord16 rtcpPort = 0) = 0;
|
||||
|
||||
// Retreive the last registered error code.
|
||||
virtual ErrorCode LastError() const = 0;
|
||||
|
||||
// Put the local IPv4 address in localIP.
|
||||
// Note: this API is for IPv4 only.
|
||||
static WebRtc_Word32 LocalHostAddress(WebRtc_UWord32& localIP);
|
||||
|
||||
// Put the local IP6 address in localIP.
|
||||
// Note: this API is for IPv6 only.
|
||||
static WebRtc_Word32 LocalHostAddressIPV6(char localIP[16]);
|
||||
|
||||
// Return a copy of hostOrder (host order) in network order.
|
||||
static WebRtc_UWord16 Htons(WebRtc_UWord16 hostOrder);
|
||||
|
||||
// Return a copy of hostOrder (host order) in network order.
|
||||
static WebRtc_UWord32 Htonl(WebRtc_UWord32 hostOrder);
|
||||
|
||||
// Return IPv4 address in ip as 32 bit integer.
|
||||
static WebRtc_UWord32 InetAddrIPV4(const char* ip);
|
||||
|
||||
// Convert the character string src into a network address structure in
|
||||
// the af address family and put it in dst.
|
||||
// Note: same functionality as inet_pton(..)
|
||||
static WebRtc_Word32 InetPresentationToNumeric(WebRtc_Word32 af,
|
||||
const char* src,
|
||||
void* dst);
|
||||
|
||||
// Set ip and sourcePort according to address. As input parameter ipSize
|
||||
// is the length of ip. As output parameter it's the number of characters
|
||||
// written to ip (not counting the '\0' character).
|
||||
// Note: this API is only implemented on Windows and Linux.
|
||||
static WebRtc_Word32 IPAddress(const SocketAddress& address,
|
||||
char* ip,
|
||||
WebRtc_UWord32& ipSize,
|
||||
WebRtc_UWord16& sourcePort);
|
||||
|
||||
// Set ip and sourcePort according to address. As input parameter ipSize
|
||||
// is the length of ip. As output parameter it's the number of characters
|
||||
// written to ip (not counting the '\0' character).
|
||||
// Note: this API is only implemented on Windows and Linux.
|
||||
// Additional note: this API caches the address of the last call to it. If
|
||||
// address is likley to be the same for multiple calls it may be beneficial
|
||||
// to call this API instead of IPAddress().
|
||||
virtual WebRtc_Word32 IPAddressCached(const SocketAddress& address,
|
||||
char* ip,
|
||||
WebRtc_UWord32& ipSize,
|
||||
WebRtc_UWord16& sourcePort) = 0;
|
||||
|
||||
// Return true if ipaddr is a valid IP address.
|
||||
// If ipV6 is false ipaddr is interpreted as an IPv4 address otherwise it
|
||||
// is interptreted as IPv6.
|
||||
static bool IsIpAddressValid(const char* ipaddr, const bool ipV6);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_H_
|
2999
webrtc/test/channel_transport/udp_transport_impl.cc
Normal file
2999
webrtc/test/channel_transport/udp_transport_impl.cc
Normal file
File diff suppressed because it is too large
Load Diff
264
webrtc/test/channel_transport/udp_transport_impl.h
Normal file
264
webrtc/test/channel_transport/udp_transport_impl.h
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_IMPL_H_
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_IMPL_H_
|
||||
|
||||
#include "webrtc/test/channel_transport/udp_transport.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
class RWLockWrapper;
|
||||
|
||||
namespace test {
|
||||
|
||||
class UdpSocketManager;
|
||||
|
||||
class UdpTransportImpl : public UdpTransport
|
||||
{
|
||||
public:
|
||||
// A factory that returns a wrapped UDP socket or equivalent.
|
||||
class SocketFactoryInterface {
|
||||
public:
|
||||
virtual ~SocketFactoryInterface() {}
|
||||
virtual UdpSocketWrapper* CreateSocket(const WebRtc_Word32 id,
|
||||
UdpSocketManager* mgr,
|
||||
CallbackObj obj,
|
||||
IncomingSocketCallback cb,
|
||||
bool ipV6Enable,
|
||||
bool disableGQOS) = 0;
|
||||
};
|
||||
|
||||
// Constructor, only called by UdpTransport::Create and tests.
|
||||
// The constructor takes ownership of the "maker".
|
||||
// The constructor does not take ownership of socket_manager.
|
||||
UdpTransportImpl(const WebRtc_Word32 id,
|
||||
SocketFactoryInterface* maker,
|
||||
UdpSocketManager* socket_manager);
|
||||
virtual ~UdpTransportImpl();
|
||||
|
||||
// UdpTransport functions
|
||||
virtual WebRtc_Word32 InitializeSendSockets(
|
||||
const char* ipAddr,
|
||||
const WebRtc_UWord16 rtpPort,
|
||||
const WebRtc_UWord16 rtcpPort = 0);
|
||||
virtual WebRtc_Word32 InitializeReceiveSockets(
|
||||
UdpTransportData* const packetCallback,
|
||||
const WebRtc_UWord16 rtpPort,
|
||||
const char* ipAddr = NULL,
|
||||
const char* multicastIpAddr = NULL,
|
||||
const WebRtc_UWord16 rtcpPort = 0);
|
||||
virtual WebRtc_Word32 InitializeSourcePorts(
|
||||
const WebRtc_UWord16 rtpPort,
|
||||
const WebRtc_UWord16 rtcpPort = 0);
|
||||
virtual WebRtc_Word32 SourcePorts(WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort) const;
|
||||
virtual WebRtc_Word32 ReceiveSocketInformation(
|
||||
char ipAddr[kIpAddressVersion6Length],
|
||||
WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort,
|
||||
char multicastIpAddr[kIpAddressVersion6Length]) const;
|
||||
virtual WebRtc_Word32 SendSocketInformation(
|
||||
char ipAddr[kIpAddressVersion6Length],
|
||||
WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort) const;
|
||||
virtual WebRtc_Word32 RemoteSocketInformation(
|
||||
char ipAddr[kIpAddressVersion6Length],
|
||||
WebRtc_UWord16& rtpPort,
|
||||
WebRtc_UWord16& rtcpPort) const;
|
||||
virtual WebRtc_Word32 SetQoS(const bool QoS,
|
||||
const WebRtc_Word32 serviceType,
|
||||
const WebRtc_UWord32 maxBitrate = 0,
|
||||
const WebRtc_Word32 overrideDSCP = 0,
|
||||
const bool audio = false);
|
||||
virtual WebRtc_Word32 QoS(bool& QoS, WebRtc_Word32& serviceType,
|
||||
WebRtc_Word32& overrideDSCP) const;
|
||||
virtual WebRtc_Word32 SetToS(const WebRtc_Word32 DSCP,
|
||||
const bool useSetSockOpt = false);
|
||||
virtual WebRtc_Word32 ToS(WebRtc_Word32& DSCP,
|
||||
bool& useSetSockOpt) const;
|
||||
virtual WebRtc_Word32 SetPCP(const WebRtc_Word32 PCP);
|
||||
virtual WebRtc_Word32 PCP(WebRtc_Word32& PCP) const;
|
||||
virtual WebRtc_Word32 EnableIpV6();
|
||||
virtual bool IpV6Enabled() const;
|
||||
virtual WebRtc_Word32 SetFilterIP(
|
||||
const char filterIPAddress[kIpAddressVersion6Length]);
|
||||
virtual WebRtc_Word32 FilterIP(
|
||||
char filterIPAddress[kIpAddressVersion6Length]) const;
|
||||
virtual WebRtc_Word32 SetFilterPorts(const WebRtc_UWord16 rtpFilterPort,
|
||||
const WebRtc_UWord16 rtcpFilterPort);
|
||||
virtual WebRtc_Word32 FilterPorts(WebRtc_UWord16& rtpFilterPort,
|
||||
WebRtc_UWord16& rtcpFilterPort) const;
|
||||
virtual WebRtc_Word32 StartReceiving(
|
||||
const WebRtc_UWord32 numberOfSocketBuffers);
|
||||
virtual WebRtc_Word32 StopReceiving();
|
||||
virtual bool Receiving() const;
|
||||
virtual bool SendSocketsInitialized() const;
|
||||
virtual bool SourcePortsInitialized() const;
|
||||
virtual bool ReceiveSocketsInitialized() const;
|
||||
virtual WebRtc_Word32 SendRaw(const WebRtc_Word8* data,
|
||||
WebRtc_UWord32 length, WebRtc_Word32 isRTCP,
|
||||
WebRtc_UWord16 portnr = 0,
|
||||
const char* ip = NULL);
|
||||
virtual WebRtc_Word32 SendRTPPacketTo(const WebRtc_Word8 *data,
|
||||
WebRtc_UWord32 length,
|
||||
const SocketAddress& to);
|
||||
virtual WebRtc_Word32 SendRTCPPacketTo(const WebRtc_Word8 *data,
|
||||
WebRtc_UWord32 length,
|
||||
const SocketAddress& to);
|
||||
virtual WebRtc_Word32 SendRTPPacketTo(const WebRtc_Word8 *data,
|
||||
WebRtc_UWord32 length,
|
||||
WebRtc_UWord16 rtpPort);
|
||||
virtual WebRtc_Word32 SendRTCPPacketTo(const WebRtc_Word8 *data,
|
||||
WebRtc_UWord32 length,
|
||||
WebRtc_UWord16 rtcpPort);
|
||||
// Transport functions
|
||||
virtual int SendPacket(int channel, const void* data, int length);
|
||||
virtual int SendRTCPPacket(int channel, const void* data, int length);
|
||||
|
||||
// UdpTransport functions continue.
|
||||
virtual WebRtc_Word32 SetSendIP(const char* ipaddr);
|
||||
virtual WebRtc_Word32 SetSendPorts(const WebRtc_UWord16 rtpPort,
|
||||
const WebRtc_UWord16 rtcpPort = 0);
|
||||
|
||||
virtual ErrorCode LastError() const;
|
||||
|
||||
virtual WebRtc_Word32 IPAddressCached(const SocketAddress& address,
|
||||
char* ip,
|
||||
WebRtc_UWord32& ipSize,
|
||||
WebRtc_UWord16& sourcePort);
|
||||
|
||||
WebRtc_Word32 Id() const {return _id;}
|
||||
protected:
|
||||
// IncomingSocketCallback signature functions for receiving callbacks from
|
||||
// UdpSocketWrapper.
|
||||
static void IncomingRTPCallback(CallbackObj obj,
|
||||
const WebRtc_Word8* rtpPacket,
|
||||
WebRtc_Word32 rtpPacketLength,
|
||||
const SocketAddress* from);
|
||||
static void IncomingRTCPCallback(CallbackObj obj,
|
||||
const WebRtc_Word8* rtcpPacket,
|
||||
WebRtc_Word32 rtcpPacketLength,
|
||||
const SocketAddress* from);
|
||||
|
||||
void CloseSendSockets();
|
||||
void CloseReceiveSockets();
|
||||
|
||||
// Update _remoteRTPAddr according to _destPort and _destIP
|
||||
void BuildRemoteRTPAddr();
|
||||
// Update _remoteRTCPAddr according to _destPortRTCP and _destIP
|
||||
void BuildRemoteRTCPAddr();
|
||||
|
||||
void BuildSockaddrIn(WebRtc_UWord16 portnr, const char* ip,
|
||||
SocketAddress& remoteAddr) const;
|
||||
|
||||
ErrorCode BindLocalRTPSocket();
|
||||
ErrorCode BindLocalRTCPSocket();
|
||||
|
||||
ErrorCode BindRTPSendSocket();
|
||||
ErrorCode BindRTCPSendSocket();
|
||||
|
||||
void IncomingRTPFunction(const WebRtc_Word8* rtpPacket,
|
||||
WebRtc_Word32 rtpPacketLength,
|
||||
const SocketAddress* from);
|
||||
void IncomingRTCPFunction(const WebRtc_Word8* rtcpPacket,
|
||||
WebRtc_Word32 rtcpPacketLength,
|
||||
const SocketAddress* from);
|
||||
|
||||
bool FilterIPAddress(const SocketAddress* fromAddress);
|
||||
|
||||
bool SetSockOptUsed();
|
||||
|
||||
WebRtc_Word32 EnableQoS(WebRtc_Word32 serviceType, bool audio,
|
||||
WebRtc_UWord32 maxBitrate,
|
||||
WebRtc_Word32 overrideDSCP);
|
||||
|
||||
WebRtc_Word32 DisableQoS();
|
||||
|
||||
private:
|
||||
void GetCachedAddress(char* ip, WebRtc_UWord32& ipSize,
|
||||
WebRtc_UWord16& sourcePort);
|
||||
|
||||
WebRtc_Word32 _id;
|
||||
SocketFactoryInterface* _socket_creator;
|
||||
// Protects the sockets from being re-configured while receiving packets.
|
||||
CriticalSectionWrapper* _crit;
|
||||
CriticalSectionWrapper* _critFilter;
|
||||
// _packetCallback's critical section.
|
||||
CriticalSectionWrapper* _critPacketCallback;
|
||||
UdpSocketManager* _mgr;
|
||||
ErrorCode _lastError;
|
||||
|
||||
// Remote RTP and RTCP ports.
|
||||
WebRtc_UWord16 _destPort;
|
||||
WebRtc_UWord16 _destPortRTCP;
|
||||
|
||||
// Local RTP and RTCP ports.
|
||||
WebRtc_UWord16 _localPort;
|
||||
WebRtc_UWord16 _localPortRTCP;
|
||||
|
||||
// Local port number when the local port for receiving and local port number
|
||||
// for sending are not the same.
|
||||
WebRtc_UWord16 _srcPort;
|
||||
WebRtc_UWord16 _srcPortRTCP;
|
||||
|
||||
// Remote port from which last received packet was sent.
|
||||
WebRtc_UWord16 _fromPort;
|
||||
WebRtc_UWord16 _fromPortRTCP;
|
||||
|
||||
char _fromIP[kIpAddressVersion6Length];
|
||||
char _destIP[kIpAddressVersion6Length];
|
||||
char _localIP[kIpAddressVersion6Length];
|
||||
char _localMulticastIP[kIpAddressVersion6Length];
|
||||
|
||||
UdpSocketWrapper* _ptrRtpSocket;
|
||||
UdpSocketWrapper* _ptrRtcpSocket;
|
||||
|
||||
// Local port when the local port for receiving and local port for sending
|
||||
// are not the same.
|
||||
UdpSocketWrapper* _ptrSendRtpSocket;
|
||||
UdpSocketWrapper* _ptrSendRtcpSocket;
|
||||
|
||||
SocketAddress _remoteRTPAddr;
|
||||
SocketAddress _remoteRTCPAddr;
|
||||
|
||||
SocketAddress _localRTPAddr;
|
||||
SocketAddress _localRTCPAddr;
|
||||
|
||||
WebRtc_Word32 _tos;
|
||||
bool _receiving;
|
||||
bool _useSetSockOpt;
|
||||
bool _qos;
|
||||
WebRtc_Word32 _pcp;
|
||||
bool _ipV6Enabled;
|
||||
WebRtc_Word32 _serviceType;
|
||||
WebRtc_Word32 _overrideDSCP;
|
||||
WebRtc_UWord32 _maxBitrate;
|
||||
|
||||
// Cache used by GetCachedAddress(..).
|
||||
RWLockWrapper* _cachLock;
|
||||
SocketAddress _previousAddress;
|
||||
char _previousIP[kIpAddressVersion6Length];
|
||||
WebRtc_UWord32 _previousIPSize;
|
||||
WebRtc_UWord16 _previousSourcePort;
|
||||
|
||||
SocketAddress _filterIPAddress;
|
||||
WebRtc_UWord16 _rtpFilterPort;
|
||||
WebRtc_UWord16 _rtcpFilterPort;
|
||||
|
||||
UdpTransportData* _packetCallback;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_IMPL_H_
|
146
webrtc/test/channel_transport/udp_transport_unittest.cc
Normal file
146
webrtc/test/channel_transport/udp_transport_unittest.cc
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "webrtc/test/channel_transport/udp_transport.h"
|
||||
// We include the implementation header file to get at the dependency-injecting
|
||||
// constructor.
|
||||
#include "webrtc/test/channel_transport/udp_transport_impl.h"
|
||||
// We must mock the socket manager, for which we need its definition.
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class MockUdpSocketWrapper : public UdpSocketWrapper {
|
||||
public:
|
||||
// The following methods have to be mocked because they are pure.
|
||||
MOCK_METHOD1(ChangeUniqueId, WebRtc_Word32(WebRtc_Word32));
|
||||
MOCK_METHOD2(SetCallback, bool(CallbackObj, IncomingSocketCallback));
|
||||
MOCK_METHOD1(Bind, bool(const SocketAddress&));
|
||||
MOCK_METHOD0(ValidHandle, bool());
|
||||
MOCK_METHOD4(SetSockopt, bool(WebRtc_Word32, WebRtc_Word32,
|
||||
const WebRtc_Word8*,
|
||||
WebRtc_Word32));
|
||||
MOCK_METHOD1(SetTOS, WebRtc_Word32(WebRtc_Word32));
|
||||
MOCK_METHOD3(SendTo, WebRtc_Word32(const WebRtc_Word8*, WebRtc_Word32,
|
||||
const SocketAddress&));
|
||||
MOCK_METHOD8(SetQos, bool(WebRtc_Word32, WebRtc_Word32,
|
||||
WebRtc_Word32, WebRtc_Word32,
|
||||
WebRtc_Word32, WebRtc_Word32,
|
||||
const SocketAddress &,
|
||||
WebRtc_Word32));
|
||||
};
|
||||
|
||||
class MockUdpSocketManager : public UdpSocketManager {
|
||||
public:
|
||||
// Access to protected destructor.
|
||||
void Destroy() {
|
||||
delete this;
|
||||
}
|
||||
MOCK_METHOD2(Init, bool(WebRtc_Word32, WebRtc_UWord8&));
|
||||
MOCK_METHOD1(ChangeUniqueId, WebRtc_Word32(const WebRtc_Word32));
|
||||
MOCK_METHOD0(Start, bool());
|
||||
MOCK_METHOD0(Stop, bool());
|
||||
MOCK_METHOD1(AddSocket, bool(UdpSocketWrapper*));
|
||||
MOCK_METHOD1(RemoveSocket, bool(UdpSocketWrapper*));
|
||||
};
|
||||
|
||||
class MockSocketFactory :
|
||||
public UdpTransportImpl::SocketFactoryInterface {
|
||||
public:
|
||||
MockSocketFactory(std::vector<MockUdpSocketWrapper*>* socket_counter)
|
||||
: socket_counter_(socket_counter) {
|
||||
}
|
||||
UdpSocketWrapper* CreateSocket(const WebRtc_Word32 id,
|
||||
UdpSocketManager* mgr,
|
||||
CallbackObj obj,
|
||||
IncomingSocketCallback cb,
|
||||
bool ipV6Enable,
|
||||
bool disableGQOS) {
|
||||
MockUdpSocketWrapper* socket = new MockUdpSocketWrapper();
|
||||
// We instrument the socket with calls that are expected, but do
|
||||
// not matter for any specific test, in order to avoid warning messages.
|
||||
EXPECT_CALL(*socket, ValidHandle()).WillRepeatedly(Return(true));
|
||||
EXPECT_CALL(*socket, Bind(_)).WillOnce(Return(true));
|
||||
socket_counter_->push_back(socket);
|
||||
return socket;
|
||||
}
|
||||
std::vector<MockUdpSocketWrapper*>* socket_counter_;
|
||||
};
|
||||
|
||||
class UDPTransportTest : public ::testing::Test {
|
||||
public:
|
||||
UDPTransportTest()
|
||||
: sockets_created_(0) {
|
||||
}
|
||||
|
||||
~UDPTransportTest() {
|
||||
// In production, sockets register themselves at creation time with
|
||||
// an UdpSocketManager, and the UdpSocketManager is responsible for
|
||||
// deleting them. In this test, we just delete them after the test.
|
||||
while (!sockets_created_.empty()) {
|
||||
delete sockets_created_.back();
|
||||
sockets_created_.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
int NumSocketsCreated() {
|
||||
return sockets_created_.size();
|
||||
}
|
||||
|
||||
std::vector<MockUdpSocketWrapper*>* sockets_created() {
|
||||
return &sockets_created_;
|
||||
}
|
||||
private:
|
||||
std::vector<MockUdpSocketWrapper*> sockets_created_;
|
||||
};
|
||||
|
||||
TEST_F(UDPTransportTest, CreateTransport) {
|
||||
WebRtc_Word32 id = 0;
|
||||
WebRtc_UWord8 threads = 1;
|
||||
UdpTransport* transport = UdpTransport::Create(id, threads);
|
||||
UdpTransport::Destroy(transport);
|
||||
}
|
||||
|
||||
// This test verifies that the mock_socket is not called from the constructor.
|
||||
TEST_F(UDPTransportTest, ConstructorDoesNotCreateSocket) {
|
||||
WebRtc_Word32 id = 0;
|
||||
UdpTransportImpl::SocketFactoryInterface* null_maker = NULL;
|
||||
UdpSocketManager* null_manager = NULL;
|
||||
UdpTransport* transport = new UdpTransportImpl(id,
|
||||
null_maker,
|
||||
null_manager);
|
||||
delete transport;
|
||||
}
|
||||
|
||||
TEST_F(UDPTransportTest, InitializeSourcePorts) {
|
||||
WebRtc_Word32 id = 0;
|
||||
UdpTransportImpl::SocketFactoryInterface* mock_maker
|
||||
= new MockSocketFactory(sockets_created());
|
||||
MockUdpSocketManager* mock_manager = new MockUdpSocketManager();
|
||||
UdpTransport* transport = new UdpTransportImpl(id,
|
||||
mock_maker,
|
||||
mock_manager);
|
||||
EXPECT_EQ(0, transport->InitializeSourcePorts(4711, 4712));
|
||||
EXPECT_EQ(2, NumSocketsCreated());
|
||||
|
||||
delete transport;
|
||||
mock_manager->Destroy();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
Loading…
x
Reference in New Issue
Block a user