Only initialize usrsctp when it's used and uninitialize when it's not being used.

BUG=chromium:612366, webrtc:5909
R=deadbeef@webrtc.org

Review URL: https://codereview.webrtc.org/1995993002 .

Cr-Commit-Position: refs/heads/master@{#12816}
This commit is contained in:
Tommi 2016-05-19 19:58:38 +02:00
parent e725f7c73e
commit 7d01331eca
3 changed files with 211 additions and 177 deletions

View File

@ -20,6 +20,7 @@
#include "usrsctplib/usrsctp.h"
#include "webrtc/base/arraysize.h"
#include "webrtc/base/copyonwritebuffer.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/safe_conversions.h"
@ -27,8 +28,29 @@
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/media/base/streamparams.h"
namespace cricket {
// The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280,
// take off 80 bytes for DTLS/TURN/TCP/IP overhead.
static const size_t kSctpMtu = 1200;
// The size of the SCTP association send buffer. 256kB, the usrsctp default.
static const int kSendBufferSize = 262144;
struct SctpInboundPacket {
rtc::CopyOnWriteBuffer buffer;
ReceiveDataParams params;
// The |flags| parameter is used by SCTP to distinguish notification packets
// from other types of packets.
int flags;
};
namespace {
typedef cricket::SctpDataMediaChannel::StreamSet StreamSet;
// Set the initial value of the static SCTP Data Engines reference count.
int g_usrsctp_usage_count = 0;
rtc::GlobalLockPod g_usrsctp_lock_;
typedef SctpDataMediaChannel::StreamSet StreamSet;
// Returns a comma-separated, human-readable list of the stream IDs in 's'
std::string ListStreams(const StreamSet& s) {
std::stringstream result;
@ -85,78 +107,62 @@ std::string ListArray(const uint16_t* array, int num_elems) {
}
return result.str();
}
} // namespace
namespace cricket {
typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage;
typedef rtc::ScopedMessageData<rtc::CopyOnWriteBuffer> OutboundPacketMessage;
// The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280,
// take off 80 bytes for DTLS/TURN/TCP/IP overhead.
static const size_t kSctpMtu = 1200;
// The size of the SCTP association send buffer. 256kB, the usrsctp default.
static const int kSendBufferSize = 262144;
enum {
MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket
MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer
};
struct SctpInboundPacket {
rtc::CopyOnWriteBuffer buffer;
ReceiveDataParams params;
// The |flags| parameter is used by SCTP to distinguish notification packets
// from other types of packets.
int flags;
};
// Helper for logging SCTP messages.
static void debug_sctp_printf(const char *format, ...) {
void DebugSctpPrintf(const char* format, ...) {
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
char s[255];
va_list ap;
va_start(ap, format);
vsnprintf(s, sizeof(s), format, ap);
LOG(LS_INFO) << "SCTP: " << s;
va_end(ap);
#endif
}
// Get the PPID to use for the terminating fragment of this type.
static SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid(
cricket::DataMessageType type) {
SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid(DataMessageType type) {
switch (type) {
default:
case cricket::DMT_NONE:
case DMT_NONE:
return SctpDataMediaChannel::PPID_NONE;
case cricket::DMT_CONTROL:
case DMT_CONTROL:
return SctpDataMediaChannel::PPID_CONTROL;
case cricket::DMT_BINARY:
case DMT_BINARY:
return SctpDataMediaChannel::PPID_BINARY_LAST;
case cricket::DMT_TEXT:
case DMT_TEXT:
return SctpDataMediaChannel::PPID_TEXT_LAST;
};
}
static bool GetDataMediaType(
SctpDataMediaChannel::PayloadProtocolIdentifier ppid,
cricket::DataMessageType *dest) {
bool GetDataMediaType(SctpDataMediaChannel::PayloadProtocolIdentifier ppid,
DataMessageType* dest) {
ASSERT(dest != NULL);
switch (ppid) {
case SctpDataMediaChannel::PPID_BINARY_PARTIAL:
case SctpDataMediaChannel::PPID_BINARY_LAST:
*dest = cricket::DMT_BINARY;
*dest = DMT_BINARY;
return true;
case SctpDataMediaChannel::PPID_TEXT_PARTIAL:
case SctpDataMediaChannel::PPID_TEXT_LAST:
*dest = cricket::DMT_TEXT;
*dest = DMT_TEXT;
return true;
case SctpDataMediaChannel::PPID_CONTROL:
*dest = cricket::DMT_CONTROL;
*dest = DMT_CONTROL;
return true;
case SctpDataMediaChannel::PPID_NONE:
*dest = cricket::DMT_NONE;
*dest = DMT_NONE;
return true;
default:
@ -165,7 +171,7 @@ static bool GetDataMediaType(
}
// Log the packet in text2pcap format, if log level is at LS_VERBOSE.
static void VerboseLogPacket(const void *data, size_t length, int direction) {
void VerboseLogPacket(const void* data, size_t length, int direction) {
if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) {
char *dump_buf;
// Some downstream project uses an older version of usrsctp that expects
@ -181,8 +187,11 @@ static void VerboseLogPacket(const void *data, size_t length, int direction) {
// This is the callback usrsctp uses when there's data to send on the network
// that has been wrapped appropriatly for the SCTP protocol.
static int OnSctpOutboundPacket(void* addr, void* data, size_t length,
uint8_t tos, uint8_t set_df) {
int OnSctpOutboundPacket(void* addr,
void* data,
size_t length,
uint8_t tos,
uint8_t set_df) {
SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr);
LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
<< "addr: " << addr << "; length: " << length
@ -201,10 +210,13 @@ static int OnSctpOutboundPacket(void* addr, void* data, size_t length,
// a packet has been interpreted and parsed by usrsctp and found to contain
// payload data. It is called by a usrsctp thread. It is assumed this function
// will free the memory used by 'data'.
static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr,
void* data, size_t length,
struct sctp_rcvinfo rcv, int flags,
void* ulp_info) {
int OnSctpInboundPacket(struct socket* sock,
union sctp_sockstore addr,
void* data,
size_t length,
struct sctp_rcvinfo rcv,
int flags,
void* ulp_info) {
SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info);
// Post data to the channel's receiver thread (copying it).
// TODO(ldixon): Unclear if copy is needed as this method is responsible for
@ -212,7 +224,7 @@ static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr,
const SctpDataMediaChannel::PayloadProtocolIdentifier ppid =
static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>(
rtc::HostToNetwork32(rcv.rcv_ppid));
cricket::DataMessageType type = cricket::DMT_NONE;
DataMessageType type = DMT_NONE;
if (!GetDataMediaType(ppid, &type) && !(flags & MSG_NOTIFICATION)) {
// It's neither a notification nor a recognized data packet. Drop it.
LOG(LS_ERROR) << "Received an unknown PPID " << ppid
@ -233,78 +245,94 @@ static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr,
return 1;
}
// Set the initial value of the static SCTP Data Engines reference count.
int SctpDataEngine::usrsctp_engines_count = 0;
void InitializeUsrSctp() {
LOG(LS_INFO) << __FUNCTION__;
// First argument is udp_encapsulation_port, which is not releveant for our
// AF_CONN use of sctp.
usrsctp_init(0, &OnSctpOutboundPacket, &DebugSctpPrintf);
SctpDataEngine::SctpDataEngine() {
if (usrsctp_engines_count == 0) {
// First argument is udp_encapsulation_port, which is not releveant for our
// AF_CONN use of sctp.
usrsctp_init(0, cricket::OnSctpOutboundPacket, debug_sctp_printf);
// To turn on/off detailed SCTP debugging. You will also need to have the
// SCTP_DEBUG cpp defines flag.
// usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
// To turn on/off detailed SCTP debugging. You will also need to have the
// SCTP_DEBUG cpp defines flag.
// usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
// TODO(ldixon): Consider turning this on/off.
usrsctp_sysctl_set_sctp_ecn_enable(0);
// TODO(ldixon): Consider turning this on/off.
usrsctp_sysctl_set_sctp_ecn_enable(0);
// This is harmless, but we should find out when the library default
// changes.
int send_size = usrsctp_sysctl_get_sctp_sendspace();
if (send_size != kSendBufferSize) {
LOG(LS_ERROR) << "Got different send size than expected: " << send_size;
}
// This is harmless, but we should find out when the library default
// changes.
int send_size = usrsctp_sysctl_get_sctp_sendspace();
if (send_size != kSendBufferSize) {
LOG(LS_ERROR) << "Got different send size than expected: " << send_size;
// TODO(ldixon): Consider turning this on/off.
// This is not needed right now (we don't do dynamic address changes):
// If SCTP Auto-ASCONF is enabled, the peer is informed automatically
// when a new address is added or removed. This feature is enabled by
// default.
// usrsctp_sysctl_set_sctp_auto_asconf(0);
// TODO(ldixon): Consider turning this on/off.
// Add a blackhole sysctl. Setting it to 1 results in no ABORTs
// being sent in response to INITs, setting it to 2 results
// in no ABORTs being sent for received OOTB packets.
// This is similar to the TCP sysctl.
//
// See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html
// See: http://svnweb.freebsd.org/base?view=revision&revision=229805
// usrsctp_sysctl_set_sctp_blackhole(2);
// Set the number of default outgoing streams. This is the number we'll
// send in the SCTP INIT message. The 'appropriate default' in the
// second paragraph of
// http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2
// is kMaxSctpSid.
usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(kMaxSctpSid);
}
void UninitializeUsrSctp() {
LOG(LS_INFO) << __FUNCTION__;
// usrsctp_finish() may fail if it's called too soon after the channels are
// closed. Wait and try again until it succeeds for up to 3 seconds.
for (size_t i = 0; i < 300; ++i) {
if (usrsctp_finish() == 0) {
return;
}
// TODO(ldixon): Consider turning this on/off.
// This is not needed right now (we don't do dynamic address changes):
// If SCTP Auto-ASCONF is enabled, the peer is informed automatically
// when a new address is added or removed. This feature is enabled by
// default.
// usrsctp_sysctl_set_sctp_auto_asconf(0);
// TODO(ldixon): Consider turning this on/off.
// Add a blackhole sysctl. Setting it to 1 results in no ABORTs
// being sent in response to INITs, setting it to 2 results
// in no ABORTs being sent for received OOTB packets.
// This is similar to the TCP sysctl.
//
// See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html
// See: http://svnweb.freebsd.org/base?view=revision&revision=229805
// usrsctp_sysctl_set_sctp_blackhole(2);
// Set the number of default outgoing streams. This is the number we'll
// send in the SCTP INIT message. The 'appropriate default' in the
// second paragraph of
// http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2
// is cricket::kMaxSctpSid.
usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(
cricket::kMaxSctpSid);
rtc::Thread::SleepMs(10);
}
usrsctp_engines_count++;
LOG(LS_ERROR) << "Failed to shutdown usrsctp.";
}
cricket::DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName);
void IncrementUsrSctpUsageCount() {
rtc::GlobalLockScope lock(&g_usrsctp_lock_);
if (!g_usrsctp_usage_count) {
InitializeUsrSctp();
}
++g_usrsctp_usage_count;
}
void DecrementUsrSctpUsageCount() {
rtc::GlobalLockScope lock(&g_usrsctp_lock_);
--g_usrsctp_usage_count;
if (!g_usrsctp_usage_count) {
UninitializeUsrSctp();
}
}
DataCodec GetSctpDataCodec() {
DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName);
codec.SetParam(kCodecParamPort, kSctpDefaultPort);
codecs_.push_back(codec);
return codec;
}
SctpDataEngine::~SctpDataEngine() {
usrsctp_engines_count--;
LOG(LS_VERBOSE) << "usrsctp_engines_count:" << usrsctp_engines_count;
} // namespace
if (usrsctp_engines_count == 0) {
// usrsctp_finish() may fail if it's called too soon after the channels are
// closed. Wait and try again until it succeeds for up to 3 seconds.
for (size_t i = 0; i < 300; ++i) {
if (usrsctp_finish() == 0)
return;
SctpDataEngine::SctpDataEngine() : codecs_(1, GetSctpDataCodec()) {}
rtc::Thread::SleepMs(10);
}
LOG(LS_ERROR) << "Failed to shutdown usrsctp.";
}
}
SctpDataEngine::~SctpDataEngine() {}
// Called on the worker thread.
DataMediaChannel* SctpDataEngine::CreateChannel(
DataChannelType data_channel_type) {
if (data_channel_type != DCT_SCTP) {
@ -314,7 +342,7 @@ DataMediaChannel* SctpDataEngine::CreateChannel(
}
// static
SctpDataMediaChannel* SctpDataEngine::GetChannelFromSocket(
SctpDataMediaChannel* SctpDataMediaChannel::GetChannelFromSocket(
struct socket* sock) {
struct sockaddr* addrs = nullptr;
int naddrs = usrsctp_getladdrs(sock, 0, &addrs);
@ -336,8 +364,8 @@ SctpDataMediaChannel* SctpDataEngine::GetChannelFromSocket(
}
// static
int SctpDataEngine::SendThresholdCallback(struct socket* sock,
uint32_t sb_free) {
int SctpDataMediaChannel::SendThresholdCallback(struct socket* sock,
uint32_t sb_free) {
// Fired on our I/O thread. SctpDataMediaChannel::OnPacketReceived() gets
// a packet containing acknowledgments, which goes into usrsctp_conninput,
// and then back here.
@ -389,17 +417,19 @@ bool SctpDataMediaChannel::OpenSctpSocket() {
return false;
}
IncrementUsrSctpUsageCount();
// If kSendBufferSize isn't reflective of reality, we log an error, but we
// still have to do something reasonable here. Look up what the buffer's
// real size is and set our threshold to something reasonable.
const static int kSendThreshold = usrsctp_sysctl_get_sctp_sendspace() / 2;
sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP,
cricket::OnSctpInboundPacket,
&SctpDataEngine::SendThresholdCallback,
kSendThreshold, this);
sock_ = usrsctp_socket(
AF_CONN, SOCK_STREAM, IPPROTO_SCTP, OnSctpInboundPacket,
&SctpDataMediaChannel::SendThresholdCallback, kSendThreshold, this);
if (!sock_) {
LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket.";
DecrementUsrSctpUsageCount();
return false;
}
@ -488,6 +518,8 @@ void SctpDataMediaChannel::CloseSctpSocket() {
usrsctp_close(sock_);
sock_ = NULL;
usrsctp_deregister_address(this);
DecrementUsrSctpUsageCount();
}
}
@ -599,7 +631,7 @@ bool SctpDataMediaChannel::SendData(
return false;
}
if (params.type != cricket::DMT_CONTROL &&
if (params.type != DMT_CONTROL &&
open_streams_.find(params.ssrc) == open_streams_.end()) {
LOG(LS_WARNING) << debug_name_ << "->SendData(...): "
<< "Not sending data because ssrc is unknown: "
@ -717,7 +749,7 @@ bool SctpDataMediaChannel::AddStream(const StreamParams& stream) {
}
const uint32_t ssrc = stream.first_ssrc();
if (ssrc >= cricket::kMaxSctpSid) {
if (ssrc >= kMaxSctpSid) {
LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): "
<< "Not adding data stream '" << stream.id
<< "' with ssrc=" << ssrc
@ -984,8 +1016,9 @@ void SctpDataMediaChannel::OnPacketFromSctpToNetwork(
}
bool SctpDataMediaChannel::SendQueuedStreamResets() {
if (!sent_reset_streams_.empty() || queued_reset_streams_.empty())
if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) {
return true;
}
LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending ["
<< ListStreams(queued_reset_streams_) << "], Open: ["

View File

@ -25,6 +25,7 @@ enum PreservedErrno {
} // namespace cricket
#include "webrtc/base/copyonwritebuffer.h"
#include "webrtc/base/gtest_prod_util.h"
#include "webrtc/media/base/codec.h"
#include "webrtc/media/base/mediachannel.h"
#include "webrtc/media/base/mediaengine.h"
@ -75,19 +76,13 @@ class SctpDataMediaChannel;
class SctpDataEngine : public DataEngineInterface, public sigslot::has_slots<> {
public:
SctpDataEngine();
virtual ~SctpDataEngine();
~SctpDataEngine() override;
virtual DataMediaChannel* CreateChannel(DataChannelType data_channel_type);
virtual const std::vector<DataCodec>& data_codecs() { return codecs_; }
static int SendThresholdCallback(struct socket* sock, uint32_t sb_free);
DataMediaChannel* CreateChannel(DataChannelType data_channel_type) override;
const std::vector<DataCodec>& data_codecs() override { return codecs_; }
private:
static int usrsctp_engines_count;
std::vector<DataCodec> codecs_;
static SctpDataMediaChannel* GetChannelFromSocket(struct socket* sock);
const std::vector<DataCodec> codecs_;
};
// TODO(ldixon): Make into a special type of TypedMessageData.
@ -161,11 +156,16 @@ class SctpDataMediaChannel : public DataMediaChannel,
void OnSendThresholdCallback();
// Helper for debugging.
void set_debug_name(const std::string& debug_name) {
void set_debug_name_for_testing(const char* debug_name) {
debug_name_ = debug_name;
}
const std::string& debug_name() const { return debug_name_; }
const struct socket* socket() const { return sock_; }
private:
FRIEND_TEST_ALL_PREFIXES(SctpDataMediaChannelTest, EngineSignalsRightChannel);
static int SendThresholdCallback(struct socket* sock, uint32_t sb_free);
static SctpDataMediaChannel* GetChannelFromSocket(struct socket* sock);
private:
sockaddr_conn GetSctpSockAddr(int port);
@ -229,8 +229,8 @@ class SctpDataMediaChannel : public DataMediaChannel,
StreamSet queued_reset_streams_;
StreamSet sent_reset_streams_;
// A human-readable name for debugging messages.
std::string debug_name_;
// A static human-readable name for debugging messages.
const char* debug_name_;
};
} // namespace cricket

View File

@ -29,13 +29,14 @@
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/media/sctp/sctpdataengine.h"
namespace cricket {
enum {
MSG_PACKET = 1,
};
// Fake NetworkInterface that sends/receives sctp packets. The one in
// webrtc/media/base/fakenetworkinterface.h only works with rtp/rtcp.
class SctpFakeNetworkInterface : public cricket::MediaChannel::NetworkInterface,
class SctpFakeNetworkInterface : public MediaChannel::NetworkInterface,
public rtc::MessageHandler {
public:
explicit SctpFakeNetworkInterface(rtc::Thread* thread)
@ -43,7 +44,7 @@ class SctpFakeNetworkInterface : public cricket::MediaChannel::NetworkInterface,
dest_(NULL) {
}
void SetDestination(cricket::DataMediaChannel* dest) { dest_ = dest; }
void SetDestination(DataMediaChannel* dest) { dest_ = dest; }
protected:
// Called to send raw packet down the wire (e.g. SCTP an packet).
@ -91,7 +92,7 @@ class SctpFakeNetworkInterface : public cricket::MediaChannel::NetworkInterface,
private:
// Not owned by this class.
rtc::Thread* thread_;
cricket::DataMediaChannel* dest_;
DataMediaChannel* dest_;
};
// This is essentially a buffer to hold recieved data. It stores only the last
@ -106,11 +107,12 @@ class SctpFakeDataReceiver : public sigslot::has_slots<> {
void Clear() {
received_ = false;
last_data_ = "";
last_params_ = cricket::ReceiveDataParams();
last_params_ = ReceiveDataParams();
}
virtual void OnDataReceived(const cricket::ReceiveDataParams& params,
const char* data, size_t length) {
virtual void OnDataReceived(const ReceiveDataParams& params,
const char* data,
size_t length) {
received_ = true;
last_data_ = std::string(data, length);
last_params_ = params;
@ -118,12 +120,12 @@ class SctpFakeDataReceiver : public sigslot::has_slots<> {
bool received() const { return received_; }
std::string last_data() const { return last_data_; }
cricket::ReceiveDataParams last_params() const { return last_params_; }
ReceiveDataParams last_params() const { return last_params_; }
private:
bool received_;
std::string last_data_;
cricket::ReceiveDataParams last_params_;
ReceiveDataParams last_params_;
};
class SignalReadyToSendObserver : public sigslot::has_slots<> {
@ -147,7 +149,7 @@ class SignalReadyToSendObserver : public sigslot::has_slots<> {
class SignalChannelClosedObserver : public sigslot::has_slots<> {
public:
SignalChannelClosedObserver() {}
void BindSelf(cricket::SctpDataMediaChannel* channel) {
void BindSelf(SctpDataMediaChannel* channel) {
channel->SignalStreamClosedRemotely.connect(
this, &SignalChannelClosedObserver::OnStreamClosed);
}
@ -168,12 +170,12 @@ class SignalChannelClosedObserver : public sigslot::has_slots<> {
class SignalChannelClosedReopener : public sigslot::has_slots<> {
public:
SignalChannelClosedReopener(cricket::SctpDataMediaChannel* channel,
cricket::SctpDataMediaChannel* peer)
SignalChannelClosedReopener(SctpDataMediaChannel* channel,
SctpDataMediaChannel* peer)
: channel_(channel), peer_(peer) {}
void OnStreamClosed(int stream) {
cricket::StreamParams p(cricket::StreamParams::CreateLegacy(stream));
StreamParams p(StreamParams::CreateLegacy(stream));
channel_->AddSendStream(p);
channel_->AddRecvStream(p);
peer_->AddSendStream(p);
@ -186,8 +188,8 @@ class SignalChannelClosedReopener : public sigslot::has_slots<> {
}
private:
cricket::SctpDataMediaChannel* channel_;
cricket::SctpDataMediaChannel* peer_;
SctpDataMediaChannel* channel_;
SctpDataMediaChannel* peer_;
std::vector<int> streams_;
};
@ -200,9 +202,7 @@ class SctpDataMediaChannelTest : public testing::Test,
static void SetUpTestCase() {
}
virtual void SetUp() {
engine_.reset(new cricket::SctpDataEngine());
}
virtual void SetUp() { engine_.reset(new SctpDataEngine()); }
void SetupConnectedChannels() {
net1_.reset(new SctpFakeNetworkInterface(rtc::Thread::Current()));
@ -212,11 +212,11 @@ class SctpDataMediaChannelTest : public testing::Test,
chan1_ready_to_send_count_ = 0;
chan2_ready_to_send_count_ = 0;
chan1_.reset(CreateChannel(net1_.get(), recv1_.get()));
chan1_->set_debug_name("chan1/connector");
chan1_->set_debug_name_for_testing("chan1/connector");
chan1_->SignalReadyToSend.connect(
this, &SctpDataMediaChannelTest::OnChan1ReadyToSend);
chan2_.reset(CreateChannel(net2_.get(), recv2_.get()));
chan2_->set_debug_name("chan2/listener");
chan2_->set_debug_name_for_testing("chan2/listener");
chan2_->SignalReadyToSend.connect(
this, &SctpDataMediaChannelTest::OnChan2ReadyToSend);
// Setup two connected channels ready to send and receive.
@ -254,7 +254,7 @@ class SctpDataMediaChannelTest : public testing::Test,
bool AddStream(int ssrc) {
bool ret = true;
cricket::StreamParams p(cricket::StreamParams::CreateLegacy(ssrc));
StreamParams p(StreamParams::CreateLegacy(ssrc));
ret = ret && chan1_->AddSendStream(p);
ret = ret && chan1_->AddRecvStream(p);
ret = ret && chan2_->AddSendStream(p);
@ -262,11 +262,10 @@ class SctpDataMediaChannelTest : public testing::Test,
return ret;
}
cricket::SctpDataMediaChannel* CreateChannel(
SctpFakeNetworkInterface* net, SctpFakeDataReceiver* recv) {
cricket::SctpDataMediaChannel* channel =
static_cast<cricket::SctpDataMediaChannel*>(engine_->CreateChannel(
cricket::DCT_SCTP));
SctpDataMediaChannel* CreateChannel(SctpFakeNetworkInterface* net,
SctpFakeDataReceiver* recv) {
SctpDataMediaChannel* channel =
static_cast<SctpDataMediaChannel*>(engine_->CreateChannel(DCT_SCTP));
channel->SetInterface(net);
// When data is received, pass it to the SctpFakeDataReceiver.
channel->SignalDataReceived.connect(
@ -274,11 +273,11 @@ class SctpDataMediaChannelTest : public testing::Test,
return channel;
}
bool SendData(cricket::SctpDataMediaChannel* chan,
bool SendData(SctpDataMediaChannel* chan,
uint32_t ssrc,
const std::string& msg,
cricket::SendDataResult* result) {
cricket::SendDataParams params;
SendDataResult* result) {
SendDataParams params;
params.ssrc = ssrc;
return chan->SendData(params, rtc::CopyOnWriteBuffer(
@ -304,21 +303,21 @@ class SctpDataMediaChannelTest : public testing::Test,
return !thread->IsQuitting();
}
cricket::SctpDataMediaChannel* channel1() { return chan1_.get(); }
cricket::SctpDataMediaChannel* channel2() { return chan2_.get(); }
SctpDataMediaChannel* channel1() { return chan1_.get(); }
SctpDataMediaChannel* channel2() { return chan2_.get(); }
SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
int channel1_ready_to_send_count() { return chan1_ready_to_send_count_; }
int channel2_ready_to_send_count() { return chan2_ready_to_send_count_; }
private:
std::unique_ptr<cricket::SctpDataEngine> engine_;
std::unique_ptr<SctpDataEngine> engine_;
std::unique_ptr<SctpFakeNetworkInterface> net1_;
std::unique_ptr<SctpFakeNetworkInterface> net2_;
std::unique_ptr<SctpFakeDataReceiver> recv1_;
std::unique_ptr<SctpFakeDataReceiver> recv2_;
std::unique_ptr<cricket::SctpDataMediaChannel> chan1_;
std::unique_ptr<cricket::SctpDataMediaChannel> chan2_;
std::unique_ptr<SctpDataMediaChannel> chan1_;
std::unique_ptr<SctpDataMediaChannel> chan2_;
int chan1_ready_to_send_count_;
int chan2_ready_to_send_count_;
@ -345,12 +344,12 @@ TEST_F(SctpDataMediaChannelTest, SignalReadyToSend) {
channel2()->SignalReadyToSend.connect(&signal_observer_2,
&SignalReadyToSendObserver::OnSignaled);
cricket::SendDataResult result;
SendDataResult result;
ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
EXPECT_TRUE_WAIT(signal_observer_1.IsSignaled(true), 1000);
@ -360,10 +359,10 @@ TEST_F(SctpDataMediaChannelTest, SignalReadyToSend) {
TEST_F(SctpDataMediaChannelTest, SendData) {
SetupConnectedChannels();
cricket::SendDataResult result;
SendDataResult result;
LOG(LS_VERBOSE) << "chan1 sending: 'hello?' -----------------------------";
ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
<< ", recv2.last_params.ssrc="
@ -376,7 +375,7 @@ TEST_F(SctpDataMediaChannelTest, SendData) {
LOG(LS_VERBOSE) << "chan2 sending: 'hi chan1' -----------------------------";
ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
<< ", recv1.last_params.ssrc="
@ -392,8 +391,8 @@ TEST_F(SctpDataMediaChannelTest, SendData) {
TEST_F(SctpDataMediaChannelTest, SendDataBlocked) {
SetupConnectedChannels();
cricket::SendDataResult result;
cricket::SendDataParams params;
SendDataResult result;
SendDataParams params;
params.ssrc = 1;
std::vector<char> buffer(1024 * 64, 0);
@ -401,11 +400,11 @@ TEST_F(SctpDataMediaChannelTest, SendDataBlocked) {
for (size_t i = 0; i < 100; ++i) {
channel1()->SendData(
params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
if (result == cricket::SDR_BLOCK)
if (result == SDR_BLOCK)
break;
}
EXPECT_EQ(cricket::SDR_BLOCK, result);
EXPECT_EQ(SDR_BLOCK, result);
}
TEST_F(SctpDataMediaChannelTest, ClosesRemoteStream) {
@ -414,12 +413,12 @@ TEST_F(SctpDataMediaChannelTest, ClosesRemoteStream) {
chan_1_sig_receiver.BindSelf(channel1());
chan_2_sig_receiver.BindSelf(channel2());
cricket::SendDataResult result;
SendDataResult result;
ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
// Close channel 1. Channel 2 should notify us.
@ -434,12 +433,12 @@ TEST_F(SctpDataMediaChannelTest, ClosesTwoRemoteStreams) {
chan_1_sig_receiver.BindSelf(channel1());
chan_2_sig_receiver.BindSelf(channel2());
cricket::SendDataResult result;
SendDataResult result;
ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
// Close two streams on one side.
@ -457,12 +456,12 @@ TEST_F(SctpDataMediaChannelTest, ClosesStreamsOnBothSides) {
chan_1_sig_receiver.BindSelf(channel1());
chan_2_sig_receiver.BindSelf(channel2());
cricket::SendDataResult result;
SendDataResult result;
ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
// Close one stream on channel1(), while closing three streams on
@ -484,7 +483,7 @@ TEST_F(SctpDataMediaChannelTest, EngineSignalsRightChannel) {
EXPECT_TRUE_WAIT(channel1()->socket() != NULL, 1000);
struct socket *sock = const_cast<struct socket*>(channel1()->socket());
int prior_count = channel1_ready_to_send_count();
cricket::SctpDataEngine::SendThresholdCallback(sock, 0);
SctpDataMediaChannel::SendThresholdCallback(sock, 0);
EXPECT_GT(channel1_ready_to_send_count(), prior_count);
}
@ -503,12 +502,12 @@ TEST_F(SctpDataMediaChannelTest, RefusesHighNumberedChannels) {
TEST_F(SctpDataMediaChannelTest, MAYBE_ReusesAStream) {
// Shut down channel 1, then open it up again for reuse.
SetupConnectedChannels();
cricket::SendDataResult result;
SendDataResult result;
SignalChannelClosedObserver chan_2_sig_receiver;
chan_2_sig_receiver.BindSelf(channel2());
ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
channel1()->RemoveSendStream(1);
@ -518,8 +517,10 @@ TEST_F(SctpDataMediaChannelTest, MAYBE_ReusesAStream) {
// Create a new channel 1.
AddStream(1);
ASSERT_TRUE(SendData(channel1(), 1, "hi?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
EXPECT_EQ(SDR_SUCCESS, result);
EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hi?"), 1000);
channel1()->RemoveSendStream(1);
EXPECT_TRUE_WAIT(chan_2_sig_receiver.StreamCloseCount(1) == 2, 1000);
}
} // namespace cricket