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

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

Issue 1823503002: Reland Use CopyOnWriteBuffer instead of Buffer to avoid unnecessary copies. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 9 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
« no previous file with comments | « webrtc/media/sctp/sctpdataengine.h ('k') | webrtc/media/sctp/sctpdataengine_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/media/sctp/sctpdataengine.h" 11 #include "webrtc/media/sctp/sctpdataengine.h"
12 12
13 #include <stdarg.h> 13 #include <stdarg.h>
14 #include <stdio.h> 14 #include <stdio.h>
15 15
16 #include <memory> 16 #include <memory>
17 #include <sstream> 17 #include <sstream>
18 #include <vector> 18 #include <vector>
19 19
20 #include "usrsctplib/usrsctp.h" 20 #include "usrsctplib/usrsctp.h"
21 #include "webrtc/base/arraysize.h" 21 #include "webrtc/base/arraysize.h"
22 #include "webrtc/base/buffer.h" 22 #include "webrtc/base/copyonwritebuffer.h"
23 #include "webrtc/base/helpers.h" 23 #include "webrtc/base/helpers.h"
24 #include "webrtc/base/logging.h" 24 #include "webrtc/base/logging.h"
25 #include "webrtc/base/safe_conversions.h" 25 #include "webrtc/base/safe_conversions.h"
26 #include "webrtc/media/base/codec.h" 26 #include "webrtc/media/base/codec.h"
27 #include "webrtc/media/base/mediaconstants.h" 27 #include "webrtc/media/base/mediaconstants.h"
28 #include "webrtc/media/base/streamparams.h" 28 #include "webrtc/media/base/streamparams.h"
29 29
30 namespace { 30 namespace {
31 typedef cricket::SctpDataMediaChannel::StreamSet StreamSet; 31 typedef cricket::SctpDataMediaChannel::StreamSet StreamSet;
32 // Returns a comma-separated, human-readable list of the stream IDs in 's' 32 // Returns a comma-separated, human-readable list of the stream IDs in 's'
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 } else { 82 } else {
83 result << array[i]; 83 result << array[i];
84 } 84 }
85 } 85 }
86 return result.str(); 86 return result.str();
87 } 87 }
88 } // namespace 88 } // namespace
89 89
90 namespace cricket { 90 namespace cricket {
91 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage; 91 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage;
92 typedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage; 92 typedef rtc::ScopedMessageData<rtc::CopyOnWriteBuffer> OutboundPacketMessage;
93 93
94 // The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280, 94 // The biggest SCTP packet. Starting from a 'safe' wire MTU value of 1280,
95 // take off 80 bytes for DTLS/TURN/TCP/IP overhead. 95 // take off 80 bytes for DTLS/TURN/TCP/IP overhead.
96 static const size_t kSctpMtu = 1200; 96 static const size_t kSctpMtu = 1200;
97 97
98 // The size of the SCTP association send buffer. 256kB, the usrsctp default. 98 // The size of the SCTP association send buffer. 256kB, the usrsctp default.
99 static const int kSendBufferSize = 262144; 99 static const int kSendBufferSize = 262144;
100 enum { 100 enum {
101 MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket 101 MSG_SCTPINBOUNDPACKET = 1, // MessageData is SctpInboundPacket
102 MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer 102 MSG_SCTPOUTBOUNDPACKET = 2, // MessageData is rtc:Buffer
103 }; 103 };
104 104
105 struct SctpInboundPacket { 105 struct SctpInboundPacket {
106 rtc::Buffer buffer; 106 rtc::CopyOnWriteBuffer buffer;
107 ReceiveDataParams params; 107 ReceiveDataParams params;
108 // The |flags| parameter is used by SCTP to distinguish notification packets 108 // The |flags| parameter is used by SCTP to distinguish notification packets
109 // from other types of packets. 109 // from other types of packets.
110 int flags; 110 int flags;
111 }; 111 };
112 112
113 // Helper for logging SCTP messages. 113 // Helper for logging SCTP messages.
114 static void debug_sctp_printf(const char *format, ...) { 114 static void debug_sctp_printf(const char *format, ...) {
115 char s[255]; 115 char s[255];
116 va_list ap; 116 va_list ap;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 case SctpDataMediaChannel::PPID_NONE: 158 case SctpDataMediaChannel::PPID_NONE:
159 *dest = cricket::DMT_NONE; 159 *dest = cricket::DMT_NONE;
160 return true; 160 return true;
161 161
162 default: 162 default:
163 return false; 163 return false;
164 } 164 }
165 } 165 }
166 166
167 // Log the packet in text2pcap format, if log level is at LS_VERBOSE. 167 // Log the packet in text2pcap format, if log level is at LS_VERBOSE.
168 static void VerboseLogPacket(void *data, size_t length, int direction) { 168 static void VerboseLogPacket(const void *data, size_t length, int direction) {
169 if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) { 169 if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) {
170 char *dump_buf; 170 char *dump_buf;
171 // Some downstream project uses an older version of usrsctp that expects
172 // a non-const "void*" as first parameter when dumping the packet, so we
173 // need to cast the const away here to avoid a compiler error.
171 if ((dump_buf = usrsctp_dumppacket( 174 if ((dump_buf = usrsctp_dumppacket(
172 data, length, direction)) != NULL) { 175 const_cast<void*>(data), length, direction)) != NULL) {
joachim 2016/03/20 10:14:10 This is the change compared to https://codereview.
173 LOG(LS_VERBOSE) << dump_buf; 176 LOG(LS_VERBOSE) << dump_buf;
174 usrsctp_freedumpbuffer(dump_buf); 177 usrsctp_freedumpbuffer(dump_buf);
175 } 178 }
176 } 179 }
177 } 180 }
178 181
179 // This is the callback usrsctp uses when there's data to send on the network 182 // This is the callback usrsctp uses when there's data to send on the network
180 // that has been wrapped appropriatly for the SCTP protocol. 183 // that has been wrapped appropriatly for the SCTP protocol.
181 static int OnSctpOutboundPacket(void* addr, void* data, size_t length, 184 static int OnSctpOutboundPacket(void* addr, void* data, size_t length,
182 uint8_t tos, uint8_t set_df) { 185 uint8_t tos, uint8_t set_df) {
183 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr); 186 SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr);
184 LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():" 187 LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
185 << "addr: " << addr << "; length: " << length 188 << "addr: " << addr << "; length: " << length
186 << "; tos: " << std::hex << static_cast<int>(tos) 189 << "; tos: " << std::hex << static_cast<int>(tos)
187 << "; set_df: " << std::hex << static_cast<int>(set_df); 190 << "; set_df: " << std::hex << static_cast<int>(set_df);
188 191
189 VerboseLogPacket(addr, length, SCTP_DUMP_OUTBOUND); 192 VerboseLogPacket(addr, length, SCTP_DUMP_OUTBOUND);
190 // Note: We have to copy the data; the caller will delete it. 193 // Note: We have to copy the data; the caller will delete it.
191 auto* msg = new OutboundPacketMessage( 194 auto* msg = new OutboundPacketMessage(
192 new rtc::Buffer(reinterpret_cast<uint8_t*>(data), length)); 195 new rtc::CopyOnWriteBuffer(reinterpret_cast<uint8_t*>(data), length));
193 channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg); 196 channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg);
194 return 0; 197 return 0;
195 } 198 }
196 199
197 // This is the callback called from usrsctp when data has been received, after 200 // This is the callback called from usrsctp when data has been received, after
198 // a packet has been interpreted and parsed by usrsctp and found to contain 201 // a packet has been interpreted and parsed by usrsctp and found to contain
199 // payload data. It is called by a usrsctp thread. It is assumed this function 202 // payload data. It is called by a usrsctp thread. It is assumed this function
200 // will free the memory used by 'data'. 203 // will free the memory used by 'data'.
201 static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr, 204 static int OnSctpInboundPacket(struct socket* sock, union sctp_sockstore addr,
202 void* data, size_t length, 205 void* data, size_t length,
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 577
575 bool SctpDataMediaChannel::RemoveRecvStream(uint32_t ssrc) { 578 bool SctpDataMediaChannel::RemoveRecvStream(uint32_t ssrc) {
576 // SCTP DataChannels are always bi-directional and calling RemoveSendStream 579 // SCTP DataChannels are always bi-directional and calling RemoveSendStream
577 // will disable both sending and receiving on the stream. So RemoveRecvStream 580 // will disable both sending and receiving on the stream. So RemoveRecvStream
578 // is a no-op. 581 // is a no-op.
579 return true; 582 return true;
580 } 583 }
581 584
582 bool SctpDataMediaChannel::SendData( 585 bool SctpDataMediaChannel::SendData(
583 const SendDataParams& params, 586 const SendDataParams& params,
584 const rtc::Buffer& payload, 587 const rtc::CopyOnWriteBuffer& payload,
585 SendDataResult* result) { 588 SendDataResult* result) {
586 if (result) { 589 if (result) {
587 // Preset |result| to assume an error. If SendData succeeds, we'll 590 // Preset |result| to assume an error. If SendData succeeds, we'll
588 // overwrite |*result| once more at the end. 591 // overwrite |*result| once more at the end.
589 *result = SDR_ERROR; 592 *result = SDR_ERROR;
590 } 593 }
591 594
592 if (!sending_) { 595 if (!sending_) {
593 LOG(LS_WARNING) << debug_name_ << "->SendData(...): " 596 LOG(LS_WARNING) << debug_name_ << "->SendData(...): "
594 << "Not sending packet with ssrc=" << params.ssrc 597 << "Not sending packet with ssrc=" << params.ssrc
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 } 647 }
645 if (result) { 648 if (result) {
646 // Only way out now is success. 649 // Only way out now is success.
647 *result = SDR_SUCCESS; 650 *result = SDR_SUCCESS;
648 } 651 }
649 return true; 652 return true;
650 } 653 }
651 654
652 // Called by network interface when a packet has been received. 655 // Called by network interface when a packet has been received.
653 void SctpDataMediaChannel::OnPacketReceived( 656 void SctpDataMediaChannel::OnPacketReceived(
654 rtc::Buffer* packet, const rtc::PacketTime& packet_time) { 657 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
655 RTC_DCHECK(rtc::Thread::Current() == worker_thread_); 658 RTC_DCHECK(rtc::Thread::Current() == worker_thread_);
656 LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): " 659 LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): "
657 << " length=" << packet->size() << ", sending: " << sending_; 660 << " length=" << packet->size() << ", sending: " << sending_;
658 // Only give receiving packets to usrsctp after if connected. This enables two 661 // Only give receiving packets to usrsctp after if connected. This enables two
659 // peers to each make a connect call, but for them not to receive an INIT 662 // peers to each make a connect call, but for them not to receive an INIT
660 // packet before they have called connect; least the last receiver of the INIT 663 // packet before they have called connect; least the last receiver of the INIT
661 // packet will have called connect, and a connection will be established. 664 // packet will have called connect, and a connection will be established.
662 if (sending_) { 665 if (sending_) {
663 // Pass received packet to SCTP stack. Once processed by usrsctp, the data 666 // Pass received packet to SCTP stack. Once processed by usrsctp, the data
664 // will be will be given to the global OnSctpInboundData, and then, 667 // will be will be given to the global OnSctpInboundData, and then,
665 // marshalled by a Post and handled with OnMessage. 668 // marshalled by a Post and handled with OnMessage.
666 VerboseLogPacket(packet->data(), packet->size(), SCTP_DUMP_INBOUND); 669 VerboseLogPacket(packet->cdata(), packet->size(), SCTP_DUMP_INBOUND);
667 usrsctp_conninput(this, packet->data(), packet->size(), 0); 670 usrsctp_conninput(this, packet->cdata(), packet->size(), 0);
668 } else { 671 } else {
669 // TODO(ldixon): Consider caching the packet for very slightly better 672 // TODO(ldixon): Consider caching the packet for very slightly better
670 // reliability. 673 // reliability.
671 } 674 }
672 } 675 }
673 676
674 void SctpDataMediaChannel::OnInboundPacketFromSctpToChannel( 677 void SctpDataMediaChannel::OnInboundPacketFromSctpToChannel(
675 SctpInboundPacket* packet) { 678 SctpInboundPacket* packet) {
676 LOG(LS_VERBOSE) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 679 LOG(LS_VERBOSE) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): "
677 << "Received SCTP data:" 680 << "Received SCTP data:"
678 << " ssrc=" << packet->params.ssrc 681 << " ssrc=" << packet->params.ssrc
679 << " notification: " << (packet->flags & MSG_NOTIFICATION) 682 << " notification: " << (packet->flags & MSG_NOTIFICATION)
680 << " length=" << packet->buffer.size(); 683 << " length=" << packet->buffer.size();
681 // Sending a packet with data == NULL (no data) is SCTPs "close the 684 // Sending a packet with data == NULL (no data) is SCTPs "close the
682 // connection" message. This sets sock_ = NULL; 685 // connection" message. This sets sock_ = NULL;
683 if (!packet->buffer.size() || !packet->buffer.data()) { 686 if (!packet->buffer.size() || !packet->buffer.data()) {
684 LOG(LS_INFO) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): " 687 LOG(LS_INFO) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): "
685 "No data, closing."; 688 "No data, closing.";
686 return; 689 return;
687 } 690 }
688 if (packet->flags & MSG_NOTIFICATION) { 691 if (packet->flags & MSG_NOTIFICATION) {
689 OnNotificationFromSctp(&packet->buffer); 692 OnNotificationFromSctp(packet->buffer);
690 } else { 693 } else {
691 OnDataFromSctpToChannel(packet->params, &packet->buffer); 694 OnDataFromSctpToChannel(packet->params, packet->buffer);
692 } 695 }
693 } 696 }
694 697
695 void SctpDataMediaChannel::OnDataFromSctpToChannel( 698 void SctpDataMediaChannel::OnDataFromSctpToChannel(
696 const ReceiveDataParams& params, rtc::Buffer* buffer) { 699 const ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer) {
697 if (receiving_) { 700 if (receiving_) {
698 LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): " 701 LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): "
699 << "Posting with length: " << buffer->size() 702 << "Posting with length: " << buffer.size()
700 << " on stream " << params.ssrc; 703 << " on stream " << params.ssrc;
701 // Reports all received messages to upper layers, no matter whether the sid 704 // Reports all received messages to upper layers, no matter whether the sid
702 // is known. 705 // is known.
703 SignalDataReceived(params, buffer->data<char>(), buffer->size()); 706 SignalDataReceived(params, buffer.data<char>(), buffer.size());
704 } else { 707 } else {
705 LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): " 708 LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): "
706 << "Not receiving packet with sid=" << params.ssrc 709 << "Not receiving packet with sid=" << params.ssrc
707 << " len=" << buffer->size() << " before SetReceive(true)."; 710 << " len=" << buffer.size() << " before SetReceive(true).";
708 } 711 }
709 } 712 }
710 713
711 bool SctpDataMediaChannel::AddStream(const StreamParams& stream) { 714 bool SctpDataMediaChannel::AddStream(const StreamParams& stream) {
712 if (!stream.has_ssrcs()) { 715 if (!stream.has_ssrcs()) {
713 return false; 716 return false;
714 } 717 }
715 718
716 const uint32_t ssrc = stream.first_ssrc(); 719 const uint32_t ssrc = stream.first_ssrc();
717 if (ssrc >= cricket::kMaxSctpSid) { 720 if (ssrc >= cricket::kMaxSctpSid) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 // SendQueuedStreamResets(). 763 // SendQueuedStreamResets().
761 queued_reset_streams_.insert(ssrc); 764 queued_reset_streams_.insert(ssrc);
762 765
763 // Signal our stream-reset logic that it should try to send now, if it can. 766 // Signal our stream-reset logic that it should try to send now, if it can.
764 SendQueuedStreamResets(); 767 SendQueuedStreamResets();
765 768
766 // The stream will actually get removed when we get the acknowledgment. 769 // The stream will actually get removed when we get the acknowledgment.
767 return true; 770 return true;
768 } 771 }
769 772
770 void SctpDataMediaChannel::OnNotificationFromSctp(rtc::Buffer* buffer) { 773 void SctpDataMediaChannel::OnNotificationFromSctp(
774 const rtc::CopyOnWriteBuffer& buffer) {
771 const sctp_notification& notification = 775 const sctp_notification& notification =
772 reinterpret_cast<const sctp_notification&>(*buffer->data()); 776 reinterpret_cast<const sctp_notification&>(*buffer.data());
773 ASSERT(notification.sn_header.sn_length == buffer->size()); 777 ASSERT(notification.sn_header.sn_length == buffer.size());
774 778
775 // TODO(ldixon): handle notifications appropriately. 779 // TODO(ldixon): handle notifications appropriately.
776 switch (notification.sn_header.sn_type) { 780 switch (notification.sn_header.sn_type) {
777 case SCTP_ASSOC_CHANGE: 781 case SCTP_ASSOC_CHANGE:
778 LOG(LS_VERBOSE) << "SCTP_ASSOC_CHANGE"; 782 LOG(LS_VERBOSE) << "SCTP_ASSOC_CHANGE";
779 OnNotificationAssocChange(notification.sn_assoc_change); 783 OnNotificationAssocChange(notification.sn_assoc_change);
780 break; 784 break;
781 case SCTP_REMOTE_ERROR: 785 case SCTP_REMOTE_ERROR:
782 LOG(LS_INFO) << "SCTP_REMOTE_ERROR"; 786 LOG(LS_INFO) << "SCTP_REMOTE_ERROR";
783 break; 787 break;
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 &remote_port_); 960 &remote_port_);
957 } 961 }
958 962
959 bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) { 963 bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
960 return GetCodecIntParameter( 964 return GetCodecIntParameter(
961 codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort, 965 codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
962 &local_port_); 966 &local_port_);
963 } 967 }
964 968
965 void SctpDataMediaChannel::OnPacketFromSctpToNetwork( 969 void SctpDataMediaChannel::OnPacketFromSctpToNetwork(
966 rtc::Buffer* buffer) { 970 rtc::CopyOnWriteBuffer* buffer) {
967 // usrsctp seems to interpret the MTU we give it strangely -- it seems to 971 // usrsctp seems to interpret the MTU we give it strangely -- it seems to
968 // give us back packets bigger than that MTU, if only by a fixed amount. 972 // give us back packets bigger than that MTU, if only by a fixed amount.
969 // This is that amount that we've observed. 973 // This is that amount that we've observed.
970 const int kSctpOverhead = 76; 974 const int kSctpOverhead = 76;
971 if (buffer->size() > (kSctpOverhead + kSctpMtu)) { 975 if (buffer->size() > (kSctpOverhead + kSctpMtu)) {
972 LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): " 976 LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): "
973 << "SCTP seems to have made a packet that is bigger " 977 << "SCTP seems to have made a packet that is bigger "
974 << "than its official MTU: " << buffer->size() 978 << "than its official MTU: " << buffer->size()
975 << " vs max of " << kSctpMtu 979 << " vs max of " << kSctpMtu
976 << " even after adding " << kSctpOverhead 980 << " even after adding " << kSctpOverhead
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 } 1033 }
1030 case MSG_SCTPOUTBOUNDPACKET: { 1034 case MSG_SCTPOUTBOUNDPACKET: {
1031 std::unique_ptr<OutboundPacketMessage> pdata( 1035 std::unique_ptr<OutboundPacketMessage> pdata(
1032 static_cast<OutboundPacketMessage*>(msg->pdata)); 1036 static_cast<OutboundPacketMessage*>(msg->pdata));
1033 OnPacketFromSctpToNetwork(pdata->data().get()); 1037 OnPacketFromSctpToNetwork(pdata->data().get());
1034 break; 1038 break;
1035 } 1039 }
1036 } 1040 }
1037 } 1041 }
1038 } // namespace cricket 1042 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/media/sctp/sctpdataengine.h ('k') | webrtc/media/sctp/sctpdataengine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698