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

Side by Side Diff: content/browser/renderer_host/p2p/socket_host.cc

Issue 264793017: Implements RTP header dumping. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix leak Created 6 years, 6 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
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/browser/renderer_host/p2p/socket_host.h" 5 #include "content/browser/renderer_host/p2p/socket_host.h"
6 6
7 #include "base/sys_byteorder.h" 7 #include "base/sys_byteorder.h"
8 #include "content/browser/renderer_host/p2p/socket_host_tcp.h" 8 #include "content/browser/renderer_host/p2p/socket_host_tcp.h"
9 #include "content/browser/renderer_host/p2p/socket_host_tcp_server.h" 9 #include "content/browser/renderer_host/p2p/socket_host_tcp_server.h"
10 #include "content/browser/renderer_host/p2p/socket_host_udp.h" 10 #include "content/browser/renderer_host/p2p/socket_host_udp.h"
11 #include "content/browser/renderer_host/render_process_host_impl.h"
12 #include "content/public/browser/browser_thread.h"
11 #include "crypto/hmac.h" 13 #include "crypto/hmac.h"
12 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" 14 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
13 #include "third_party/libjingle/source/talk/base/byteorder.h" 15 #include "third_party/libjingle/source/talk/base/byteorder.h"
14 #include "third_party/libjingle/source/talk/base/messagedigest.h" 16 #include "third_party/libjingle/source/talk/base/messagedigest.h"
15 #include "third_party/libjingle/source/talk/p2p/base/stun.h" 17 #include "third_party/libjingle/source/talk/p2p/base/stun.h"
16 18
17 namespace { 19 namespace {
18 20
19 const uint32 kStunMagicCookie = 0x2112A442; 21 const uint32 kStunMagicCookie = 0x2112A442;
20 const int kMinRtpHdrLen = 12; 22 const int kMinRtpHdrLen = 12;
(...skipping 27 matching lines...) Expand all
48 bool IsTurnSendIndicationPacket(const char* data) { 50 bool IsTurnSendIndicationPacket(const char* data) {
49 uint16 type = talk_base::GetBE16(data); 51 uint16 type = talk_base::GetBE16(data);
50 return (type == cricket::TURN_SEND_INDICATION); 52 return (type == cricket::TURN_SEND_INDICATION);
51 } 53 }
52 54
53 bool IsRtpPacket(const char* data, int len) { 55 bool IsRtpPacket(const char* data, int len) {
54 return ((*data & 0xC0) == 0x80); 56 return ((*data & 0xC0) == 0x80);
55 } 57 }
56 58
57 // Verifies rtp header and message length. 59 // Verifies rtp header and message length.
58 bool ValidateRtpHeader(char* rtp, int length) { 60 bool ValidateRtpHeader(const char* rtp, int length, size_t* header_length) {
61 if (header_length)
62 *header_length = 0;
63
59 int cc_count = rtp[0] & 0x0F; 64 int cc_count = rtp[0] & 0x0F;
60 int rtp_hdr_len_without_extn = kMinRtpHdrLen + 4 * cc_count; 65 int rtp_hdr_len_without_extn = kMinRtpHdrLen + 4 * cc_count;
61 if (rtp_hdr_len_without_extn > length) { 66 if (rtp_hdr_len_without_extn > length) {
62 return false; 67 return false;
63 } 68 }
64 69
65 // If extension bit is not set, we are done with header processing, as input 70 // If extension bit is not set, we are done with header processing, as input
66 // length is verified above. 71 // length is verified above.
67 if (!(rtp[0] & 0x10)) { 72 if (!(rtp[0] & 0x10)) {
73 if (header_length)
74 *header_length = rtp_hdr_len_without_extn;
75
68 return true; 76 return true;
69 } 77 }
70 78
71 rtp += rtp_hdr_len_without_extn; 79 rtp += rtp_hdr_len_without_extn;
72 80
73 // Getting extension profile length. 81 // Getting extension profile length.
74 // Length is in 32 bit words. 82 // Length is in 32 bit words.
75 uint16 extn_length = talk_base::GetBE16(rtp + 2) * 4; 83 uint16 extn_length = talk_base::GetBE16(rtp + 2) * 4;
76 84
77 // Verify input length against total header size. 85 // Verify input length against total header size.
78 if (rtp_hdr_len_without_extn + kRtpExtnHdrLen + extn_length > length) { 86 if (rtp_hdr_len_without_extn + kRtpExtnHdrLen + extn_length > length) {
79 return false; 87 return false;
80 } 88 }
89
90 if (header_length)
91 *header_length = rtp_hdr_len_without_extn + kRtpExtnHdrLen + extn_length;
81 return true; 92 return true;
82 } 93 }
83 94
84 void UpdateAbsSendTimeExtnValue(char* extn_data, int len, 95 void UpdateAbsSendTimeExtnValue(char* extn_data, int len,
85 uint32 abs_send_time) { 96 uint32 abs_send_time) {
86 // Absolute send time in RTP streams. 97 // Absolute send time in RTP streams.
87 // 98 //
88 // The absolute send time is signaled to the receiver in-band using the 99 // The absolute send time is signaled to the receiver in-band using the
89 // general mechanism for RTP header extensions [RFC5285]. The payload 100 // general mechanism for RTP header extensions [RFC5285]. The payload
90 // of this extension (the transmitted value) is a 24-bit unsigned integer 101 // of this extension (the transmitted value) is a 24-bit unsigned integer
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 if (options.packet_time_params.rtp_sendtime_extension_id != -1) { 210 if (options.packet_time_params.rtp_sendtime_extension_id != -1) {
200 UpdateRtpAbsSendTimeExtn( 211 UpdateRtpAbsSendTimeExtn(
201 start, rtp_length, 212 start, rtp_length,
202 options.packet_time_params.rtp_sendtime_extension_id, abs_send_time); 213 options.packet_time_params.rtp_sendtime_extension_id, abs_send_time);
203 } 214 }
204 215
205 UpdateRtpAuthTag(start, rtp_length, options); 216 UpdateRtpAuthTag(start, rtp_length, options);
206 return true; 217 return true;
207 } 218 }
208 219
209 bool GetRtpPacketStartPositionAndLength( 220 bool GetRtpPacketStartPositionAndLength(const char* packet,
210 char* packet, int length, int* rtp_start_pos, int* rtp_packet_length) { 221 int length,
222 int* rtp_start_pos,
223 int* rtp_packet_length) {
211 int rtp_begin, rtp_length; 224 int rtp_begin, rtp_length;
212 if (IsTurnChannelData(packet)) { 225 if (IsTurnChannelData(packet)) {
213 // Turn Channel Message header format. 226 // Turn Channel Message header format.
214 // 0 1 2 3 227 // 0 1 2 3
215 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 228 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
216 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 229 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217 // | Channel Number | Length | 230 // | Channel Number | Length |
218 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 231 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219 // | | 232 // | |
220 // / Application Data / 233 // / Application Data /
(...skipping 15 matching lines...) Expand all
236 } 249 }
237 // Validate STUN message length. 250 // Validate STUN message length.
238 int stun_msg_len = talk_base::GetBE16(&packet[2]); 251 int stun_msg_len = talk_base::GetBE16(&packet[2]);
239 if (stun_msg_len + P2PSocketHost::kStunHeaderSize != length) { 252 if (stun_msg_len + P2PSocketHost::kStunHeaderSize != length) {
240 return false; 253 return false;
241 } 254 }
242 255
243 // First skip mandatory stun header which is of 20 bytes. 256 // First skip mandatory stun header which is of 20 bytes.
244 rtp_begin = P2PSocketHost::kStunHeaderSize; 257 rtp_begin = P2PSocketHost::kStunHeaderSize;
245 // Loop through STUN attributes until we find STUN DATA attribute. 258 // Loop through STUN attributes until we find STUN DATA attribute.
246 char* start = packet + rtp_begin; 259 const char* start = packet + rtp_begin;
247 bool data_attr_present = false; 260 bool data_attr_present = false;
248 while ((packet + rtp_begin) - start < stun_msg_len) { 261 while ((packet + rtp_begin) - start < stun_msg_len) {
249 // Keep reading STUN attributes until we hit DATA attribute. 262 // Keep reading STUN attributes until we hit DATA attribute.
250 // Attribute will be a TLV structure. 263 // Attribute will be a TLV structure.
251 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 264 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
252 // | Type | Length | 265 // | Type | Length |
253 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 266 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
254 // | Value (variable) .... 267 // | Value (variable) ....
255 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 268 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
256 // The value in the length field MUST contain the length of the Value 269 // The value in the length field MUST contain the length of the Value
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 309
297 } else { 310 } else {
298 // This is a raw RTP packet. 311 // This is a raw RTP packet.
299 rtp_begin = 0; 312 rtp_begin = 0;
300 rtp_length = length; 313 rtp_length = length;
301 } 314 }
302 315
303 // Making sure we have a valid RTP packet at the end. 316 // Making sure we have a valid RTP packet at the end.
304 if (!(rtp_length < kMinRtpHdrLen) && 317 if (!(rtp_length < kMinRtpHdrLen) &&
305 IsRtpPacket(packet + rtp_begin, rtp_length) && 318 IsRtpPacket(packet + rtp_begin, rtp_length) &&
306 ValidateRtpHeader(packet + rtp_begin, rtp_length)) { 319 ValidateRtpHeader(packet + rtp_begin, rtp_length, NULL)) {
307 *rtp_start_pos = rtp_begin; 320 *rtp_start_pos = rtp_begin;
308 *rtp_packet_length = rtp_length; 321 *rtp_packet_length = rtp_length;
309 return true; 322 return true;
310 } 323 }
311 return false; 324 return false;
312 } 325 }
313 326
314 // ValidateRtpHeader must be called before this method to make sure, we have 327 // ValidateRtpHeader must be called before this method to make sure, we have
315 // a sane rtp packet. 328 // a sane rtp packet.
316 bool UpdateRtpAbsSendTimeExtn(char* rtp, int length, 329 bool UpdateRtpAbsSendTimeExtn(char* rtp, int length,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 while ((*rtp == 0) && (rtp - extn_start < extn_length)) { 395 while ((*rtp == 0) && (rtp - extn_start < extn_length)) {
383 ++rtp; 396 ++rtp;
384 } 397 }
385 } 398 }
386 } 399 }
387 return found; 400 return found;
388 } 401 }
389 402
390 } // packet_processing_helpers 403 } // packet_processing_helpers
391 404
392 P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender, 405 P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender, int socket_id)
393 int id)
394 : message_sender_(message_sender), 406 : message_sender_(message_sender),
395 id_(id), 407 id_(socket_id),
396 state_(STATE_UNINITIALIZED) { 408 state_(STATE_UNINITIALIZED),
409 dump_incoming_rtp_packet_(false),
410 dump_outgoing_rtp_packet_(false),
411 weak_ptr_factory_(this) {
397 } 412 }
398 413
399 P2PSocketHost::~P2PSocketHost() { } 414 P2PSocketHost::~P2PSocketHost() { }
400 415
401 // Verifies that the packet |data| has a valid STUN header. 416 // Verifies that the packet |data| has a valid STUN header.
402 // static 417 // static
403 bool P2PSocketHost::GetStunPacketType( 418 bool P2PSocketHost::GetStunPacketType(
404 const char* data, int data_size, StunMessageType* type) { 419 const char* data, int data_size, StunMessageType* type) {
405 420
406 if (data_size < kStunHeaderSize) 421 if (data_size < kStunHeaderSize)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 } 454 }
440 } 455 }
441 456
442 // static 457 // static
443 bool P2PSocketHost::IsRequestOrResponse(StunMessageType type) { 458 bool P2PSocketHost::IsRequestOrResponse(StunMessageType type) {
444 return type == STUN_BINDING_REQUEST || type == STUN_BINDING_RESPONSE || 459 return type == STUN_BINDING_REQUEST || type == STUN_BINDING_RESPONSE ||
445 type == STUN_ALLOCATE_REQUEST || type == STUN_ALLOCATE_RESPONSE; 460 type == STUN_ALLOCATE_REQUEST || type == STUN_ALLOCATE_RESPONSE;
446 } 461 }
447 462
448 // static 463 // static
449 P2PSocketHost* P2PSocketHost::Create( 464 P2PSocketHost* P2PSocketHost::Create(IPC::Sender* message_sender,
450 IPC::Sender* message_sender, int id, P2PSocketType type, 465 int socket_id,
451 net::URLRequestContextGetter* url_context, 466 P2PSocketType type,
452 P2PMessageThrottler* throttler) { 467 net::URLRequestContextGetter* url_context,
468 P2PMessageThrottler* throttler) {
453 switch (type) { 469 switch (type) {
454 case P2P_SOCKET_UDP: 470 case P2P_SOCKET_UDP:
455 return new P2PSocketHostUdp(message_sender, id, throttler); 471 return new P2PSocketHostUdp(message_sender, socket_id, throttler);
456 case P2P_SOCKET_TCP_SERVER: 472 case P2P_SOCKET_TCP_SERVER:
457 return new P2PSocketHostTcpServer( 473 return new P2PSocketHostTcpServer(
458 message_sender, id, P2P_SOCKET_TCP_CLIENT); 474 message_sender, socket_id, P2P_SOCKET_TCP_CLIENT);
459 475
460 case P2P_SOCKET_STUN_TCP_SERVER: 476 case P2P_SOCKET_STUN_TCP_SERVER:
461 return new P2PSocketHostTcpServer( 477 return new P2PSocketHostTcpServer(
462 message_sender, id, P2P_SOCKET_STUN_TCP_CLIENT); 478 message_sender, socket_id, P2P_SOCKET_STUN_TCP_CLIENT);
463 479
464 case P2P_SOCKET_TCP_CLIENT: 480 case P2P_SOCKET_TCP_CLIENT:
465 case P2P_SOCKET_SSLTCP_CLIENT: 481 case P2P_SOCKET_SSLTCP_CLIENT:
466 case P2P_SOCKET_TLS_CLIENT: 482 case P2P_SOCKET_TLS_CLIENT:
467 return new P2PSocketHostTcp(message_sender, id, type, url_context); 483 return new P2PSocketHostTcp(message_sender, socket_id, type, url_context);
468 484
469 case P2P_SOCKET_STUN_TCP_CLIENT: 485 case P2P_SOCKET_STUN_TCP_CLIENT:
470 case P2P_SOCKET_STUN_SSLTCP_CLIENT: 486 case P2P_SOCKET_STUN_SSLTCP_CLIENT:
471 case P2P_SOCKET_STUN_TLS_CLIENT: 487 case P2P_SOCKET_STUN_TLS_CLIENT:
472 return new P2PSocketHostStunTcp(message_sender, id, type, url_context); 488 return new P2PSocketHostStunTcp(
489 message_sender, socket_id, type, url_context);
473 } 490 }
474 491
475 NOTREACHED(); 492 NOTREACHED();
476 return NULL; 493 return NULL;
477 } 494 }
478 495
496 void P2PSocketHost::StartRtpDump(
497 bool incoming,
498 bool outgoing,
499 const RenderProcessHost::WebRtcRtpPacketCallback& packet_callback) {
500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
501 DCHECK(!packet_callback.is_null());
502 DCHECK(incoming || outgoing);
503
504 if (incoming)
505 dump_incoming_rtp_packet_ = true;
506
507 if (outgoing)
508 dump_outgoing_rtp_packet_ = true;
509
510 packet_dump_callback_ = packet_callback;
511 }
512
513 void P2PSocketHost::StopRtpDump(bool incoming, bool outgoing) {
514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
515 DCHECK(incoming || outgoing);
516
517 if (incoming)
518 dump_incoming_rtp_packet_ = false;
519
520 if (outgoing)
521 dump_outgoing_rtp_packet_ = false;
522
523 if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_)
524 packet_dump_callback_.Reset();
525 }
526
527 void P2PSocketHost::DumpRtpPacket(const char* packet,
528 size_t length,
529 bool incoming) {
530 if (IsDtlsPacket(packet, length) || IsRtcpPacket(packet))
531 return;
532
533 int rtp_packet_pos = 0;
534 int rtp_packet_length = length;
535 if (!packet_processing_helpers::GetRtpPacketStartPositionAndLength(
536 packet, length, &rtp_packet_pos, &rtp_packet_length))
537 return;
538
539 packet += rtp_packet_pos;
540
541 size_t header_length = 0;
542 bool valid = ValidateRtpHeader(packet, rtp_packet_length, &header_length);
543 if (!valid) {
544 DCHECK(false);
545 return;
546 }
547
548 scoped_ptr<uint8[]> header_buffer(new uint8[header_length]);
549 memcpy(header_buffer.get(), packet, header_length);
550
551 // Posts to the IO thread as the data members should be accessed on the IO
552 // thread only.
553 BrowserThread::PostTask(BrowserThread::IO,
554 FROM_HERE,
555 base::Bind(&P2PSocketHost::DumpRtpPacketOnIOThread,
556 weak_ptr_factory_.GetWeakPtr(),
557 Passed(&header_buffer),
558 header_length,
559 rtp_packet_length,
560 incoming));
561 }
562
563 void P2PSocketHost::DumpRtpPacketOnIOThread(scoped_ptr<uint8[]> packet_header,
564 size_t header_length,
565 size_t packet_length,
566 bool incoming) {
567 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
568
569 if ((incoming && !dump_incoming_rtp_packet_) ||
570 (!incoming && !dump_outgoing_rtp_packet_) ||
571 packet_dump_callback_.is_null()) {
572 return;
573 }
574
575 // |packet_dump_callback_| must be called on the UI thread.
576 BrowserThread::PostTask(BrowserThread::UI,
577 FROM_HERE,
578 base::Bind(packet_dump_callback_,
579 packet_header.get(),
580 header_length,
581 packet_length,
582 incoming));
583 }
584
479 } // namespace content 585 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/p2p/socket_host.h ('k') | content/browser/renderer_host/p2p/socket_host_tcp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698