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

Side by Side Diff: chrome/browser/media/webrtc_rtp_dump_handler.cc

Issue 264793017: Implements RTP header dumping. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 7 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media/webrtc_rtp_dump_handler.h"
6
7 #include "base/file_util.h"
8 #include "base/logging.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/time/time.h"
11 #include "chrome/browser/media/webrtc_rtp_dump_writer.h"
12 #include "content/public/browser/browser_thread.h"
13
14 using content::BrowserThread;
15
16 namespace {
17
18 // |path| must be a copy of FilePath, not a reference.
19 void DeleteFileHelper(base::FilePath path) {
20 base::DeleteFile(path, false);
21 }
22
23 static const size_t kMaxOngoingRtpDumpsAllowed = 5;
24
25 // The browser process wide total number of ongoing (i.e. started and not
26 // released) RTP dumps. Incoming and outgoing in one WebRtcDumpHandler are
27 // counted as one dump.
28 // Must be accessed on the browser IO thread.
29 static size_t g_ongoing_rtp_dumps = 0;
30
31 } // namespace
32
33 WebRtcRtpDumpHandler::WebRtcRtpDumpHandler(const base::FilePath& dump_dir)
34 : dump_dir_(dump_dir),
35 incoming_state_(STATE_NONE),
36 outgoing_state_(STATE_NONE) {
37 }
38
39 WebRtcRtpDumpHandler::~WebRtcRtpDumpHandler() {
40 if (!incoming_dump_path_.empty()) {
41 BrowserThread::PostTask(BrowserThread::FILE,
42 FROM_HERE,
43 base::Bind(&DeleteFileHelper, incoming_dump_path_));
44 }
45
46 if (!outgoing_dump_path_.empty()) {
47 BrowserThread::PostTask(BrowserThread::FILE,
48 FROM_HERE,
49 base::Bind(&DeleteFileHelper, outgoing_dump_path_));
50 }
51
52 if (dump_writer_)
53 g_ongoing_rtp_dumps--;
54 }
55
56 bool WebRtcRtpDumpHandler::StartDump(const PacketType& type) {
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
58
59 bool succeeded = false;
60
61 if (type.incoming && incoming_state_ == STATE_NONE &&
62 outgoing_state_ <= STATE_STARTED) {
63 incoming_state_ = STATE_STARTED;
64 succeeded = true;
65 }
66 if (type.outgoing && outgoing_state_ == STATE_NONE &&
67 incoming_state_ <= STATE_STARTED) {
68 outgoing_state_ = STATE_STARTED;
69 succeeded = true;
70 }
71
72 if (!dump_writer_ && g_ongoing_rtp_dumps >= kMaxOngoingRtpDumpsAllowed) {
73 DVLOG(2) << "Max RTP dump limit reached.";
74 return false;
75 }
76
77 DVLOG(2) << "Start RTP dumping: incoming = " << type.incoming
78 << ", outgoing = " << type.outgoing;
79
80 if (succeeded && !dump_writer_) {
81 g_ongoing_rtp_dumps++;
82
83 static const char kRecvDumpFilePrefix[] = "rtpdump_recv_";
84 static const char kSendDumpFilePrefix[] = "rtpdump_send_";
85 static const char kDumpFileExtension[] = ".gz";
86 static const size_t kMaxDumpSize = 5 * 1024 * 1024; // 5MB
87
88 std::string dump_id = base::DoubleToString(base::Time::Now().ToDoubleT());
89 incoming_dump_path_ =
90 dump_dir_.AppendASCII(std::string(kRecvDumpFilePrefix) + dump_id)
91 .AddExtension(FILE_PATH_LITERAL(kDumpFileExtension));
92
93 outgoing_dump_path_ =
94 dump_dir_.AppendASCII(std::string(kSendDumpFilePrefix) + dump_id)
95 .AddExtension(FILE_PATH_LITERAL(kDumpFileExtension));
96
97 // WebRtcRtpDumpWriter does not support changing the dump path after it's
98 // created. So we assign both incoming and outgoing dump path even if only
99 // one type of dumping has been started.
100 dump_writer_.reset(new WebRtcRtpDumpWriter(
101 incoming_dump_path_,
102 outgoing_dump_path_,
103 kMaxDumpSize,
104 base::Bind(&WebRtcRtpDumpHandler::OnMaxDumpSizeReached,
105 base::Unretained(this))));
106 }
107 return succeeded;
108 }
109
110 bool WebRtcRtpDumpHandler::StopDump(const PacketType& type) {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
112
113 bool succeeded = false;
114 if (type.incoming && incoming_state_ == STATE_STARTED) {
115 incoming_state_ = STATE_STOPPED;
116 succeeded = true;
117 }
118 if (type.outgoing && outgoing_state_ == STATE_STARTED) {
119 outgoing_state_ = STATE_STOPPED;
120 succeeded = true;
121 }
122
123 DVLOG(2) << "Stop RTP dumping: incoming = " << type.incoming
124 << ", outgoing = " << type.outgoing;
125 return succeeded;
126 }
127
128 bool WebRtcRtpDumpHandler::ReleaseDump(const ReleaseDumpCallback& callback) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
130
131 // All types of dumps must have been stopped or not started.
132 if (incoming_state_ == STATE_STARTED || incoming_state_ == STATE_RELEASING ||
133 outgoing_state_ == STATE_STARTED || outgoing_state_ == STATE_RELEASING ||
134 (incoming_state_ == STATE_NONE && outgoing_state_ == STATE_NONE) ||
135 !dump_writer_)
136 return false;
137
138 if (incoming_state_ == STATE_STOPPED)
139 incoming_state_ = STATE_RELEASING;
140
141 if (outgoing_state_ == STATE_STOPPED)
142 outgoing_state_ = STATE_RELEASING;
143
144 dump_writer_->EndDump(base::Bind(
145 &WebRtcRtpDumpHandler::OnDumpEnded, base::Unretained(this), callback));
146
147 DVLOG(2) << "Releasing RTP dump.";
148
149 return true;
150 }
151
152 void WebRtcRtpDumpHandler::OnRtpPacket(const uint8* packet_header,
153 size_t header_length,
154 size_t packet_length,
155 bool incoming) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
157
158 if ((incoming && incoming_state_ != STATE_STARTED) ||
159 (!incoming && outgoing_state_ != STATE_STARTED))
160 return;
161
162 dump_writer_->WriteRtpPacket(
163 packet_header, header_length, packet_length, incoming);
164 }
165
166 void WebRtcRtpDumpHandler::SetDumpWriterForTesting(
167 scoped_ptr<WebRtcRtpDumpWriter> writer) {
168 DCHECK(!dump_writer_.get());
169 dump_writer_ = writer.Pass();
170 g_ongoing_rtp_dumps++;
171 }
172
173 void WebRtcRtpDumpHandler::OnMaxDumpSizeReached() {
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
175
176 PacketType type = {true, true};
177 StopDump(type);
178 }
179
180 void WebRtcRtpDumpHandler::OnDumpEnded(const ReleaseDumpCallback& callback,
181 bool succeeded) {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
183
184 dump_writer_.reset();
185 g_ongoing_rtp_dumps--;
186
187 ReleasedDumps dumps;
188 if (succeeded) {
189 dumps.incoming_dump_path = incoming_dump_path_;
190 dumps.outgoing_dump_path = outgoing_dump_path_;
191 callback.Run(dumps);
192
193 DVLOG(2) << "RTP dump released: " << incoming_dump_path_.value() << ", "
194 << outgoing_dump_path_.value();
195 } else {
196 BrowserThread::PostTask(BrowserThread::FILE,
197 FROM_HERE,
198 base::Bind(&DeleteFileHelper, incoming_dump_path_));
199
200 BrowserThread::PostTask(BrowserThread::FILE,
201 FROM_HERE,
202 base::Bind(&DeleteFileHelper, outgoing_dump_path_));
203
204 // Call back with an empty list.
205 callback.Run(dumps);
206 DVLOG(2) << "Releasing RTP dump failed.";
207 }
208
209 incoming_state_ = STATE_NONE;
210 outgoing_state_ = STATE_NONE;
211 incoming_dump_path_.clear();
212 outgoing_dump_path_.clear();
213 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698