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

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 6 years 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 // 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;
120
Sergey Ulanov 2014/12/23 01:11:02 nit: Don't need this empty line.
guoweis_left_chromium 2014/12/23 18:53:16 Done.
107 void OnError() override; 121 void OnError() override;
108 void OnDataReceived(const net::IPEndPoint& address, 122 void OnDataReceived(const net::IPEndPoint& address,
109 const std::vector<char>& data, 123 const std::vector<char>& data,
110 const base::TimeTicks& timestamp) override; 124 const base::TimeTicks& timestamp) override;
111 125
112 private: 126 private:
113 enum InternalState { 127 enum InternalState {
114 IS_UNINITIALIZED, 128 IS_UNINITIALIZED,
115 IS_OPENING, 129 IS_OPENING,
116 IS_OPEN, 130 IS_OPEN,
117 IS_CLOSED, 131 IS_CLOSED,
118 IS_ERROR, 132 IS_ERROR,
119 }; 133 };
120 134
121 // Increment the counter for consecutive bytes discarded as socket is running 135 // Increment the counter for consecutive bytes discarded as socket is running
122 // out of buffer. 136 // out of buffer.
123 void IncrementDiscardCounters(size_t bytes_discarded); 137 void IncrementDiscardCounters(size_t bytes_discarded);
124 138
125 // Update trace of send throttling internal state. This should be called 139 // Update trace of send throttling internal state. This should be called
126 // immediately after any changes to |send_bytes_available_| and/or 140 // immediately after any changes to |send_bytes_available_| and/or
127 // |in_flight_packet_sizes_|. 141 // |in_flight_packet_records_|.
128 void TraceSendThrottlingState() const; 142 void TraceSendThrottlingState() const;
129 143
130 void InitAcceptedTcp(P2PSocketClient* client, 144 void InitAcceptedTcp(P2PSocketClient* client,
131 const rtc::SocketAddress& local_address, 145 const rtc::SocketAddress& local_address,
132 const rtc::SocketAddress& remote_address); 146 const rtc::SocketAddress& remote_address);
133 147
134 int DoSetOption(P2PSocketOption option, int value); 148 int DoSetOption(P2PSocketOption option, int value);
135 149
136 // Allow a finch experiment to control the initial value of 150 // Allow a finch experiment to control the initial value of
137 // send_bytes_available_; 151 // send_bytes_available_;
(...skipping 18 matching lines...) Expand all
156 // Current state of the object. 170 // Current state of the object.
157 InternalState state_; 171 InternalState state_;
158 172
159 // Track the number of bytes allowed to be sent non-blocking. This is used to 173 // 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 174 // throttle the sending of packets to the browser process. For each packet
161 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs 175 // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs
162 // from the browser process) are made, the value is increased back. This 176 // from the browser process) are made, the value is increased back. This
163 // allows short bursts of high-rate sending without dropping packets, but 177 // allows short bursts of high-rate sending without dropping packets, but
164 // quickly restricts the client to a sustainable steady-state rate. 178 // quickly restricts the client to a sustainable steady-state rate.
165 size_t send_bytes_available_; 179 size_t send_bytes_available_;
166 std::deque<size_t> in_flight_packet_sizes_; 180
181 // Used to detect when browser doesn't send SendComplete message for some
182 // packets. In normal case, the first packet should be the one that we're
183 // going to receive the next completion signal.
184 InFlightPacketList in_flight_packet_records_;
167 185
168 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the 186 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
169 // caller expects SignalWritable notification. 187 // caller expects SignalWritable notification.
170 bool writable_signal_expected_; 188 bool writable_signal_expected_;
171 189
172 // Current error code. Valid when state_ == IS_ERROR. 190 // Current error code. Valid when state_ == IS_ERROR.
173 int error_; 191 int error_;
174 int options_[P2P_SOCKET_OPT_MAX]; 192 int options_[P2P_SOCKET_OPT_MAX];
175 193
176 // Track the maximum and current consecutive bytes discarded due to not enough 194 // 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) { 256 if (total_packets_ > 0) {
239 UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded", 257 UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded",
240 (packets_discarded_ * 100) / total_packets_); 258 (packets_discarded_ * 100) / total_packets_);
241 } 259 }
242 } 260 }
243 261
244 void IpcPacketSocket::TraceSendThrottlingState() const { 262 void IpcPacketSocket::TraceSendThrottlingState() const {
245 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(), 263 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(),
246 send_bytes_available_); 264 send_bytes_available_);
247 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(), 265 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(),
248 in_flight_packet_sizes_.size()); 266 in_flight_packet_records_.size());
249 } 267 }
250 268
251 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) { 269 void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) {
252 current_discard_bytes_sequence_ += bytes_discarded; 270 current_discard_bytes_sequence_ += bytes_discarded;
253 packets_discarded_++; 271 packets_discarded_++;
254 272
255 if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) { 273 if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) {
256 max_discard_bytes_sequence_ = current_discard_bytes_sequence_; 274 max_discard_bytes_sequence_ = current_discard_bytes_sequence_;
257 } 275 }
258 } 276 }
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 total_packets_++; 396 total_packets_++;
379 397
380 if (data_size > send_bytes_available_) { 398 if (data_size > send_bytes_available_) {
381 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock", 399 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
382 TRACE_EVENT_SCOPE_THREAD, 400 TRACE_EVENT_SCOPE_THREAD,
383 "id", 401 "id",
384 client_->GetSocketID()); 402 client_->GetSocketID());
385 if (!writable_signal_expected_) { 403 if (!writable_signal_expected_) {
386 WebRtcLogMessage(base::StringPrintf( 404 WebRtcLogMessage(base::StringPrintf(
387 "IpcPacketSocket: sending is blocked. %d packets_in_flight.", 405 "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
388 static_cast<int>(in_flight_packet_sizes_.size()))); 406 static_cast<int>(in_flight_packet_records_.size())));
389 407
390 writable_signal_expected_ = true; 408 writable_signal_expected_ = true;
391 } 409 }
392 410
393 error_ = EWOULDBLOCK; 411 error_ = EWOULDBLOCK;
394 IncrementDiscardCounters(data_size); 412 IncrementDiscardCounters(data_size);
395 return -1; 413 return -1;
396 } else { 414 } else {
397 current_discard_bytes_sequence_ = 0; 415 current_discard_bytes_sequence_ = 0;
398 } 416 }
399 417
400 net::IPEndPoint address_chrome; 418 net::IPEndPoint address_chrome;
401 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { 419 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
402 DVLOG(1) << "Failed to convert remote address to IPEndPoint: address = " 420 DVLOG(1) << "Failed to convert remote address to IPEndPoint: address = "
403 << address.ToSensitiveString() << ", remote_address_ = " 421 << address.ToSensitiveString() << ", remote_address_ = "
404 << remote_address_.ToSensitiveString(); 422 << remote_address_.ToSensitiveString();
405 NOTREACHED(); 423 NOTREACHED();
406 error_ = EINVAL; 424 error_ = EINVAL;
407 return -1; 425 return -1;
408 } 426 }
409 427
410 send_bytes_available_ -= data_size; 428 send_bytes_available_ -= data_size;
411 in_flight_packet_sizes_.push_back(data_size);
412 TraceSendThrottlingState();
413 429
414 const char* data_char = reinterpret_cast<const char*>(data); 430 const char* data_char = reinterpret_cast<const char*>(data);
415 std::vector<char> data_vector(data_char, data_char + data_size); 431 std::vector<char> data_vector(data_char, data_char + data_size);
416 client_->SendWithDscp(address_chrome, data_vector, options); 432 uint64_t packet_id =
433 client_->SendWithDscp(address_chrome, data_vector, options);
434
435 // Ensure packet_id is not 0. It can't be the case according to
436 // P2PSocketClientImpl::SendWithDscp().
437 DCHECK_NE(packet_id, 0uL);
438
439 in_flight_packet_records_.push_back(
440 InFlightPacketRecord(packet_id, data_size));
441 TraceSendThrottlingState();
417 442
418 // Fake successful send. The caller ignores result anyway. 443 // Fake successful send. The caller ignores result anyway.
419 return data_size; 444 return data_size;
420 } 445 }
421 446
422 int IpcPacketSocket::Close() { 447 int IpcPacketSocket::Close() {
423 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 448 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
424 449
425 client_->Close(); 450 client_->Close();
426 state_ = IS_CLOSED; 451 state_ = IS_CLOSED;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 577
553 rtc::SocketAddress remote_address; 578 rtc::SocketAddress remote_address;
554 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) { 579 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) {
555 // Always expect correct IPv4 address to be allocated. 580 // Always expect correct IPv4 address to be allocated.
556 NOTREACHED(); 581 NOTREACHED();
557 } 582 }
558 socket->InitAcceptedTcp(client, local_address_, remote_address); 583 socket->InitAcceptedTcp(client, local_address_, remote_address);
559 SignalNewConnection(this, socket.release()); 584 SignalNewConnection(this, socket.release());
560 } 585 }
561 586
562 void IpcPacketSocket::OnSendComplete() { 587 void IpcPacketSocket::OnSendComplete(const P2PSendPacketMetrics& send_metrics) {
563 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 588 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
564 589
565 CHECK(!in_flight_packet_sizes_.empty()); 590 CHECK(!in_flight_packet_records_.empty());
566 send_bytes_available_ += in_flight_packet_sizes_.front(); 591
592 InFlightPacketList::iterator it = in_flight_packet_records_.begin();
Sergey Ulanov 2014/12/23 01:11:02 nit: this can be: const InFlightPacketRecord& pack
guoweis_left_chromium 2014/12/23 18:53:16 Done.
593
594 // Tracking is not turned on for TCP so it's always 0. For UDP, this will
595 // cause a crash when the packet ids don't match.
596 CHECK(send_metrics.packet_id == 0 || it->packet_id == send_metrics.packet_id);
597
598 send_bytes_available_ += it->packet_size;
567 599
568 DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes); 600 DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes);
569 601
570 in_flight_packet_sizes_.pop_front(); 602 in_flight_packet_records_.erase(it);
Sergey Ulanov 2014/12/23 01:11:02 pop_front()?
guoweis_left_chromium 2014/12/23 18:53:16 Done.
571 TraceSendThrottlingState(); 603 TraceSendThrottlingState();
572 604
573 if (writable_signal_expected_ && send_bytes_available_ > 0) { 605 if (writable_signal_expected_ && send_bytes_available_ > 0) {
574 WebRtcLogMessage(base::StringPrintf( 606 WebRtcLogMessage(base::StringPrintf(
575 "IpcPacketSocket: sending is unblocked. %d packets in flight.", 607 "IpcPacketSocket: sending is unblocked. %d packets in flight.",
576 static_cast<int>(in_flight_packet_sizes_.size()))); 608 static_cast<int>(in_flight_packet_records_.size())));
577 609
578 SignalReadyToSend(this); 610 SignalReadyToSend(this);
579 writable_signal_expected_ = false; 611 writable_signal_expected_ = false;
580 } 612 }
581 } 613 }
582 614
583 void IpcPacketSocket::OnError() { 615 void IpcPacketSocket::OnError() {
584 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 616 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
585 bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED); 617 bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED);
586 state_ = IS_ERROR; 618 state_ = IS_ERROR;
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 } 772 }
741 773
742 rtc::AsyncResolverInterface* 774 rtc::AsyncResolverInterface*
743 IpcPacketSocketFactory::CreateAsyncResolver() { 775 IpcPacketSocketFactory::CreateAsyncResolver() {
744 scoped_ptr<AsyncAddressResolverImpl> resolver( 776 scoped_ptr<AsyncAddressResolverImpl> resolver(
745 new AsyncAddressResolverImpl(socket_dispatcher_)); 777 new AsyncAddressResolverImpl(socket_dispatcher_));
746 return resolver.release(); 778 return resolver.release();
747 } 779 }
748 780
749 } // namespace content 781 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698