Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: talk/media/sctp/sctpdataengine.cc

Issue 1266033005: Added send-thresholding and fixed text packet dumping. Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2012 Google Inc. and Robin Seggelmann 3 * Copyright 2012 Google Inc. and Robin Seggelmann
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 case SctpDataMediaChannel::PPID_NONE: 170 case SctpDataMediaChannel::PPID_NONE:
171 *dest = cricket::DMT_NONE; 171 *dest = cricket::DMT_NONE;
172 return true; 172 return true;
173 173
174 default: 174 default:
175 return false; 175 return false;
176 } 176 }
177 } 177 }
178 178
179 // Log the packet in text2pcap format, if log level is at LS_VERBOSE. 179 // Log the packet in text2pcap format, if log level is at LS_VERBOSE.
180 static void VerboseLogPacket(void *addr, size_t length, int direction) { 180 static void VerboseLogPacket(void *data, size_t length, int direction) {
181 if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) { 181 if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) {
182 char *dump_buf; 182 char *dump_buf;
183 if ((dump_buf = usrsctp_dumppacket( 183 if ((dump_buf = usrsctp_dumppacket(
184 addr, length, direction)) != NULL) { 184 data, length, direction)) != NULL) {
185 LOG(LS_VERBOSE) << dump_buf; 185 LOG(LS_VERBOSE) << dump_buf;
186 usrsctp_freedumpbuffer(dump_buf); 186 usrsctp_freedumpbuffer(dump_buf);
187 } 187 }
188 } 188 }
189 } 189 }
190 190
191 // This is the callback usrsctp uses when there's data to send on the network 191 // This is the callback usrsctp uses when there's data to send on the network
192 // that has been wrapped appropriatly for the SCTP protocol. 192 // that has been wrapped appropriatly for the SCTP protocol.
193 static int OnSctpOutboundPacket(void* addr, void* data, size_t length, 193 static int OnSctpOutboundPacket(void* addr, void* data, size_t length,
194 uint8_t tos, uint8_t set_df) { 194 uint8_t tos, uint8_t set_df) {
195 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr); 195 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr);
196 LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():" 196 LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
197 << "addr: " << addr << "; length: " << length 197 << "addr: " << addr << "; length: " << length
198 << "; tos: " << std::hex << static_cast<int>(tos) 198 << "; tos: " << std::hex << static_cast<int>(tos)
199 << "; set_df: " << std::hex << static_cast<int>(set_df); 199 << "; set_df: " << std::hex << static_cast<int>(set_df);
200 200
201 VerboseLogPacket(addr, length, SCTP_DUMP_OUTBOUND); 201 VerboseLogPacket(data, length, SCTP_DUMP_OUTBOUND);
202 // Note: We have to copy the data; the caller will delete it. 202 // Note: We have to copy the data; the caller will delete it.
203 auto* msg = new OutboundPacketMessage( 203 auto* msg = new OutboundPacketMessage(
204 new rtc::Buffer(reinterpret_cast<uint8_t*>(data), length)); 204 new rtc::Buffer(reinterpret_cast<uint8_t*>(data), length));
205 channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg); 205 channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg);
206 return 0; 206 return 0;
207 } 207 }
208 208
209 // This is the callback called from usrsctp when data has been received, after 209 // This is the callback called from usrsctp when data has been received, after
210 // a packet has been interpreted and parsed by usrsctp and found to contain 210 // a packet has been interpreted and parsed by usrsctp and found to contain
211 // payload data. It is called by a usrsctp thread. It is assumed this function 211 // payload data. It is called by a usrsctp thread. It is assumed this function
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 } 308 }
309 309
310 DataMediaChannel* SctpDataEngine::CreateChannel( 310 DataMediaChannel* SctpDataEngine::CreateChannel(
311 DataChannelType data_channel_type) { 311 DataChannelType data_channel_type) {
312 if (data_channel_type != DCT_SCTP) { 312 if (data_channel_type != DCT_SCTP) {
313 return NULL; 313 return NULL;
314 } 314 }
315 return new SctpDataMediaChannel(rtc::Thread::Current()); 315 return new SctpDataMediaChannel(rtc::Thread::Current());
316 } 316 }
317 317
318 // Our registrar of sockets to their channels. Used for callbacks.
319 SctpDataMediaChannel::SocketChannelMap SctpDataMediaChannel::sock_channel_map_;
320
318 SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) 321 SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread)
319 : worker_thread_(thread), 322 : worker_thread_(thread),
320 local_port_(kSctpDefaultPort), 323 local_port_(kSctpDefaultPort),
321 remote_port_(kSctpDefaultPort), 324 remote_port_(kSctpDefaultPort),
322 sock_(NULL), 325 sock_(NULL),
323 sending_(false), 326 sending_(false),
324 receiving_(false), 327 receiving_(false),
325 debug_name_("SctpDataMediaChannel") { 328 debug_name_("SctpDataMediaChannel") {
326 } 329 }
327 330
328 SctpDataMediaChannel::~SctpDataMediaChannel() { 331 SctpDataMediaChannel::~SctpDataMediaChannel() {
329 CloseSctpSocket(); 332 CloseSctpSocket();
330 } 333 }
331 334
332 sockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) { 335 sockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) {
333 sockaddr_conn sconn = {0}; 336 sockaddr_conn sconn = {0};
334 sconn.sconn_family = AF_CONN; 337 sconn.sconn_family = AF_CONN;
335 #ifdef HAVE_SCONN_LEN 338 #ifdef HAVE_SCONN_LEN
336 sconn.sconn_len = sizeof(sockaddr_conn); 339 sconn.sconn_len = sizeof(sockaddr_conn);
337 #endif 340 #endif
338 // Note: conversion from int to uint16_t happens here. 341 // Note: conversion from int to uint16_t happens here.
339 sconn.sconn_port = rtc::HostToNetwork16(port); 342 sconn.sconn_port = rtc::HostToNetwork16(port);
340 sconn.sconn_addr = this; 343 sconn.sconn_addr = this;
341 return sconn; 344 return sconn;
342 } 345 }
343 346
347 // static
348 int SctpDataMediaChannel::SendThresholdCallback(struct socket* sock,
pthatcher1 2015/08/05 21:42:55 I think it would make more sense to put this callb
lally1 2015/08/18 20:38:56 I don't know where I'd get an instance pointer.
pthatcher1 2015/08/18 21:51:52 The instance pointer to the engine? Could you use
349 uint32_t sb_free) {
pthatcher1 2015/08/05 21:42:55 No ulp_info, like with reading a packet? That's l
lally1 2015/08/18 20:38:56 Yeah, that's the real issue here. I had a prior v
350 SocketChannelMap::iterator it = sock_channel_map_.find(sock);
pthatcher1 2015/08/05 21:42:55 You can use auto it = sock_channel_map_.find(soc
lally1 2015/08/18 20:38:56 Thanks!
351 if (it == sock_channel_map_.end()) {
pthatcher1 2015/08/05 21:42:55 Since there are almost always a very low number of
lally1 2015/08/18 20:38:56 Done.
352 // Socket is in the process of shutdown.
353 LOG(LS_ERROR) << "Failed to get SctpDataMediaChannel for socket " << sock;
354 return 0;
355 }
356
357 it->second->SignalReadyToSend(true);
358 return 0;
359 }
360
344 bool SctpDataMediaChannel::OpenSctpSocket() { 361 bool SctpDataMediaChannel::OpenSctpSocket() {
345 if (sock_) { 362 if (sock_) {
346 LOG(LS_VERBOSE) << debug_name_ 363 LOG(LS_VERBOSE) << debug_name_
347 << "->Ignoring attempt to re-create existing socket."; 364 << "->Ignoring attempt to re-create existing socket.";
348 return false; 365 return false;
349 } 366 }
367
368 const int send_threshold = usrsctp_sysctl_get_sctp_sendspace() / 2;
369
350 sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, 370 sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP,
351 cricket::OnSctpInboundPacket, NULL, 0, this); 371 cricket::OnSctpInboundPacket,
372 &SctpDataMediaChannel::SendThresholdCallback,
373 send_threshold, this);
352 if (!sock_) { 374 if (!sock_) {
353 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; 375 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket.";
354 return false; 376 return false;
355 } 377 }
356 378
379 sock_channel_map_[sock_] = this;
380
357 // Make the socket non-blocking. Connect, close, shutdown etc will not block 381 // Make the socket non-blocking. Connect, close, shutdown etc will not block
358 // the thread waiting for the socket operation to complete. 382 // the thread waiting for the socket operation to complete.
359 if (usrsctp_set_non_blocking(sock_, 1) < 0) { 383 if (usrsctp_set_non_blocking(sock_, 1) < 0) {
360 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking."; 384 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking.";
361 return false; 385 return false;
362 } 386 }
363 387
364 // This ensures that the usrsctp close call deletes the association. This 388 // This ensures that the usrsctp close call deletes the association. This
365 // prevents usrsctp from calling OnSctpOutboundPacket with references to 389 // prevents usrsctp from calling OnSctpOutboundPacket with references to
366 // this class as the address. 390 // this class as the address.
(...skipping 19 matching lines...) Expand all
386 410
387 // Nagle. 411 // Nagle.
388 uint32_t nodelay = 1; 412 uint32_t nodelay = 1;
389 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, 413 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay,
390 sizeof(nodelay))) { 414 sizeof(nodelay))) {
391 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY."; 415 LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY.";
392 return false; 416 return false;
393 } 417 }
394 418
395 // Disable MTU discovery 419 // Disable MTU discovery
396 struct sctp_paddrparams params = {{0}}; 420 struct sctp_paddrparams params;
421 memset(&params, 0, sizeof(params));
397 params.spp_assoc_id = 0; 422 params.spp_assoc_id = 0;
398 params.spp_flags = SPP_PMTUD_DISABLE; 423 params.spp_flags = SPP_PMTUD_DISABLE;
399 params.spp_pathmtu = kSctpMtu; 424 params.spp_pathmtu = kSctpMtu;
400 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &params, 425 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &params,
401 sizeof(params))) { 426 sizeof(params))) {
402 LOG_ERRNO(LS_ERROR) << debug_name_ 427 LOG_ERRNO(LS_ERROR) << debug_name_
403 << "Failed to set SCTP_PEER_ADDR_PARAMS."; 428 << "Failed to set SCTP_PEER_ADDR_PARAMS.";
404 return false; 429 return false;
405 } 430 }
406 431
(...skipping 23 matching lines...) Expand all
430 return true; 455 return true;
431 } 456 }
432 457
433 void SctpDataMediaChannel::CloseSctpSocket() { 458 void SctpDataMediaChannel::CloseSctpSocket() {
434 sending_ = false; 459 sending_ = false;
435 if (sock_) { 460 if (sock_) {
436 // We assume that SO_LINGER option is set to close the association when 461 // We assume that SO_LINGER option is set to close the association when
437 // close is called. This means that any pending packets in usrsctp will be 462 // close is called. This means that any pending packets in usrsctp will be
438 // discarded instead of being sent. 463 // discarded instead of being sent.
439 usrsctp_close(sock_); 464 usrsctp_close(sock_);
465 SocketChannelMap::iterator it = sock_channel_map_.find(sock_);
466 if (it != sock_channel_map_.end()) {
467 sock_channel_map_.erase(it);
468 } else {
469 LOG(LS_ERROR) << "CloseSctpSocket: the socket wasn't registered.";
470 }
pthatcher1 2015/08/05 21:42:55 I think this works, and it shorter and only does o
lally1 2015/08/18 20:38:56 Thanks. Moved above into ~SctpDataMediaChannel(),
440 sock_ = NULL; 471 sock_ = NULL;
441 usrsctp_deregister_address(this); 472 usrsctp_deregister_address(this);
442 } 473 }
443 } 474 }
444 475
445 bool SctpDataMediaChannel::Connect() { 476 bool SctpDataMediaChannel::Connect() {
446 LOG(LS_VERBOSE) << debug_name_ << "->Connect()."; 477 LOG(LS_VERBOSE) << debug_name_ << "->Connect().";
447 478
448 // If we already have a socket connection, just return. 479 // If we already have a socket connection, just return.
449 if (sock_) { 480 if (sock_) {
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 } 928 }
898 929
899 bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { 930 bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
900 return GetCodecIntParameter( 931 return GetCodecIntParameter(
901 codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 932 codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
902 &local_port_); 933 &local_port_);
903 } 934 }
904 935
905 void SctpDataMediaChannel::OnPacketFromSctpToNetwork( 936 void SctpDataMediaChannel::OnPacketFromSctpToNetwork(
906 rtc::Buffer* buffer) { 937 rtc::Buffer* buffer) {
907 if (buffer->size() > kSctpMtu) { 938 // this is completely made up.
939 const int kSctpOverhead = 76;
pthatcher1 2015/08/05 21:42:55 This could use a little more documentation, even i
lally1 2015/08/18 20:38:56 Done.
940 if (buffer->size() > (kSctpOverhead + kSctpMtu)) {
908 LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " 941 LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): "
909 << "SCTP seems to have made a packet that is bigger " 942 << "SCTP seems to have made a packet that is bigger "
910 "than its official MTU."; 943 << "than its official MTU: " << buffer->size()
944 << " vs max of " << kSctpMtu;
pthatcher1 2015/08/05 21:42:55 Should probably include something like "assuming X
lally1 2015/08/18 20:38:56 Done.
911 } 945 }
912 MediaChannel::SendPacket(buffer); 946 MediaChannel::SendPacket(buffer);
913 } 947 }
914 948
915 bool SctpDataMediaChannel::SendQueuedStreamResets() { 949 bool SctpDataMediaChannel::SendQueuedStreamResets() {
916 if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) 950 if (!sent_reset_streams_.empty() || queued_reset_streams_.empty())
917 return true; 951 return true;
918 952
919 LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending [" 953 LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending ["
920 << ListStreams(queued_reset_streams_) << "], Open: [" 954 << ListStreams(queued_reset_streams_) << "], Open: ["
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 } 996 }
963 case MSG_SCTPOUTBOUNDPACKET: { 997 case MSG_SCTPOUTBOUNDPACKET: {
964 rtc::scoped_ptr<OutboundPacketMessage> pdata( 998 rtc::scoped_ptr<OutboundPacketMessage> pdata(
965 static_cast<OutboundPacketMessage*>(msg->pdata)); 999 static_cast<OutboundPacketMessage*>(msg->pdata));
966 OnPacketFromSctpToNetwork(pdata->data().get()); 1000 OnPacketFromSctpToNetwork(pdata->data().get());
967 break; 1001 break;
968 } 1002 }
969 } 1003 }
970 } 1004 }
971 } // namespace cricket 1005 } // namespace cricket
OLDNEW
« talk/media/sctp/sctpdataengine.h ('K') | « talk/media/sctp/sctpdataengine.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698