summaryrefslogtreecommitdiff
path: root/chromium/services/network/p2p/socket.h
blob: 63a42ac6b2930619408ceee09e924208a2a68b2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SERVICES_NETWORK_P2P_SOCKET_H_
#define SERVICES_NETWORK_P2P_SOCKET_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>

#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/ip_endpoint.h"
#include "net/socket/datagram_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/p2p_socket_type.h"
#include "services/network/public/mojom/p2p.mojom.h"

namespace net {
class NetLog;
class NetworkIsolationKey;
}

namespace network {

class ProxyResolvingClientSocketFactory;
class P2PMessageThrottler;

// Base class for P2P sockets.
class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocket : public mojom::P2PSocket {
 public:
  // Interface implemented in P2PSocketManager.
  class Delegate {
   public:
    Delegate() = default;

    // Destroys |socket| and removes it from the list of sockets.
    virtual void DestroySocket(P2PSocket* socket) = 0;

    // Called by P2PSocketTcpServer after a new socket is created for an
    // incoming connection.
    virtual void AddAcceptedConnection(std::unique_ptr<P2PSocket> socket) = 0;

    // Called for each incoming/outgoing packet.
    virtual void DumpPacket(base::span<const uint8_t> data, bool incoming) = 0;

   protected:
    virtual ~Delegate() = default;
  };

  static const int kStunHeaderSize = 20;
  static const size_t kMaximumPacketSize = 32768;

  // Creates P2PSocket of the specific type.
  static std::unique_ptr<P2PSocket> Create(
      Delegate* delegate,
      mojo::PendingRemote<mojom::P2PSocketClient> client,
      mojo::PendingReceiver<mojom::P2PSocket> socket,
      P2PSocketType type,
      net::NetLog* net_log,
      ProxyResolvingClientSocketFactory* proxy_resolving_socket_factory,
      P2PMessageThrottler* throttler);

  ~P2PSocket() override;

  // Initializes the socket. Returns false when initialization fails.
  // |min_port| and |max_port| specify the valid range of allowed ports.
  // |min_port| must be less than or equal to |max_port|.
  // If |min_port| is zero, |max_port| must also be zero and it means all ports
  // are valid.
  // If |local_address.port()| is zero, the socket will be initialized to a port
  // in the valid range.
  // If |local_address.port()| is nonzero and not in the valid range,
  // initialization will fail.
  // |network_isolation_key| specifies the network stack cache shard to used.
  virtual void Init(const net::IPEndPoint& local_address,
                    uint16_t min_port,
                    uint16_t max_port,
                    const P2PHostAndIPEndPoint& remote_address,
                    const net::NetworkIsolationKey& network_isolation_key) = 0;

  mojo::PendingRemote<mojom::P2PSocketClient> ReleaseClientForTesting();
  mojo::PendingReceiver<mojom::P2PSocket> ReleaseReceiverForTesting();

 protected:
  friend class P2PSocketTcpTestBase;

  // This should match suffix IPProtocolType defined in histograms.xml.
  enum ProtocolType { UDP = 0x1, TCP = 0x2 };

  // TODO(mallinath) - Remove this below enum and use one defined in
  // libjingle/souce/talk/p2p/base/stun.h
  enum StunMessageType {
    STUN_BINDING_REQUEST = 0x0001,
    STUN_BINDING_RESPONSE = 0x0101,
    STUN_BINDING_ERROR_RESPONSE = 0x0111,
    STUN_SHARED_SECRET_REQUEST = 0x0002,
    STUN_SHARED_SECRET_RESPONSE = 0x0102,
    STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112,
    STUN_ALLOCATE_REQUEST = 0x0003,
    STUN_ALLOCATE_RESPONSE = 0x0103,
    STUN_ALLOCATE_ERROR_RESPONSE = 0x0113,
    STUN_SEND_REQUEST = 0x0004,
    STUN_SEND_RESPONSE = 0x0104,
    STUN_SEND_ERROR_RESPONSE = 0x0114,
    STUN_DATA_INDICATION = 0x0115,
    TURN_SEND_INDICATION = 0x0016,
    TURN_DATA_INDICATION = 0x0017,
    TURN_CREATE_PERMISSION_REQUEST = 0x0008,
    TURN_CREATE_PERMISSION_RESPONSE = 0x0108,
    TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118,
    TURN_CHANNEL_BIND_REQUEST = 0x0009,
    TURN_CHANNEL_BIND_RESPONSE = 0x0109,
    TURN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119,
  };

  enum State {
    STATE_UNINITIALIZED,
    STATE_CONNECTING,
    STATE_OPEN,
  };

  P2PSocket(Delegate* delegate,
            mojo::PendingRemote<mojom::P2PSocketClient> client,
            mojo::PendingReceiver<mojom::P2PSocket> socket,
            ProtocolType protocol_type);

  // Verifies that the packet |data| has a valid STUN header. In case
  // of success stores type of the message in |type|.
  static bool GetStunPacketType(const uint8_t* data,
                                int data_size,
                                StunMessageType* type);
  static bool IsRequestOrResponse(StunMessageType type);

  static void ReportSocketError(int result, const char* histogram_name);

  // Should be called by subclasses on protocol errors. Closes P2PSocket and
  // P2PSocketClient channels and calls delegate_->DestroySocket() to
  // destroy the socket.
  void OnError();

  // Used by subclasses to track the metrics of delayed bytes and packets.
  void IncrementDelayedPackets();
  void IncrementTotalSentPackets();
  void IncrementDelayedBytes(uint32_t size);
  void DecrementDelayedBytes(uint32_t size);

  Delegate* delegate_;
  mojo::Remote<mojom::P2PSocketClient> client_;
  mojo::Receiver<mojom::P2PSocket> receiver_;

  ProtocolType protocol_type_;

 private:
  // Track total delayed packets for calculating how many packets are
  // delayed by system at the end of call.
  uint32_t send_packets_delayed_total_ = 0;
  uint32_t send_packets_total_ = 0;

  // Track the maximum of consecutive delayed bytes caused by system's
  // EWOULDBLOCK.
  int32_t send_bytes_delayed_max_ = 0;
  int32_t send_bytes_delayed_cur_ = 0;

  base::WeakPtrFactory<P2PSocket> weak_ptr_factory_{this};

  DISALLOW_COPY_AND_ASSIGN(P2PSocket);
};

}  // namespace network

#endif  // SERVICES_NETWORK_P2P_SOCKET_H_