| OLD | NEW | 
|---|
| 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 102 }  // namespace | 102 }  // namespace | 
| 103 | 103 | 
| 104 namespace cricket { | 104 namespace cricket { | 
| 105 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage; | 105 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage; | 
| 106 typedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage; | 106 typedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage; | 
| 107 | 107 | 
| 108 // The biggest SCTP packet.  Starting from a 'safe' wire MTU value of 1280, | 108 // The biggest SCTP packet.  Starting from a 'safe' wire MTU value of 1280, | 
| 109 // take off 80 bytes for DTLS/TURN/TCP/IP overhead. | 109 // take off 80 bytes for DTLS/TURN/TCP/IP overhead. | 
| 110 static const size_t kSctpMtu = 1200; | 110 static const size_t kSctpMtu = 1200; | 
| 111 | 111 | 
| 112 // The size of the SCTP association send buffer.  256kB, the usrsctp default. |  | 
| 113 static const int kSendBufferSize = 262144; |  | 
| 114 enum { | 112 enum { | 
| 115   MSG_SCTPINBOUNDPACKET = 1,   // MessageData is SctpInboundPacket | 113   MSG_SCTPINBOUNDPACKET = 1,   // MessageData is SctpInboundPacket | 
| 116   MSG_SCTPOUTBOUNDPACKET = 2,  // MessageData is rtc:Buffer | 114   MSG_SCTPOUTBOUNDPACKET = 2,  // MessageData is rtc:Buffer | 
| 117 }; | 115 }; | 
| 118 | 116 | 
| 119 struct SctpInboundPacket { | 117 struct SctpInboundPacket { | 
| 120   rtc::Buffer buffer; | 118   rtc::Buffer buffer; | 
| 121   ReceiveDataParams params; | 119   ReceiveDataParams params; | 
| 122   // The |flags| parameter is used by SCTP to distinguish notification packets | 120   // The |flags| parameter is used by SCTP to distinguish notification packets | 
| 123   // from other types of packets. | 121   // from other types of packets. | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 172     case SctpDataMediaChannel::PPID_NONE: | 170     case SctpDataMediaChannel::PPID_NONE: | 
| 173       *dest = cricket::DMT_NONE; | 171       *dest = cricket::DMT_NONE; | 
| 174       return true; | 172       return true; | 
| 175 | 173 | 
| 176     default: | 174     default: | 
| 177       return false; | 175       return false; | 
| 178   } | 176   } | 
| 179 } | 177 } | 
| 180 | 178 | 
| 181 // 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. | 
| 182 static void VerboseLogPacket(void *data, size_t length, int direction) { | 180 static void VerboseLogPacket(void *addr, size_t length, int direction) { | 
| 183   if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) { | 181   if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) { | 
| 184     char *dump_buf; | 182     char *dump_buf; | 
| 185     if ((dump_buf = usrsctp_dumppacket( | 183     if ((dump_buf = usrsctp_dumppacket( | 
| 186              data, length, direction)) != NULL) { | 184              addr, length, direction)) != NULL) { | 
| 187       LOG(LS_VERBOSE) << dump_buf; | 185       LOG(LS_VERBOSE) << dump_buf; | 
| 188       usrsctp_freedumpbuffer(dump_buf); | 186       usrsctp_freedumpbuffer(dump_buf); | 
| 189     } | 187     } | 
| 190   } | 188   } | 
| 191 } | 189 } | 
| 192 | 190 | 
| 193 // 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 | 
| 194 // that has been wrapped appropriatly for the SCTP protocol. | 192 // that has been wrapped appropriatly for the SCTP protocol. | 
| 195 static int OnSctpOutboundPacket(void* addr, void* data, size_t length, | 193 static int OnSctpOutboundPacket(void* addr, void* data, size_t length, | 
| 196                                 uint8_t tos, uint8_t set_df) { | 194                                 uint8_t tos, uint8_t set_df) { | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 239     // The ownership of |packet| transfers to |msg|. | 237     // The ownership of |packet| transfers to |msg|. | 
| 240     InboundPacketMessage* msg = new InboundPacketMessage(packet); | 238     InboundPacketMessage* msg = new InboundPacketMessage(packet); | 
| 241     channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET, msg); | 239     channel->worker_thread()->Post(channel, MSG_SCTPINBOUNDPACKET, msg); | 
| 242   } | 240   } | 
| 243   free(data); | 241   free(data); | 
| 244   return 1; | 242   return 1; | 
| 245 } | 243 } | 
| 246 | 244 | 
| 247 // Set the initial value of the static SCTP Data Engines reference count. | 245 // Set the initial value of the static SCTP Data Engines reference count. | 
| 248 int SctpDataEngine::usrsctp_engines_count = 0; | 246 int SctpDataEngine::usrsctp_engines_count = 0; | 
| 249 // All the channels created by this engine, used for callbacks from |  | 
| 250 // usrsctplib that only contain socket pointers.  Channels are removed when |  | 
| 251 // SignalDestroyed is fired. |  | 
| 252 std::vector<SctpDataMediaChannel*> SctpDataEngine::channels_; |  | 
| 253 | 247 | 
| 254 SctpDataEngine::SctpDataEngine() { | 248 SctpDataEngine::SctpDataEngine() { | 
| 255   if (usrsctp_engines_count == 0) { | 249   if (usrsctp_engines_count == 0) { | 
| 256     // First argument is udp_encapsulation_port, which is not releveant for our | 250     // First argument is udp_encapsulation_port, which is not releveant for our | 
| 257     // AF_CONN use of sctp. | 251     // AF_CONN use of sctp. | 
| 258     usrsctp_init(0, cricket::OnSctpOutboundPacket, debug_sctp_printf); | 252     usrsctp_init(0, cricket::OnSctpOutboundPacket, debug_sctp_printf); | 
| 259 | 253 | 
| 260     // To turn on/off detailed SCTP debugging. You will also need to have the | 254     // To turn on/off detailed SCTP debugging. You will also need to have the | 
| 261     // SCTP_DEBUG cpp defines flag. | 255     // SCTP_DEBUG cpp defines flag. | 
| 262     // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); | 256     // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); | 
| 263 | 257 | 
| 264     // TODO(ldixon): Consider turning this on/off. | 258     // TODO(ldixon): Consider turning this on/off. | 
| 265     usrsctp_sysctl_set_sctp_ecn_enable(0); | 259     usrsctp_sysctl_set_sctp_ecn_enable(0); | 
| 266 | 260 | 
| 267     int send_size = usrsctp_sysctl_get_sctp_sendspace(); |  | 
| 268     if (send_size != kSendBufferSize) { |  | 
| 269       LOG(LS_ERROR) << "Got different send size than expected: " << send_size; |  | 
| 270     } |  | 
| 271 |  | 
| 272     // TODO(ldixon): Consider turning this on/off. | 261     // TODO(ldixon): Consider turning this on/off. | 
| 273     // This is not needed right now (we don't do dynamic address changes): | 262     // This is not needed right now (we don't do dynamic address changes): | 
| 274     // If SCTP Auto-ASCONF is enabled, the peer is informed automatically | 263     // If SCTP Auto-ASCONF is enabled, the peer is informed automatically | 
| 275     // when a new address is added or removed. This feature is enabled by | 264     // when a new address is added or removed. This feature is enabled by | 
| 276     // default. | 265     // default. | 
| 277     // usrsctp_sysctl_set_sctp_auto_asconf(0); | 266     // usrsctp_sysctl_set_sctp_auto_asconf(0); | 
| 278 | 267 | 
| 279     // TODO(ldixon): Consider turning this on/off. | 268     // TODO(ldixon): Consider turning this on/off. | 
| 280     // Add a blackhole sysctl. Setting it to 1 results in no ABORTs | 269     // Add a blackhole sysctl. Setting it to 1 results in no ABORTs | 
| 281     // being sent in response to INITs, setting it to 2 results | 270     // being sent in response to INITs, setting it to 2 results | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 316     } | 305     } | 
| 317     LOG(LS_ERROR) << "Failed to shutdown usrsctp."; | 306     LOG(LS_ERROR) << "Failed to shutdown usrsctp."; | 
| 318   } | 307   } | 
| 319 } | 308 } | 
| 320 | 309 | 
| 321 DataMediaChannel* SctpDataEngine::CreateChannel( | 310 DataMediaChannel* SctpDataEngine::CreateChannel( | 
| 322     DataChannelType data_channel_type) { | 311     DataChannelType data_channel_type) { | 
| 323   if (data_channel_type != DCT_SCTP) { | 312   if (data_channel_type != DCT_SCTP) { | 
| 324     return NULL; | 313     return NULL; | 
| 325   } | 314   } | 
| 326   SctpDataMediaChannel *channel = new SctpDataMediaChannel( | 315   return new SctpDataMediaChannel(rtc::Thread::Current()); | 
| 327       rtc::Thread::Current()); |  | 
| 328   channels_.push_back(channel); |  | 
| 329   channel->SignalDestroyed.connect(this, &SctpDataEngine::OnChannelDestroyed); |  | 
| 330   return channel; |  | 
| 331 } | 316 } | 
| 332 | 317 | 
| 333 // static |  | 
| 334 SctpDataMediaChannel* SctpDataEngine::GetChannelFromSocket( |  | 
| 335     struct socket* sock) { |  | 
| 336   for (auto p:channels_) { |  | 
| 337     if (p->socket() == sock) { |  | 
| 338       return p; |  | 
| 339     } |  | 
| 340   } |  | 
| 341   return 0; |  | 
| 342 } |  | 
| 343 |  | 
| 344 |  | 
| 345 void SctpDataEngine::OnChannelDestroyed(SctpDataMediaChannel* channel) { |  | 
| 346   auto it = std::find(channels_.begin(), channels_.end(), channel); |  | 
| 347   if (it == channels_.end()) { |  | 
| 348     LOG(LS_ERROR) << "OnChannelDestroyed: the channel wasn't registered."; |  | 
| 349     return; |  | 
| 350   } |  | 
| 351   channels_.erase(it); |  | 
| 352 } |  | 
| 353 |  | 
| 354 // static |  | 
| 355 int SctpDataEngine::SendThresholdCallback(struct socket* sock, |  | 
| 356                                           uint32_t sb_free) { |  | 
| 357   SctpDataMediaChannel *channel = GetChannelFromSocket(sock); |  | 
| 358   if (!channel) { |  | 
| 359     LOG(LS_ERROR) << "SendThresholdCallback: Failed to get channel for socket " |  | 
| 360                   << sock; |  | 
| 361     return 0; |  | 
| 362   } |  | 
| 363   channel->SignalReadyToSend(true); |  | 
| 364   return 0; |  | 
| 365 } |  | 
| 366 |  | 
| 367 |  | 
| 368 SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) | 318 SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread) | 
| 369     : worker_thread_(thread), | 319     : worker_thread_(thread), | 
| 370       local_port_(kSctpDefaultPort), | 320       local_port_(kSctpDefaultPort), | 
| 371       remote_port_(kSctpDefaultPort), | 321       remote_port_(kSctpDefaultPort), | 
| 372       sock_(NULL), | 322       sock_(NULL), | 
| 373       sending_(false), | 323       sending_(false), | 
| 374       receiving_(false), | 324       receiving_(false), | 
| 375       debug_name_("SctpDataMediaChannel") { | 325       debug_name_("SctpDataMediaChannel") { | 
| 376 } | 326 } | 
| 377 | 327 | 
| 378 SctpDataMediaChannel::~SctpDataMediaChannel() { | 328 SctpDataMediaChannel::~SctpDataMediaChannel() { | 
| 379   CloseSctpSocket(); | 329   CloseSctpSocket(); | 
| 380   SignalDestroyed(this); |  | 
| 381 } | 330 } | 
| 382 | 331 | 
| 383 sockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) { | 332 sockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) { | 
| 384   sockaddr_conn sconn = {0}; | 333   sockaddr_conn sconn = {0}; | 
| 385   sconn.sconn_family = AF_CONN; | 334   sconn.sconn_family = AF_CONN; | 
| 386 #ifdef HAVE_SCONN_LEN | 335 #ifdef HAVE_SCONN_LEN | 
| 387   sconn.sconn_len = sizeof(sockaddr_conn); | 336   sconn.sconn_len = sizeof(sockaddr_conn); | 
| 388 #endif | 337 #endif | 
| 389   // Note: conversion from int to uint16_t happens here. | 338   // Note: conversion from int to uint16_t happens here. | 
| 390   sconn.sconn_port = rtc::HostToNetwork16(port); | 339   sconn.sconn_port = rtc::HostToNetwork16(port); | 
| 391   sconn.sconn_addr = this; | 340   sconn.sconn_addr = this; | 
| 392   return sconn; | 341   return sconn; | 
| 393 } | 342 } | 
| 394 | 343 | 
| 395 bool SctpDataMediaChannel::OpenSctpSocket() { | 344 bool SctpDataMediaChannel::OpenSctpSocket() { | 
| 396   if (sock_) { | 345   if (sock_) { | 
| 397     LOG(LS_VERBOSE) << debug_name_ | 346     LOG(LS_VERBOSE) << debug_name_ | 
| 398                     << "->Ignoring attempt to re-create existing socket."; | 347                     << "->Ignoring attempt to re-create existing socket."; | 
| 399     return false; | 348     return false; | 
| 400   } | 349   } | 
| 401 |  | 
| 402   // If kSendBufferSize isn't reflective of reality, we log an error, but we |  | 
| 403   // still have to do something reasonable here.  Look up what the buffer's |  | 
| 404   // real size is and set our threshold to something reasonable. |  | 
| 405   const static int send_threshold = usrsctp_sysctl_get_sctp_sendspace() / 2; |  | 
| 406 |  | 
| 407   sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, | 350   sock_ = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, | 
| 408                          cricket::OnSctpInboundPacket, | 351                          cricket::OnSctpInboundPacket, NULL, 0, this); | 
| 409                          &SctpDataEngine::SendThresholdCallback, |  | 
| 410                          send_threshold, this); |  | 
| 411   if (!sock_) { | 352   if (!sock_) { | 
| 412     LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; | 353     LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket."; | 
| 413     return false; | 354     return false; | 
| 414   } | 355   } | 
| 415 | 356 | 
| 416   // Make the socket non-blocking. Connect, close, shutdown etc will not block | 357   // Make the socket non-blocking. Connect, close, shutdown etc will not block | 
| 417   // the thread waiting for the socket operation to complete. | 358   // the thread waiting for the socket operation to complete. | 
| 418   if (usrsctp_set_non_blocking(sock_, 1) < 0) { | 359   if (usrsctp_set_non_blocking(sock_, 1) < 0) { | 
| 419     LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking."; | 360     LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking."; | 
| 420     return false; | 361     return false; | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 445 | 386 | 
| 446   // Nagle. | 387   // Nagle. | 
| 447   uint32_t nodelay = 1; | 388   uint32_t nodelay = 1; | 
| 448   if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, | 389   if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, | 
| 449                          sizeof(nodelay))) { | 390                          sizeof(nodelay))) { | 
| 450     LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY."; | 391     LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY."; | 
| 451     return false; | 392     return false; | 
| 452   } | 393   } | 
| 453 | 394 | 
| 454   // Disable MTU discovery | 395   // Disable MTU discovery | 
| 455   struct sctp_paddrparams params; | 396   struct sctp_paddrparams params = {{0}}; | 
| 456   memset(¶ms, 0, sizeof(params)); |  | 
| 457   params.spp_assoc_id = 0; | 397   params.spp_assoc_id = 0; | 
| 458   params.spp_flags = SPP_PMTUD_DISABLE; | 398   params.spp_flags = SPP_PMTUD_DISABLE; | 
| 459   params.spp_pathmtu = kSctpMtu; | 399   params.spp_pathmtu = kSctpMtu; | 
| 460   if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, ¶ms, | 400   if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, ¶ms, | 
| 461       sizeof(params))) { | 401       sizeof(params))) { | 
| 462     LOG_ERRNO(LS_ERROR) << debug_name_ | 402     LOG_ERRNO(LS_ERROR) << debug_name_ | 
| 463                         << "Failed to set SCTP_PEER_ADDR_PARAMS."; | 403                         << "Failed to set SCTP_PEER_ADDR_PARAMS."; | 
| 464     return false; | 404     return false; | 
| 465   } | 405   } | 
| 466 | 406 | 
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 957 } | 897 } | 
| 958 | 898 | 
| 959 bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { | 899 bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { | 
| 960   return GetCodecIntParameter( | 900   return GetCodecIntParameter( | 
| 961       codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, | 901       codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, | 
| 962       &local_port_); | 902       &local_port_); | 
| 963 } | 903 } | 
| 964 | 904 | 
| 965 void SctpDataMediaChannel::OnPacketFromSctpToNetwork( | 905 void SctpDataMediaChannel::OnPacketFromSctpToNetwork( | 
| 966     rtc::Buffer* buffer) { | 906     rtc::Buffer* buffer) { | 
| 967   // usrsctp seems to interpret the MTU we give it strangely -- it seems to | 907   if (buffer->size() > kSctpMtu) { | 
| 968   // give us back packets bigger than that MTU, if only by a fixed amount. |  | 
| 969   // This is that amount that we've observed. |  | 
| 970   const int kSctpOverhead = 76; |  | 
| 971   if (buffer->size() > (kSctpOverhead + kSctpMtu)) { |  | 
| 972     LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " | 908     LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " | 
| 973                   << "SCTP seems to have made a packet that is bigger " | 909                   << "SCTP seems to have made a packet that is bigger " | 
| 974                   << "than its official MTU: " << buffer->size() | 910                      "than its official MTU."; | 
| 975                   << " vs max of " << kSctpMtu |  | 
| 976                   << " even after adding " << kSctpOverhead |  | 
| 977                   << " extra SCTP overhead"; |  | 
| 978   } | 911   } | 
| 979   MediaChannel::SendPacket(buffer); | 912   MediaChannel::SendPacket(buffer); | 
| 980 } | 913 } | 
| 981 | 914 | 
| 982 bool SctpDataMediaChannel::SendQueuedStreamResets() { | 915 bool SctpDataMediaChannel::SendQueuedStreamResets() { | 
| 983   if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) | 916   if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) | 
| 984     return true; | 917     return true; | 
| 985 | 918 | 
| 986   LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending [" | 919   LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending [" | 
| 987                   << ListStreams(queued_reset_streams_) << "], Open: [" | 920                   << ListStreams(queued_reset_streams_) << "], Open: [" | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1029     } | 962     } | 
| 1030     case MSG_SCTPOUTBOUNDPACKET: { | 963     case MSG_SCTPOUTBOUNDPACKET: { | 
| 1031       rtc::scoped_ptr<OutboundPacketMessage> pdata( | 964       rtc::scoped_ptr<OutboundPacketMessage> pdata( | 
| 1032           static_cast<OutboundPacketMessage*>(msg->pdata)); | 965           static_cast<OutboundPacketMessage*>(msg->pdata)); | 
| 1033       OnPacketFromSctpToNetwork(pdata->data().get()); | 966       OnPacketFromSctpToNetwork(pdata->data().get()); | 
| 1034       break; | 967       break; | 
| 1035     } | 968     } | 
| 1036   } | 969   } | 
| 1037 } | 970 } | 
| 1038 }  // namespace cricket | 971 }  // namespace cricket | 
| OLD | NEW | 
|---|