Update libjingle to 53057474.
R=wu@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/2274004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@4818 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/media/sctp/sctpdataengine.cc b/talk/media/sctp/sctpdataengine.cc
index 0d6bc59..3d450c6 100644
--- a/talk/media/sctp/sctpdataengine.cc
+++ b/talk/media/sctp/sctpdataengine.cc
@@ -64,28 +64,58 @@
int flags;
};
-// Helper for logging SCTP data. Given a buffer, returns a readable string.
+// Helper for logging SCTP messages.
static void debug_sctp_printf(const char *format, ...) {
char s[255];
va_list ap;
va_start(ap, format);
vsnprintf(s, sizeof(s), format, ap);
- LOG(LS_INFO) << s;
- // vprintf(format, ap);
+ LOG(LS_INFO) << "SCTP: " << s;
va_end(ap);
}
-// Helper for make a string dump of some SCTP data. Used for LOG
-// debugging messages.
-static std::string SctpDataToDebugString(void* buffer, size_t length,
- int dump_type) {
- char *dump_buf = usrsctp_dumppacket(buffer, length, dump_type);
- if (!dump_buf) {
- return "";
+// Get the PPID to use for the terminating fragment of this type.
+static SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid(
+ cricket::DataMessageType type) {
+ switch (type) {
+ default:
+ case cricket::DMT_NONE:
+ return SctpDataMediaChannel::PPID_NONE;
+ case cricket::DMT_CONTROL:
+ return SctpDataMediaChannel::PPID_CONTROL;
+ case cricket::DMT_BINARY:
+ return SctpDataMediaChannel::PPID_BINARY_LAST;
+ case cricket::DMT_TEXT:
+ return SctpDataMediaChannel::PPID_TEXT_LAST;
+ };
+}
+
+static bool GetDataMediaType(
+ SctpDataMediaChannel::PayloadProtocolIdentifier ppid,
+ cricket::DataMessageType *dest) {
+ ASSERT(dest != NULL);
+ switch (ppid) {
+ case SctpDataMediaChannel::PPID_BINARY_PARTIAL:
+ case SctpDataMediaChannel::PPID_BINARY_LAST:
+ *dest = cricket::DMT_BINARY;
+ return true;
+
+ case SctpDataMediaChannel::PPID_TEXT_PARTIAL:
+ case SctpDataMediaChannel::PPID_TEXT_LAST:
+ *dest = cricket::DMT_TEXT;
+ return true;
+
+ case SctpDataMediaChannel::PPID_CONTROL:
+ *dest = cricket::DMT_CONTROL;
+ return true;
+
+ case SctpDataMediaChannel::PPID_NONE:
+ *dest = cricket::DMT_NONE;
+ return true;
+
+ default:
+ return false;
}
- std::string s = std::string(dump_buf);
- usrsctp_freedumpbuffer(dump_buf);
- return s;
}
// This is the callback usrsctp uses when there's data to send on the network
@@ -96,9 +126,7 @@
LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
<< "addr: " << addr << "; length: " << length
<< "; tos: " << std::hex << static_cast<int>(tos)
- << "; set_df: " << std::hex << static_cast<int>(set_df)
- << "; data:" << SctpDataToDebugString(data, length,
- SCTP_DUMP_OUTBOUND);
+ << "; set_df: " << std::hex << static_cast<int>(set_df);
// Note: We have to copy the data; the caller will delete it.
talk_base::Buffer* buffer = new talk_base::Buffer(data, length);
channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET,
@@ -114,37 +142,29 @@
void* data, size_t length,
struct sctp_rcvinfo rcv, int flags,
void* ulp_info) {
- LOG(LS_VERBOSE) << "global OnSctpInboundPacket... Msg of length "
- << length << " received via " << addr.sconn.sconn_addr << ":"
- << talk_base::NetworkToHost16(addr.sconn.sconn_port)
- << " on stream " << rcv.rcv_sid
- << " with SSN " << rcv.rcv_ssn
- << " and TSN " << rcv.rcv_tsn << ", PPID "
- << talk_base::NetworkToHost32(rcv.rcv_ppid)
- << ", context " << rcv.rcv_context
- << ", data: " << data
- << ", ulp_info:" << ulp_info
- << ", flags:" << std::hex << flags;
SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info);
- // The second log call is useful when the defines flags are incorrect. In
- // this case, ulp_info ends up being bad and the second log message will
- // cause a crash.
- LOG(LS_VERBOSE) << "global OnSctpInboundPacket. channel="
- << channel->debug_name() << "...";
// Post data to the channel's receiver thread (copying it).
// TODO(ldixon): Unclear if copy is needed as this method is responsible for
// memory cleanup. But this does simplify code.
- const uint32 native_ppid = talk_base::HostToNetwork32(rcv.rcv_ppid);
- SctpInboundPacket* packet = new SctpInboundPacket();
- packet->buffer.SetData(data, length);
- packet->params.ssrc = rcv.rcv_sid;
- packet->params.seq_num = rcv.rcv_ssn;
- packet->params.timestamp = rcv.rcv_tsn;
- packet->params.type =
- static_cast<cricket::DataMessageType>(native_ppid);
- packet->flags = flags;
- channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET,
- talk_base::WrapMessageData(packet));
+ const SctpDataMediaChannel::PayloadProtocolIdentifier ppid =
+ static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>(
+ talk_base::HostToNetwork32(rcv.rcv_ppid));
+ cricket::DataMessageType type = cricket::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
+ << " on an SCTP packet. Dropping.";
+ } else {
+ SctpInboundPacket* packet = new SctpInboundPacket;
+ packet->buffer.SetData(data, length);
+ packet->params.ssrc = rcv.rcv_sid;
+ packet->params.seq_num = rcv.rcv_ssn;
+ packet->params.timestamp = rcv.rcv_tsn;
+ packet->params.type = type;
+ packet->flags = flags;
+ channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET,
+ talk_base::WrapMessageData(packet));
+ }
free(data);
return 1;
}
@@ -181,6 +201,14 @@
// 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);
}
usrsctp_engines_count++;
@@ -437,7 +465,8 @@
const talk_base::Buffer& payload,
SendDataResult* result) {
if (result) {
- // If we return true, we'll set this to SDR_SUCCESS.
+ // Preset |result| to assume an error. If SendData succeeds, we'll
+ // overwrite |*result| once more at the end.
*result = SDR_ERROR;
}
@@ -457,41 +486,36 @@
return false;
}
- // TODO(ldixon): Experiment with sctp_sendv_spa instead of sctp_sndinfo. e.g.
- // struct sctp_sendv_spa spa = {0};
- // spa.sendv_flags |= SCTP_SEND_SNDINFO_VALID;
- // spa.sendv_sndinfo.snd_sid = params.ssrc;
- // spa.sendv_sndinfo.snd_context = 0;
- // spa.sendv_sndinfo.snd_assoc_id = 0;
- // TODO(pthatcher): Support different types of protocols (e.g. SSL) and
- // messages (e.g. Binary) via SendDataParams.
- // spa.sendv_sndinfo.snd_ppid = htonl(PPID_NONE);
- // TODO(pthatcher): Support different reliability semantics.
- // For reliable: Remove SCTP_UNORDERED.
- // For partially-reliable: Add rtx or ttl.
- // spa.sendv_sndinfo.snd_flags = SCTP_UNORDERED;
- // TODO(phatcher): Try some of these things.
- // spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
- // spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX;
- // spa.sendv_prinfo.pr_value = htons(max_retransmit_count);
- // spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL;
- // spa.sendv_prinfo.pr_value = htons(max_retransmit_time);
//
// Send data using SCTP.
- sctp_sndinfo sndinfo = {0};
- sndinfo.snd_sid = params.ssrc;
- sndinfo.snd_flags = 0;
- // TODO(pthatcher): Once data types are added to SendParams, this can be set
- // from SendParams.
- sndinfo.snd_ppid = talk_base::HostToNetwork32(params.type);
- sndinfo.snd_context = 0;
- sndinfo.snd_assoc_id = 0;
- ssize_t res = usrsctp_sendv(sock_, payload.data(),
- static_cast<size_t>(payload.length()),
- NULL, 0, &sndinfo,
- static_cast<socklen_t>(sizeof(sndinfo)),
- SCTP_SENDV_SNDINFO, 0);
- if (res < 0) {
+ ssize_t send_res = 0; // result from usrsctp_sendv.
+ struct sctp_sendv_spa spa = {0};
+ spa.sendv_flags |= SCTP_SEND_SNDINFO_VALID;
+ spa.sendv_sndinfo.snd_sid = params.ssrc;
+ spa.sendv_sndinfo.snd_ppid = talk_base::HostToNetwork32(
+ GetPpid(params.type));
+
+ // Ordered implies reliable.
+ if (!params.ordered) {
+ spa.sendv_sndinfo.snd_flags |= SCTP_UNORDERED;
+ if (params.max_rtx_count >= 0 || params.max_rtx_ms == 0) {
+ spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
+ spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX;
+ spa.sendv_prinfo.pr_value = params.max_rtx_count;
+ } else {
+ spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
+ spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL;
+ spa.sendv_prinfo.pr_value = params.max_rtx_ms;
+ }
+ }
+
+ // We don't fragment.
+ send_res = usrsctp_sendv(sock_, payload.data(),
+ static_cast<size_t>(payload.length()),
+ NULL, 0, &spa,
+ static_cast<socklen_t>(sizeof(spa)),
+ SCTP_SENDV_SPA, 0);
+ if (send_res < 0) {
if (errno == EWOULDBLOCK) {
*result = SDR_BLOCK;
LOG(LS_INFO) << debug_name_ << "->SendData(...): EWOULDBLOCK returned";
@@ -503,7 +527,7 @@
return false;
}
if (result) {
- // If we return true, we'll set this to SDR_SUCCESS.
+ // Only way out now is success.
*result = SDR_SUCCESS;
}
return true;
@@ -511,17 +535,13 @@
// Called by network interface when a packet has been received.
void SctpDataMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
- LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): "
- << " length=" << packet->length() << "; data="
- << SctpDataToDebugString(packet->data(), packet->length(),
- SCTP_DUMP_INBOUND);
+ LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): " << " length="
+ << packet->length() << ", sending: " << sending_;
// Only give receiving packets to usrsctp after if connected. This enables two
// peers to each make a connect call, but for them not to receive an INIT
// packet before they have called connect; least the last receiver of the INIT
// packet will have called connect, and a connection will be established.
if (sending_) {
- LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...):"
- << " Passed packet to sctp.";
// Pass received packet to SCTP stack. Once processed by usrsctp, the data
// will be will be given to the global OnSctpInboundData, and then,
// marshalled by a Post and handled with OnMessage.
@@ -529,8 +549,6 @@
} else {
// TODO(ldixon): Consider caching the packet for very slightly better
// reliability.
- LOG(LS_INFO) << debug_name_ << "->OnPacketReceived(...):"
- << " Threw packet (probably an INIT) away.";
}
}
@@ -539,10 +557,8 @@
LOG(LS_VERBOSE) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): "
<< "Received SCTP data:"
<< " ssrc=" << packet->params.ssrc
- << " data='" << std::string(packet->buffer.data(),
- packet->buffer.length())
<< " notification: " << (packet->flags & MSG_NOTIFICATION)
- << "' length=" << packet->buffer.length();
+ << " length=" << packet->buffer.length();
// Sending a packet with data == NULL (no data) is SCTPs "close the
// connection" message. This sets sock_ = NULL;
if (!packet->buffer.length() || !packet->buffer.data()) {