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

Side by Side Diff: content/renderer/p2p/ipc_socket_factory.cc

Issue 759923003: Detect situation when there is no missing send completion signal in P2PSocket implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 12 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 | « content/common/p2p_socket_type.h ('k') | content/renderer/p2p/socket_client.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/p2p/ipc_socket_factory.h" 5 #include "content/renderer/p2p/ipc_socket_factory.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <list>
9 9
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/debug/trace_event.h" 11 #include "base/debug/trace_event.h"
12 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h" 13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/metrics/field_trial.h" 14 #include "base/metrics/field_trial.h"
15 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
18 #include "base/threading/non_thread_safe.h" 18 #include "base/threading/non_thread_safe.h"
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 69
70 // IpcPacketSocket implements rtc::AsyncPacketSocket interface 70 // IpcPacketSocket implements rtc::AsyncPacketSocket interface
71 // using P2PSocketClient that works over IPC-channel. It must be used 71 // using P2PSocketClient that works over IPC-channel. It must be used
72 // on the thread it was created. 72 // on the thread it was created.
73 class IpcPacketSocket : public rtc::AsyncPacketSocket, 73 class IpcPacketSocket : public rtc::AsyncPacketSocket,
74 public P2PSocketClientDelegate { 74 public P2PSocketClientDelegate {
75 public: 75 public:
76 IpcPacketSocket(); 76 IpcPacketSocket();
77 ~IpcPacketSocket() override; 77 ~IpcPacketSocket() override;
78 78
79 // Struct to track information when a packet is received by this socket for
80 // send. The information tracked here will be used to match with the
81 // P2PSendPacketMetrics from the underneath system socket.
82 struct InFlightPacketRecord {
83 InFlightPacketRecord(uint64_t packet_id, size_t packet_size)
84 : packet_id(packet_id), packet_size(packet_size) {}
85
86 uint64_t packet_id;
87 size_t packet_size;
88 };
89
90 typedef std::list<InFlightPacketRecord> InFlightPacketList;
91
79 // Always takes ownership of client even if initialization fails. 92 // Always takes ownership of client even if initialization fails.
80 bool Init(P2PSocketType type, P2PSocketClientImpl* client, 93 bool Init(P2PSocketType type, P2PSocketClientImpl* client,
81 const rtc::SocketAddress& local_address, 94 const rtc::SocketAddress& local_address,
82 const rtc::SocketAddress& remote_address); 95 const rtc::SocketAddress& remote_address);
83 96
84 // rtc::AsyncPacketSocket interface. 97 // rtc::AsyncPacketSocket interface.
85 rtc::SocketAddress GetLocalAddress() const override; 98 rtc::SocketAddress GetLocalAddress() const override;
86 rtc::SocketAddress GetRemoteAddress() const override; 99 rtc::SocketAddress GetRemoteAddress() const override;
87 int Send(const void* pv, 100 int Send(const void* pv,
88 size_t cb, 101 size_t cb,
89 const rtc::PacketOptions& options) override; 102 const rtc::PacketOptions& options) override;
90 int SendTo(const void* pv, 103 int SendTo(const void* pv,
91 size_t cb, 104 size_t cb,
92 const rtc::SocketAddress& addr, 105 const rtc::SocketAddress& addr,
93 const rtc::PacketOptions& options) override; 106 const rtc::PacketOptions& options) override;
94 int Close() override; 107 int Close() override;
95 State GetState() const override; 108 State GetState() const override;
96 int GetOption(rtc::Socket::Option option, int* value) override; 109 int GetOption(rtc::Socket::Option option, int* value) override;
97 int SetOption(rtc::Socket::Option option, int value) override; 110 int SetOption(rtc::Socket::Option option, int value) override;
98 int GetError() const override; 111 int GetError() const override;
99 void SetError(int error) override; 112 void SetError(int error) override;
100 113
101 // P2PSocketClientDelegate implementation. 114 // P2PSocketClientDelegate implementation.
102 void OnOpen(const net::IPEndPoint& local_address, 115 void OnOpen(const net::IPEndPoint& local_address,
103 const net::IPEndPoint& remote_address) override; 116 const net::IPEndPoint& remote_address) override;
104 void OnIncomingTcpConnection(const net::IPEndPoint& address, 117 void OnIncomingTcpConnection(const net::IPEndPoint& address,
105 P2PSocketClient* client) override; 118 P2PSocketClient* client) override;
106 void OnSendComplete() override; 119 void OnSendComplete(const P2PSendPacketMetrics& send_metrics) override;
107 void OnError() override; 120 void OnError() override;
108 void OnDataReceived(const net::IPEndPoint& address, 121 void OnDataReceived(const net::IPEndPoint& address,
109 const std::vector<char>& data, 122 const std::vector<char>& data,
110 const base::TimeTicks& timestamp) override; 123 const base::TimeTicks& timestamp) override;
111 124
112 private: 125 private:
113 enum InternalState { 126 enum InternalState {
114 IS_UNINITIALIZED, 127 IS_UNINITIALIZED,
115 IS_OPENING, 128 IS_OPENING,
116 IS_OPEN, 129 IS_OPEN,
117 IS_CLOSED, 130 IS_CLOSED,
118 IS_ERROR, 131 IS_ERROR,
119 }; 132 };
120 133
121 // Increment the counter for consecutive bytes discarded as socket is running 134 // Increment the counter for consecutive bytes discarded as socket is running
122 // out of buffer. 135 // out of buffer.
123 void IncrementDiscardCounters(size_t bytes_discarded); 136 void IncrementDiscardCounters(size_t bytes_discarded);
124 137
125 // Update trace of send throttling internal state. This should be called 138 // Update trace of send throttling internal state. This should be called
126 // immediately after any changes to |send_bytes_available_| and/or 139 // immediately after any changes to |send_bytes_available_| and/or
127 // |in_flight_packet_sizes_|. 140 // |in_flight_packet_records_|.
128 void TraceSendThrottlingState() const; 141 void TraceSendThrottlingState() const;
129 142
130 void InitAcceptedTcp(P2PSocketClient* client, 143 void InitAcceptedTcp(P2PSocketClient* client,
131 const rtc::SocketAddress& local_address, 144 const rtc::SocketAddress& local_address,
132 const rtc::SocketAddress& remote_address); 145 const rtc::SocketAddress& remote_address);
133 146
134 int DoSetOption(P2PSocketOption option, int value); 147 int DoSetOption(P2PSocketOption option, int value);
135 148
136 // Allow a finch experiment to control the initial value of 149 // Allow a finch experiment to control the initial value of
137 // send_bytes_available_; 150 // send_bytes_available_;
(...skipping 18 matching lines...) Expand all
156 // Current state of the object. 169 // Current state of the object.
157 InternalState state_; 170 InternalState state_;
158 171
159 // Track the number of bytes allowed to be sent non-blocking. This is used to 172 // Track the number of bytes allowed to be sent non-blocking. This is used to
160 // throttle the sending of packets to the browser process. For each packet 173 // throttle the sending of packets to the browser process. For each packet
161 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs 174 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs
162 // from the browser process) are made, the value is increased back. This 175 // from the browser process) are made, the value is increased back. This
163 // allows short bursts of high-rate sending without dropping packets, but 176 // allows short bursts of high-rate sending without dropping packets, but
164 // quickly restricts the client to a sustainable steady-state rate. 177 // quickly restricts the client to a sustainable steady-state rate.
165 size_t send_bytes_available_; 178 size_t send_bytes_available_;
166 std::deque<size_t> in_flight_packet_sizes_; 179
180 // Used to detect when browser doesn't send SendComplete message for some
181 // packets. In normal case, the first packet should be the one that we're
182 // going to receive the next completion signal.
183 InFlightPacketList in_flight_packet_records_;
167 184
168 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the 185 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
169 // caller expects SignalWritable notification. 186 // caller expects SignalWritable notification.
170 bool writable_signal_expected_; 187 bool writable_signal_expected_;
171 188
172 // Current error code. Valid when state_ == IS_ERROR. 189 // Current error code. Valid when state_ == IS_ERROR.
173 int error_; 190 int error_;
174 int options_[P2P_SOCKET_OPT_MAX]; 191 int options_[P2P_SOCKET_OPT_MAX];
175 192
176 // Track the maximum and current consecutive bytes discarded due to not enough 193 // Track the maximum and current consecutive bytes discarded due to not enough
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 if (total_packets_ > 0) { 255 if (total_packets_ > 0) {
239 UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded", 256 UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded",
240 (packets_discarded_ * 100) / total_packets_); 257 (packets_discarded_ * 100) / total_packets_);
241 } 258 }
242 } 259 }
243 260
244 void IpcPacketSocket::TraceSendThrottlingState() const { 261 void IpcPacketSocket::TraceSendThrottlingState() const {
245 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(), 262 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(),
246 send_bytes_available_); 263 send_bytes_available_);
247 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(), 264 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(),
248 in_flight_packet_sizes_.size()); 265 in_flight_packet_records_.size());
249 } 266 }
250 267
251 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) { 268 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) {
252 current_discard_bytes_sequence_ += bytes_discarded; 269 current_discard_bytes_sequence_ += bytes_discarded;
253 packets_discarded_++; 270 packets_discarded_++;
254 271
255 if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) { 272 if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) {
256 max_discard_bytes_sequence_ = current_discard_bytes_sequence_; 273 max_discard_bytes_sequence_ = current_discard_bytes_sequence_;
257 } 274 }
258 } 275 }
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 total_packets_++; 395 total_packets_++;
379 396
380 if (data_size > send_bytes_available_) { 397 if (data_size > send_bytes_available_) {
381 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock", 398 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
382 TRACE_EVENT_SCOPE_THREAD, 399 TRACE_EVENT_SCOPE_THREAD,
383 "id", 400 "id",
384 client_->GetSocketID()); 401 client_->GetSocketID());
385 if (!writable_signal_expected_) { 402 if (!writable_signal_expected_) {
386 WebRtcLogMessage(base::StringPrintf( 403 WebRtcLogMessage(base::StringPrintf(
387 "IpcPacketSocket: sending is blocked. %d packets_in_flight.", 404 "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
388 static_cast<int>(in_flight_packet_sizes_.size()))); 405 static_cast<int>(in_flight_packet_records_.size())));
389 406
390 writable_signal_expected_ = true; 407 writable_signal_expected_ = true;
391 } 408 }
392 409
393 error_ = EWOULDBLOCK; 410 error_ = EWOULDBLOCK;
394 IncrementDiscardCounters(data_size); 411 IncrementDiscardCounters(data_size);
395 return -1; 412 return -1;
396 } else { 413 } else {
397 current_discard_bytes_sequence_ = 0; 414 current_discard_bytes_sequence_ = 0;
398 } 415 }
399 416
400 net::IPEndPoint address_chrome; 417 net::IPEndPoint address_chrome;
401 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { 418 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
402 DVLOG(1) << "Failed to convert remote address to IPEndPoint: address = " 419 DVLOG(1) << "Failed to convert remote address to IPEndPoint: address = "
403 << address.ToSensitiveString() << ", remote_address_ = " 420 << address.ToSensitiveString() << ", remote_address_ = "
404 << remote_address_.ToSensitiveString(); 421 << remote_address_.ToSensitiveString();
405 NOTREACHED(); 422 NOTREACHED();
406 error_ = EINVAL; 423 error_ = EINVAL;
407 return -1; 424 return -1;
408 } 425 }
409 426
410 send_bytes_available_ -= data_size; 427 send_bytes_available_ -= data_size;
411 in_flight_packet_sizes_.push_back(data_size);
412 TraceSendThrottlingState();
413 428
414 const char* data_char = reinterpret_cast<const char*>(data); 429 const char* data_char = reinterpret_cast<const char*>(data);
415 std::vector<char> data_vector(data_char, data_char + data_size); 430 std::vector<char> data_vector(data_char, data_char + data_size);
416 client_->SendWithDscp(address_chrome, data_vector, options); 431 uint64_t packet_id = client_->Send(address_chrome, data_vector, options);
432
433 // Ensure packet_id is not 0. It can't be the case according to
434 // P2PSocketClientImpl::Send().
435 DCHECK_NE(packet_id, 0uL);
436
437 in_flight_packet_records_.push_back(
438 InFlightPacketRecord(packet_id, data_size));
439 TraceSendThrottlingState();
417 440
418 // Fake successful send. The caller ignores result anyway. 441 // Fake successful send. The caller ignores result anyway.
419 return data_size; 442 return data_size;
420 } 443 }
421 444
422 int IpcPacketSocket::Close() { 445 int IpcPacketSocket::Close() {
423 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 446 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
424 447
425 client_->Close(); 448 client_->Close();
426 state_ = IS_CLOSED; 449 state_ = IS_CLOSED;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 575
553 rtc::SocketAddress remote_address; 576 rtc::SocketAddress remote_address;
554 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) { 577 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) {
555 // Always expect correct IPv4 address to be allocated. 578 // Always expect correct IPv4 address to be allocated.
556 NOTREACHED(); 579 NOTREACHED();
557 } 580 }
558 socket->InitAcceptedTcp(client, local_address_, remote_address); 581 socket->InitAcceptedTcp(client, local_address_, remote_address);
559 SignalNewConnection(this, socket.release()); 582 SignalNewConnection(this, socket.release());
560 } 583 }
561 584
562 void IpcPacketSocket::OnSendComplete() { 585 void IpcPacketSocket::OnSendComplete(const P2PSendPacketMetrics& send_metrics) {
563 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 586 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
564 587
565 CHECK(!in_flight_packet_sizes_.empty()); 588 CHECK(!in_flight_packet_records_.empty());
566 send_bytes_available_ += in_flight_packet_sizes_.front(); 589
590 const InFlightPacketRecord& record = in_flight_packet_records_.front();
591
592 // Tracking is not turned on for TCP so it's always 0. For UDP, this will
593 // cause a crash when the packet ids don't match.
594 CHECK(send_metrics.packet_id == 0 ||
595 record.packet_id == send_metrics.packet_id);
596
597 send_bytes_available_ += record.packet_size;
567 598
568 DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes); 599 DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes);
569 600
570 in_flight_packet_sizes_.pop_front(); 601 in_flight_packet_records_.pop_front();
571 TraceSendThrottlingState(); 602 TraceSendThrottlingState();
572 603
573 if (writable_signal_expected_ && send_bytes_available_ > 0) { 604 if (writable_signal_expected_ && send_bytes_available_ > 0) {
574 WebRtcLogMessage(base::StringPrintf( 605 WebRtcLogMessage(base::StringPrintf(
575 "IpcPacketSocket: sending is unblocked. %d packets in flight.", 606 "IpcPacketSocket: sending is unblocked. %d packets in flight.",
576 static_cast<int>(in_flight_packet_sizes_.size()))); 607 static_cast<int>(in_flight_packet_records_.size())));
577 608
578 SignalReadyToSend(this); 609 SignalReadyToSend(this);
579 writable_signal_expected_ = false; 610 writable_signal_expected_ = false;
580 } 611 }
581 } 612 }
582 613
583 void IpcPacketSocket::OnError() { 614 void IpcPacketSocket::OnError() {
584 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 615 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
585 bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED); 616 bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED);
586 state_ = IS_ERROR; 617 state_ = IS_ERROR;
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 } 771 }
741 772
742 rtc::AsyncResolverInterface* 773 rtc::AsyncResolverInterface*
743 IpcPacketSocketFactory::CreateAsyncResolver() { 774 IpcPacketSocketFactory::CreateAsyncResolver() {
744 scoped_ptr<AsyncAddressResolverImpl> resolver( 775 scoped_ptr<AsyncAddressResolverImpl> resolver(
745 new AsyncAddressResolverImpl(socket_dispatcher_)); 776 new AsyncAddressResolverImpl(socket_dispatcher_));
746 return resolver.release(); 777 return resolver.release();
747 } 778 }
748 779
749 } // namespace content 780 } // namespace content
OLDNEW
« no previous file with comments | « content/common/p2p_socket_type.h ('k') | content/renderer/p2p/socket_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698