Chromium Code Reviews| 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 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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(¶ms, 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, ¶ms, | 425 if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, ¶ms, |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |