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
3 // found in the LICENSE file.
4 
5 #include "services/network/p2p/socket_tcp.h"
6 
7 #include <stddef.h>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/sys_byteorder.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/time/time.h"
14 #include "jingle/glue/fake_ssl_client_socket.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h"
17 #include "net/socket/client_socket_factory.h"
18 #include "net/socket/client_socket_handle.h"
19 #include "net/socket/ssl_client_socket.h"
20 #include "net/socket/tcp_client_socket.h"
21 #include "services/network/proxy_resolving_client_socket.h"
22 #include "services/network/proxy_resolving_client_socket_factory.h"
23 #include "services/network/public/cpp/p2p_param_traits.h"
24 #include "third_party/webrtc/media/base/rtp_utils.h"
25 #include "url/gurl.h"
26 
27 namespace network {
28 namespace {
29 
30 typedef uint16_t PacketLength;
31 const int kPacketHeaderSize = sizeof(PacketLength);
32 const int kTcpReadBufferSize = 4096;
33 const int kPacketLengthOffset = 2;
34 const int kTurnChannelDataHeaderSize = 4;
35 const int kTcpRecvSocketBufferSize = 128 * 1024;
36 const int kTcpSendSocketBufferSize = 128 * 1024;
37 
IsTlsClientSocket(P2PSocketType type)38 bool IsTlsClientSocket(P2PSocketType type) {
39   return (type == P2P_SOCKET_STUN_TLS_CLIENT || type == P2P_SOCKET_TLS_CLIENT);
40 }
41 
IsPseudoTlsClientSocket(P2PSocketType type)42 bool IsPseudoTlsClientSocket(P2PSocketType type) {
43   return (type == P2P_SOCKET_SSLTCP_CLIENT ||
44           type == P2P_SOCKET_STUN_SSLTCP_CLIENT);
45 }
46 
47 }  // namespace
48 
SendBuffer()49 P2PSocketTcp::SendBuffer::SendBuffer() : rtc_packet_id(-1) {}
SendBuffer(int32_t rtc_packet_id,scoped_refptr<net::DrainableIOBuffer> buffer,const net::NetworkTrafficAnnotationTag traffic_annotation)50 P2PSocketTcp::SendBuffer::SendBuffer(
51     int32_t rtc_packet_id,
52     scoped_refptr<net::DrainableIOBuffer> buffer,
53     const net::NetworkTrafficAnnotationTag traffic_annotation)
54     : rtc_packet_id(rtc_packet_id),
55       buffer(buffer),
56       traffic_annotation(traffic_annotation) {}
57 P2PSocketTcp::SendBuffer::SendBuffer(const SendBuffer& rhs) = default;
58 P2PSocketTcp::SendBuffer::~SendBuffer() = default;
59 
P2PSocketTcpBase(Delegate * delegate,mojo::PendingRemote<mojom::P2PSocketClient> client,mojo::PendingReceiver<mojom::P2PSocket> socket,P2PSocketType type,ProxyResolvingClientSocketFactory * proxy_resolving_socket_factory)60 P2PSocketTcpBase::P2PSocketTcpBase(
61     Delegate* delegate,
62     mojo::PendingRemote<mojom::P2PSocketClient> client,
63     mojo::PendingReceiver<mojom::P2PSocket> socket,
64     P2PSocketType type,
65     ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory)
66     : P2PSocket(delegate, std::move(client), std::move(socket), P2PSocket::TCP),
67       type_(type),
68       proxy_resolving_socket_factory_(proxy_resolving_socket_factory) {}
69 
70 P2PSocketTcpBase::~P2PSocketTcpBase() = default;
71 
InitAccepted(const net::IPEndPoint & remote_address,std::unique_ptr<net::StreamSocket> socket)72 void P2PSocketTcpBase::InitAccepted(const net::IPEndPoint& remote_address,
73                                     std::unique_ptr<net::StreamSocket> socket) {
74   DCHECK(socket);
75   remote_address_.ip_address = remote_address;
76   // TODO(ronghuawu): Add FakeSSLServerSocket.
77   socket_ = std::move(socket);
78   DoRead();
79 }
80 
Init(const net::IPEndPoint & local_address,uint16_t min_port,uint16_t max_port,const P2PHostAndIPEndPoint & remote_address)81 void P2PSocketTcpBase::Init(const net::IPEndPoint& local_address,
82                             uint16_t min_port,
83                             uint16_t max_port,
84                             const P2PHostAndIPEndPoint& remote_address) {
85   DCHECK(!socket_);
86 
87   remote_address_ = remote_address;
88 
89   net::HostPortPair dest_host_port_pair;
90   // If there is a domain name, let's try it first, it's required by some proxy
91   // to only take hostname for CONNECT. If it has been DNS resolved, the result
92   // is likely cached and shouldn't cause 2nd DNS resolution in the case of
93   // direct connect (i.e. no proxy).
94   if (!remote_address.hostname.empty()) {
95     dest_host_port_pair = net::HostPortPair(remote_address.hostname,
96                                             remote_address.ip_address.port());
97   } else {
98     DCHECK(!remote_address.ip_address.address().empty());
99     dest_host_port_pair =
100         net::HostPortPair::FromIPEndPoint(remote_address.ip_address);
101   }
102 
103   // TODO(mallinath) - We are ignoring local_address altogether. We should
104   // find a way to inject this into ProxyResolvingClientSocket. This could be
105   // a problem on multi-homed host.
106 
107   socket_ = proxy_resolving_socket_factory_->CreateSocket(
108       GURL("https://" + dest_host_port_pair.ToString()),
109       IsTlsClientSocket(type_));
110 
111   if (IsPseudoTlsClientSocket(type_)) {
112     socket_ =
113         std::make_unique<jingle_glue::FakeSSLClientSocket>(std::move(socket_));
114   }
115 
116   int status = socket_->Connect(
117       base::BindOnce(&P2PSocketTcpBase::OnConnected, base::Unretained(this)));
118   if (status != net::ERR_IO_PENDING)
119     OnConnected(status);
120 }
121 
OnConnected(int result)122 void P2PSocketTcpBase::OnConnected(int result) {
123   DCHECK_NE(result, net::ERR_IO_PENDING);
124 
125   if (result != net::OK) {
126     LOG(WARNING) << "Error from connecting socket, result=" << result;
127     OnError();
128     return;
129   }
130 
131   OnOpen();
132 }
133 
OnOpen()134 void P2PSocketTcpBase::OnOpen() {
135   // Setting socket send and receive buffer size.
136   if (net::OK != socket_->SetReceiveBufferSize(kTcpRecvSocketBufferSize)) {
137     LOG(WARNING) << "Failed to set socket receive buffer size to "
138                  << kTcpRecvSocketBufferSize;
139   }
140 
141   if (net::OK != socket_->SetSendBufferSize(kTcpSendSocketBufferSize)) {
142     LOG(WARNING) << "Failed to set socket send buffer size to "
143                  << kTcpSendSocketBufferSize;
144   }
145 
146   if (!DoSendSocketCreateMsg())
147     return;
148 
149   DoRead();
150 }
151 
DoSendSocketCreateMsg()152 bool P2PSocketTcpBase::DoSendSocketCreateMsg() {
153   DCHECK(socket_.get());
154 
155   net::IPEndPoint local_address;
156   int result = socket_->GetLocalAddress(&local_address);
157   if (result < 0) {
158     LOG(ERROR) << "P2PSocketTcpBase::OnConnected: unable to get local"
159                << " address: " << result;
160     OnError();
161     return false;
162   }
163 
164   VLOG(1) << "Local address: " << local_address.ToString();
165 
166   net::IPEndPoint remote_address;
167 
168   // GetPeerAddress returns ERR_NAME_NOT_RESOLVED if the socket is connected
169   // through a proxy.
170   result = socket_->GetPeerAddress(&remote_address);
171   if (result < 0 && result != net::ERR_NAME_NOT_RESOLVED) {
172     LOG(ERROR) << "P2PSocketTcpBase::OnConnected: unable to get peer"
173                << " address: " << result;
174     OnError();
175     return false;
176   }
177 
178   if (!remote_address.address().empty()) {
179     VLOG(1) << "Remote address: " << remote_address.ToString();
180     if (remote_address_.ip_address.address().empty()) {
181       // Save |remote_address| if address is empty.
182       remote_address_.ip_address = remote_address;
183     }
184   } else {
185     VLOG(1) << "Remote address is unknown since connection is proxied";
186   }
187 
188   // If we are not doing TLS, we are ready to send data now.
189   // In case of TLS SignalConnect will be sent only after TLS handshake is
190   // successful. So no buffering will be done at socket handlers if any
191   // packets sent before that by the application.
192   client_->SocketCreated(local_address, remote_address);
193   return true;
194 }
195 
DoRead()196 void P2PSocketTcpBase::DoRead() {
197   while (true) {
198     if (!read_buffer_.get()) {
199       read_buffer_ = base::MakeRefCounted<net::GrowableIOBuffer>();
200       read_buffer_->SetCapacity(kTcpReadBufferSize);
201     } else if (read_buffer_->RemainingCapacity() < kTcpReadBufferSize) {
202       // Make sure that we always have at least kTcpReadBufferSize of
203       // remaining capacity in the read buffer. Normally all packets
204       // are smaller than kTcpReadBufferSize, so this is not really
205       // required.
206       read_buffer_->SetCapacity(read_buffer_->capacity() + kTcpReadBufferSize -
207                                 read_buffer_->RemainingCapacity());
208     }
209     const int result = socket_->Read(
210         read_buffer_.get(), read_buffer_->RemainingCapacity(),
211         base::BindOnce(&P2PSocketTcp::OnRead, base::Unretained(this)));
212     if (result == net::ERR_IO_PENDING || !HandleReadResult(result))
213       return;
214   }
215 }
216 
OnRead(int result)217 void P2PSocketTcpBase::OnRead(int result) {
218   if (HandleReadResult(result))
219     DoRead();
220 }
221 
OnPacket(std::vector<int8_t> data)222 bool P2PSocketTcpBase::OnPacket(std::vector<int8_t> data) {
223   if (!connected_) {
224     P2PSocket::StunMessageType type;
225     bool stun = GetStunPacketType(reinterpret_cast<uint8_t*>(&*data.begin()),
226                                   data.size(), &type);
227     if (stun && IsRequestOrResponse(type)) {
228       connected_ = true;
229     } else if (!stun || type == STUN_DATA_INDICATION) {
230       LOG(ERROR) << "Received unexpected data packet from "
231                  << remote_address_.ip_address.ToString()
232                  << " before STUN binding is finished. "
233                  << "Terminating connection.";
234       OnError();
235       return false;
236     }
237   }
238 
239   if (data.size() == 0) {
240     // https://tools.ietf.org/html/rfc4571#section-2 allows null packets which
241     // are ignored.
242     LOG(WARNING) << "Ignoring empty RTP-over-TCP frame.";
243     return true;
244   }
245 
246   client_->DataReceived(
247       remote_address_.ip_address, data,
248       base::TimeTicks() + base::TimeDelta::FromNanoseconds(rtc::TimeNanos()));
249 
250   delegate_->DumpPacket(
251       base::make_span(reinterpret_cast<const uint8_t*>(&data[0]), data.size()),
252       true);
253 
254   return true;
255 }
256 
WriteOrQueue(SendBuffer & send_buffer)257 void P2PSocketTcpBase::WriteOrQueue(SendBuffer& send_buffer) {
258   IncrementTotalSentPackets();
259   if (write_buffer_.buffer.get()) {
260     write_queue_.push(send_buffer);
261     IncrementDelayedPackets();
262     IncrementDelayedBytes(send_buffer.buffer->size());
263     return;
264   }
265 
266   write_buffer_ = send_buffer;
267   DoWrite();
268 }
269 
DoWrite()270 void P2PSocketTcpBase::DoWrite() {
271   while (!write_pending_ && write_buffer_.buffer.get()) {
272     int result = socket_->Write(
273         write_buffer_.buffer.get(), write_buffer_.buffer->BytesRemaining(),
274         base::BindOnce(&P2PSocketTcp::OnWritten, base::Unretained(this)),
275         net::NetworkTrafficAnnotationTag(write_buffer_.traffic_annotation));
276 
277     if (result == net::ERR_IO_PENDING) {
278       write_pending_ = true;
279     } else if (!HandleWriteResult(result)) {
280       break;
281     }
282   }
283 }
284 
OnWritten(int result)285 void P2PSocketTcpBase::OnWritten(int result) {
286   DCHECK(write_pending_);
287   DCHECK_NE(result, net::ERR_IO_PENDING);
288 
289   write_pending_ = false;
290 
291   if (HandleWriteResult(result))
292     DoWrite();
293 }
294 
HandleWriteResult(int result)295 bool P2PSocketTcpBase::HandleWriteResult(int result) {
296   DCHECK(write_buffer_.buffer.get());
297 
298   if (result < 0) {
299     ReportSocketError(result, "WebRTC.ICE.TcpSocketWriteErrorCode");
300 
301     LOG(ERROR) << "Error when sending data in TCP socket: " << result;
302     OnError();
303     return false;
304   }
305 
306   write_buffer_.buffer->DidConsume(result);
307   if (write_buffer_.buffer->BytesRemaining() == 0) {
308     int64_t send_time_ms = rtc::TimeMillis();
309     client_->SendComplete(
310         P2PSendPacketMetrics(0, write_buffer_.rtc_packet_id, send_time_ms));
311     if (write_queue_.empty()) {
312       write_buffer_.buffer = nullptr;
313       write_buffer_.rtc_packet_id = -1;
314     } else {
315       write_buffer_ = write_queue_.front();
316       write_queue_.pop();
317       // Update how many bytes are still waiting to be sent.
318       DecrementDelayedBytes(write_buffer_.buffer->size());
319     }
320   }
321   return true;
322 }
323 
HandleReadResult(int result)324 bool P2PSocketTcpBase::HandleReadResult(int result) {
325   if (result < 0) {
326     LOG(ERROR) << "Error when reading from TCP socket: " << result;
327     OnError();
328     return false;
329   } else if (result == 0) {
330     LOG(WARNING) << "Remote peer has shutdown TCP socket.";
331     OnError();
332     return false;
333   }
334 
335   read_buffer_->set_offset(read_buffer_->offset() + result);
336   char* head = read_buffer_->StartOfBuffer();  // Purely a convenience.
337   int pos = 0;
338   while (pos <= read_buffer_->offset()) {
339     size_t bytes_consumed = 0;
340     if (!ProcessInput(head + pos, read_buffer_->offset() - pos,
341                       &bytes_consumed)) {
342       return false;
343     }
344     if (!bytes_consumed)
345       break;
346     pos += bytes_consumed;
347   }
348   // We've consumed all complete packets from the buffer; now move any remaining
349   // bytes to the head of the buffer and set offset to reflect this.
350   if (pos && pos <= read_buffer_->offset()) {
351     memmove(head, head + pos, read_buffer_->offset() - pos);
352     read_buffer_->set_offset(read_buffer_->offset() - pos);
353   }
354 
355   return true;
356 }
357 
Send(const std::vector<int8_t> & data,const P2PPacketInfo & packet_info,const net::MutableNetworkTrafficAnnotationTag & traffic_annotation)358 void P2PSocketTcpBase::Send(
359     const std::vector<int8_t>& data,
360     const P2PPacketInfo& packet_info,
361     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
362   // Renderer should use this socket only to send data to |remote_address_|.
363   if (data.size() > kMaximumPacketSize ||
364       !(packet_info.destination == remote_address_.ip_address)) {
365     NOTREACHED();
366     OnError();
367     return;
368   }
369 
370   if (!connected_) {
371     P2PSocket::StunMessageType type = P2PSocket::StunMessageType();
372     bool stun = GetStunPacketType(
373         reinterpret_cast<const uint8_t*>(&*data.begin()), data.size(), &type);
374     if (!stun || type == STUN_DATA_INDICATION) {
375       LOG(ERROR) << "Page tried to send a data packet to "
376                  << packet_info.destination.ToString()
377                  << " before STUN binding is finished.";
378       OnError();
379       return;
380     }
381   }
382 
383   DoSend(packet_info.destination, data, packet_info.packet_options,
384          net::NetworkTrafficAnnotationTag(traffic_annotation));
385 }
386 
SetOption(P2PSocketOption option,int32_t value)387 void P2PSocketTcpBase::SetOption(P2PSocketOption option, int32_t value) {
388   switch (option) {
389     case P2P_SOCKET_OPT_RCVBUF:
390       socket_->SetReceiveBufferSize(value);
391       break;
392     case P2P_SOCKET_OPT_SNDBUF:
393       socket_->SetSendBufferSize(value);
394       break;
395     case P2P_SOCKET_OPT_DSCP:
396       return;  // For TCP sockets DSCP setting is not available.
397     default:
398       NOTREACHED();
399       return;
400   }
401 }
402 
P2PSocketTcp(Delegate * delegate,mojo::PendingRemote<mojom::P2PSocketClient> client,mojo::PendingReceiver<mojom::P2PSocket> socket,P2PSocketType type,ProxyResolvingClientSocketFactory * proxy_resolving_socket_factory)403 P2PSocketTcp::P2PSocketTcp(
404     Delegate* delegate,
405     mojo::PendingRemote<mojom::P2PSocketClient> client,
406     mojo::PendingReceiver<mojom::P2PSocket> socket,
407     P2PSocketType type,
408     ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory)
409     : P2PSocketTcpBase(delegate,
410                        std::move(client),
411                        std::move(socket),
412                        type,
413                        proxy_resolving_socket_factory) {
414   DCHECK(type == P2P_SOCKET_TCP_CLIENT || type == P2P_SOCKET_SSLTCP_CLIENT ||
415          type == P2P_SOCKET_TLS_CLIENT);
416 }
417 
~P2PSocketTcp()418 P2PSocketTcp::~P2PSocketTcp() {}
419 
ProcessInput(char * input,int input_len,size_t * bytes_consumed)420 bool P2PSocketTcp::ProcessInput(char* input,
421                                 int input_len,
422                                 size_t* bytes_consumed) {
423   *bytes_consumed = 0;
424   if (input_len < kPacketHeaderSize)
425     return true;
426 
427   int packet_size = base::NetToHost16(*reinterpret_cast<uint16_t*>(input));
428   if (input_len < packet_size + kPacketHeaderSize)
429     return true;
430 
431   char* cur = input + kPacketHeaderSize;
432   *bytes_consumed = kPacketHeaderSize + packet_size;
433 
434   return OnPacket(std::vector<int8_t>(cur, cur + packet_size));
435 }
436 
DoSend(const net::IPEndPoint & to,const std::vector<int8_t> & data,const rtc::PacketOptions & options,const net::NetworkTrafficAnnotationTag traffic_annotation)437 void P2PSocketTcp::DoSend(
438     const net::IPEndPoint& to,
439     const std::vector<int8_t>& data,
440     const rtc::PacketOptions& options,
441     const net::NetworkTrafficAnnotationTag traffic_annotation) {
442   int size = kPacketHeaderSize + data.size();
443   SendBuffer send_buffer(options.packet_id,
444                          base::MakeRefCounted<net::DrainableIOBuffer>(
445                              base::MakeRefCounted<net::IOBuffer>(size), size),
446                          traffic_annotation);
447   *reinterpret_cast<uint16_t*>(send_buffer.buffer->data()) =
448       base::HostToNet16(data.size());
449   memcpy(send_buffer.buffer->data() + kPacketHeaderSize, &data[0], data.size());
450 
451   cricket::ApplyPacketOptions(
452       reinterpret_cast<uint8_t*>(send_buffer.buffer->data()) +
453           kPacketHeaderSize,
454       send_buffer.buffer->BytesRemaining() - kPacketHeaderSize,
455       options.packet_time_params, rtc::TimeMicros());
456 
457   WriteOrQueue(send_buffer);
458 }
459 
460 // P2PSocketStunTcp
P2PSocketStunTcp(Delegate * delegate,mojo::PendingRemote<mojom::P2PSocketClient> client,mojo::PendingReceiver<mojom::P2PSocket> socket,P2PSocketType type,ProxyResolvingClientSocketFactory * proxy_resolving_socket_factory)461 P2PSocketStunTcp::P2PSocketStunTcp(
462     Delegate* delegate,
463     mojo::PendingRemote<mojom::P2PSocketClient> client,
464     mojo::PendingReceiver<mojom::P2PSocket> socket,
465     P2PSocketType type,
466     ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory)
467     : P2PSocketTcpBase(delegate,
468                        std::move(client),
469                        std::move(socket),
470                        type,
471                        proxy_resolving_socket_factory) {
472   DCHECK(type == P2P_SOCKET_STUN_TCP_CLIENT ||
473          type == P2P_SOCKET_STUN_SSLTCP_CLIENT ||
474          type == P2P_SOCKET_STUN_TLS_CLIENT);
475 }
476 
~P2PSocketStunTcp()477 P2PSocketStunTcp::~P2PSocketStunTcp() {}
478 
ProcessInput(char * input,int input_len,size_t * bytes_consumed)479 bool P2PSocketStunTcp::ProcessInput(char* input,
480                                     int input_len,
481                                     size_t* bytes_consumed) {
482   *bytes_consumed = 0;
483   if (input_len < kPacketHeaderSize + kPacketLengthOffset)
484     return true;
485 
486   int pad_bytes;
487   int packet_size = GetExpectedPacketSize(
488       reinterpret_cast<const uint8_t*>(input), input_len, &pad_bytes);
489 
490   if (input_len < packet_size + pad_bytes)
491     return true;
492 
493   // We have a complete packet. Read through it.
494   char* cur = input;
495   *bytes_consumed = packet_size + pad_bytes;
496   return OnPacket(std::vector<int8_t>(cur, cur + packet_size));
497 }
498 
DoSend(const net::IPEndPoint & to,const std::vector<int8_t> & data,const rtc::PacketOptions & options,const net::NetworkTrafficAnnotationTag traffic_annotation)499 void P2PSocketStunTcp::DoSend(
500     const net::IPEndPoint& to,
501     const std::vector<int8_t>& data,
502     const rtc::PacketOptions& options,
503     const net::NetworkTrafficAnnotationTag traffic_annotation) {
504   // Each packet is expected to have header (STUN/TURN ChannelData), where
505   // header contains message type and and length of message.
506   if (data.size() < kPacketHeaderSize + kPacketLengthOffset) {
507     NOTREACHED();
508     OnError();
509     return;
510   }
511 
512   int pad_bytes;
513   size_t expected_len = GetExpectedPacketSize(
514       reinterpret_cast<const uint8_t*>(&data[0]), data.size(), &pad_bytes);
515 
516   // Accepts only complete STUN/TURN packets.
517   if (data.size() != expected_len) {
518     NOTREACHED();
519     OnError();
520     return;
521   }
522 
523   // Add any pad bytes to the total size.
524   int size = data.size() + pad_bytes;
525 
526   SendBuffer send_buffer(options.packet_id,
527                          base::MakeRefCounted<net::DrainableIOBuffer>(
528                              base::MakeRefCounted<net::IOBuffer>(size), size),
529                          traffic_annotation);
530   memcpy(send_buffer.buffer->data(), &data[0], data.size());
531 
532   cricket::ApplyPacketOptions(
533       reinterpret_cast<uint8_t*>(send_buffer.buffer->data()), data.size(),
534       options.packet_time_params, rtc::TimeMicros());
535 
536   if (pad_bytes) {
537     char padding[4] = {0};
538     DCHECK_LE(pad_bytes, 4);
539     memcpy(send_buffer.buffer->data() + data.size(), padding, pad_bytes);
540   }
541 
542   // WriteOrQueue may free the memory, so dump it first.
543   delegate_->DumpPacket(
544       base::make_span(reinterpret_cast<uint8_t*>(send_buffer.buffer->data()),
545                       data.size()),
546       false);
547 
548   WriteOrQueue(send_buffer);
549 }
550 
GetExpectedPacketSize(const uint8_t * data,int len,int * pad_bytes)551 int P2PSocketStunTcp::GetExpectedPacketSize(const uint8_t* data,
552                                             int len,
553                                             int* pad_bytes) {
554   DCHECK_LE(kTurnChannelDataHeaderSize, len);
555   // Both stun and turn had length at offset 2.
556   int packet_size = base::NetToHost16(
557       *reinterpret_cast<const uint16_t*>(data + kPacketLengthOffset));
558 
559   // Get packet type (STUN or TURN).
560   uint16_t msg_type =
561       base::NetToHost16(*reinterpret_cast<const uint16_t*>(data));
562 
563   *pad_bytes = 0;
564   // Add heder length to packet length.
565   if ((msg_type & 0xC000) == 0) {
566     packet_size += kStunHeaderSize;
567   } else {
568     packet_size += kTurnChannelDataHeaderSize;
569     // Calculate any padding if present.
570     if (packet_size % 4)
571       *pad_bytes = 4 - packet_size % 4;
572   }
573   return packet_size;
574 }
575 
576 }  // namespace network
577