Chromium Code Reviews| Index: talk/media/sctp/sctpdataengine.cc | 
| diff --git a/talk/media/sctp/sctpdataengine.cc b/talk/media/sctp/sctpdataengine.cc | 
| index 8c8a6a192fa25833c3de66c0587b9ed7ed3bccb3..4274012245a62a9e80d00f8b7a9aa0860d97469e 100644 | 
| --- a/talk/media/sctp/sctpdataengine.cc | 
| +++ b/talk/media/sctp/sctpdataengine.cc | 
| @@ -109,6 +109,8 @@ typedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage; | 
| // 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 | 
| @@ -177,11 +179,11 @@ static bool GetDataMediaType( | 
| } | 
| // Log the packet in text2pcap format, if log level is at LS_VERBOSE. | 
| -static void VerboseLogPacket(void *addr, size_t length, int direction) { | 
| +static void VerboseLogPacket(void *data, size_t length, int direction) { | 
| if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) { | 
| char *dump_buf; | 
| if ((dump_buf = usrsctp_dumppacket( | 
| - addr, length, direction)) != NULL) { | 
| + data, length, direction)) != NULL) { | 
| LOG(LS_VERBOSE) << dump_buf; | 
| usrsctp_freedumpbuffer(dump_buf); | 
| } | 
| @@ -244,6 +246,8 @@ static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr, | 
| // Set the initial value of the static SCTP Data Engines reference count. | 
| int SctpDataEngine::usrsctp_engines_count = 0; | 
| +// Our registrar of sockets to their channels. Used for callbacks. | 
| 
 
pthatcher1
2015/08/24 19:09:31
This might be more clear as "All the channels crea
 
lally1
2015/08/25 16:01:56
Done.
 
 | 
| +std::vector<SctpDataMediaChannel*> SctpDataEngine::channels_; | 
| SctpDataEngine::SctpDataEngine() { | 
| if (usrsctp_engines_count == 0) { | 
| @@ -258,6 +262,11 @@ SctpDataEngine::SctpDataEngine() { | 
| // TODO(ldixon): Consider turning this on/off. | 
| usrsctp_sysctl_set_sctp_ecn_enable(0); | 
| + 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 | 
| @@ -312,9 +321,37 @@ DataMediaChannel* SctpDataEngine::CreateChannel( | 
| if (data_channel_type != DCT_SCTP) { | 
| return NULL; | 
| } | 
| - return new SctpDataMediaChannel(rtc::Thread::Current()); | 
| + SctpDataMediaChannel *channel = new SctpDataMediaChannel( | 
| + rtc::Thread::Current()); | 
| + channels_.push_back(channel); | 
| + channel->SignalDestroyed.connect(this, &SctpDataEngine::OnChannelDestroyed); | 
| + return channel; | 
| } | 
| +void SctpDataEngine::OnChannelDestroyed(SctpDataMediaChannel* channel) { | 
| + auto it = std::find(channels_.begin(), channels_.end(), channel); | 
| + if (it == channels_.end()) { | 
| + LOG(LS_ERROR) << "OnChannelDestroyed: the channel wasn't registered."; | 
| + return; | 
| + } | 
| + channels_.erase(it); | 
| +} | 
| + | 
| +// static | 
| 
 
pthatcher1
2015/08/24 19:09:31
Is it really static?
 
lally1
2015/08/25 16:01:56
Yup.
 
 | 
| +int SctpDataEngine::SendThresholdCallback(struct socket* sock, | 
| + uint32_t sb_free) { | 
| + for (auto p:channels_) { | 
| + if (p->socket() == sock) { | 
| + p->SignalReadyToSend(true); | 
| + return 0; | 
| + } | 
| 
 
pthatcher1
2015/08/24 19:09:31
Would a GetChannelFromSocket method make sense?
 
lally1
2015/08/25 16:01:56
I added it in.  Whether it makes sense: it feels l
 
 | 
| + } | 
| + LOG(LS_ERROR) << "SendThresholdCallback: Failed to get channel for socket " | 
| + << sock; | 
| + return 0; | 
| +} | 
| + | 
| + | 
| SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) | 
| : worker_thread_(thread), | 
| local_port_(kSctpDefaultPort), | 
| @@ -327,6 +364,7 @@ SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) | 
| SctpDataMediaChannel::~SctpDataMediaChannel() { | 
| CloseSctpSocket(); | 
| + SignalDestroyed(this); | 
| } | 
| sockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) { | 
| @@ -347,8 +385,16 @@ bool SctpDataMediaChannel::OpenSctpSocket() { | 
| << "->Ignoring attempt to re-create existing socket."; | 
| return false; | 
| } | 
| + | 
| + // If kSendBufferSize isn't reflective of reality, we log an error, still | 
| 
 
pthatcher1
2015/08/24 19:09:31
still => but we still
?
 
lally1
2015/08/25 16:01:56
Done.
 
 | 
| + // 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 send_threshold = usrsctp_sysctl_get_sctp_sendspace() / 2; | 
| + | 
| sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, | 
| - cricket::OnSctpInboundPacket, NULL, 0, this); | 
| + cricket::OnSctpInboundPacket, | 
| + &SctpDataEngine::SendThresholdCallback, | 
| + send_threshold, this); | 
| if (!sock_) { | 
| LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; | 
| return false; | 
| @@ -393,7 +439,8 @@ bool SctpDataMediaChannel::OpenSctpSocket() { | 
| } | 
| // Disable MTU discovery | 
| - struct sctp_paddrparams params = {{0}}; | 
| + struct sctp_paddrparams params; | 
| + memset(¶ms, 0, sizeof(params)); | 
| params.spp_assoc_id = 0; | 
| params.spp_flags = SPP_PMTUD_DISABLE; | 
| params.spp_pathmtu = kSctpMtu; | 
| @@ -904,10 +951,17 @@ bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { | 
| void SctpDataMediaChannel::OnPacketFromSctpToNetwork( | 
| rtc::Buffer* buffer) { | 
| - if (buffer->size() > kSctpMtu) { | 
| + // usrsctp seems to interpret the MTU we give it strangely -- it seems to | 
| + // give us back packets bigger than that MTU, if only by a fixed amount. | 
| + // This is that amount that we've observed. | 
| + const int kSctpOverhead = 76; | 
| + if (buffer->size() > (kSctpOverhead + kSctpMtu)) { | 
| LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " | 
| << "SCTP seems to have made a packet that is bigger " | 
| - "than its official MTU."; | 
| + << "than its official MTU: " << buffer->size() | 
| + << " vs max of " << kSctpMtu | 
| + << " even after adding " << kSctpOverhead | 
| + << " extra SCTP overhead"; | 
| } | 
| MediaChannel::SendPacket(buffer); | 
| } |