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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
|
// Copyright (c) 2012 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.
//
// A toy client, which connects to a specified port and sends QUIC
// request to that endpoint.
#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_H_
#define NET_TOOLS_QUIC_QUIC_CLIENT_H_
#include <string>
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_client_session.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
namespace net {
class ProofVerifier;
class QuicServerId;
namespace tools {
class QuicEpollConnectionHelper;
namespace test {
class QuicClientPeer;
} // namespace test
class QuicClient : public EpollCallbackInterface,
public QuicDataStream::Visitor {
public:
class ResponseListener {
public:
ResponseListener() {}
virtual ~ResponseListener() {}
virtual void OnCompleteResponse(QuicStreamId id,
const BalsaHeaders& response_headers,
const string& response_body) = 0;
};
// Create a quic client, which will have events managed by an externally owned
// EpollServer.
QuicClient(IPEndPoint server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
bool print_response,
EpollServer* epoll_server);
QuicClient(IPEndPoint server_address,
const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
bool print_response,
const QuicConfig& config,
EpollServer* epoll_server);
~QuicClient() override;
// Initializes the client to create a connection. Should be called exactly
// once before calling StartConnect or Connect. Returns true if the
// initialization succeeds, false otherwise.
bool Initialize();
// "Connect" to the QUIC server, including performing synchronous crypto
// handshake.
bool Connect();
// Start the crypto handshake. This can be done in place of the synchronous
// Connect(), but callers are responsible for making sure the crypto handshake
// completes.
bool StartConnect();
// Returns true if the crypto handshake has yet to establish encryption.
// Returns false if encryption is active (even if the server hasn't confirmed
// the handshake) or if the connection has been closed.
bool EncryptionBeingEstablished();
// Disconnects from the QUIC server.
void Disconnect();
// Sends a request simple GET for each URL in |args|, and then waits for
// each to complete.
void SendRequestsAndWaitForResponse(const
base::CommandLine::StringVector& args);
// Returns a newly created QuicSpdyClientStream, owned by the
// QuicClient.
QuicSpdyClientStream* CreateReliableClientStream();
// Wait for events until the stream with the given ID is closed.
void WaitForStreamToClose(QuicStreamId id);
// Wait for events until the handshake is confirmed.
void WaitForCryptoHandshakeConfirmed();
// Wait up to 50ms, and handle any events which occur.
// Returns true if there are any outstanding requests.
bool WaitForEvents();
// From EpollCallbackInterface
void OnRegistration(EpollServer* eps, int fd, int event_mask) override {}
void OnModification(int fd, int event_mask) override {}
void OnEvent(int fd, EpollEvent* event) override;
// |fd_| can be unregistered without the client being disconnected. This
// happens in b3m QuicProber where we unregister |fd_| to feed in events to
// the client from the SelectServer.
void OnUnregistration(int fd, bool replaced) override {}
void OnShutdown(EpollServer* eps, int fd) override {}
// QuicDataStream::Visitor
void OnClose(QuicDataStream* stream) override;
QuicClientSession* session() { return session_.get(); }
bool connected() const;
void set_bind_to_address(IPAddressNumber address) {
bind_to_address_ = address;
}
IPAddressNumber bind_to_address() const { return bind_to_address_; }
void set_local_port(int local_port) { local_port_ = local_port; }
const IPEndPoint& server_address() const { return server_address_; }
const IPEndPoint& client_address() const { return client_address_; }
int fd() { return fd_; }
const QuicServerId& server_id() const { return server_id_; }
// This should only be set before the initial Connect()
void set_server_id(const QuicServerId& server_id) {
server_id_ = server_id;
}
void SetUserAgentID(const string& user_agent_id) {
crypto_config_.set_user_agent_id(user_agent_id);
}
// SetProofVerifier sets the ProofVerifier that will be used to verify the
// server's certificate and takes ownership of |verifier|.
void SetProofVerifier(ProofVerifier* verifier) {
// TODO(rtenneti): We should set ProofVerifier in QuicClientSession.
crypto_config_.SetProofVerifier(verifier);
}
// SetChannelIDSource sets a ChannelIDSource that will be called, when the
// server supports channel IDs, to obtain a channel ID for signing a message
// proving possession of the channel ID. This object takes ownership of
// |source|.
void SetChannelIDSource(ChannelIDSource* source) {
crypto_config_.SetChannelIDSource(source);
}
void SetSupportedVersions(const QuicVersionVector& versions) {
supported_versions_ = versions;
}
// Takes ownership of the listener.
void set_response_listener(ResponseListener* listener) {
response_listener_.reset(listener);
}
protected:
virtual QuicConnectionId GenerateConnectionId();
virtual QuicEpollConnectionHelper* CreateQuicConnectionHelper();
virtual QuicPacketWriter* CreateQuicPacketWriter();
virtual int ReadPacket(char* buffer,
int buffer_len,
IPEndPoint* server_address,
IPAddressNumber* client_ip);
EpollServer* epoll_server() { return epoll_server_; }
QuicConfig* config() { return &config_; }
private:
friend class net::tools::test::QuicClientPeer;
// A packet writer factory that always returns the same writer
class DummyPacketWriterFactory : public QuicConnection::PacketWriterFactory {
public:
DummyPacketWriterFactory(QuicPacketWriter* writer);
~DummyPacketWriterFactory() override;
QuicPacketWriter* Create(QuicConnection* connection) const override;
private:
QuicPacketWriter* writer_;
};
// Used during initialization: creates the UDP socket FD, sets socket options,
// and binds the socket to our address.
bool CreateUDPSocket();
// Read a UDP packet and hand it to the framer.
bool ReadAndProcessPacket();
// Address of the server.
const IPEndPoint server_address_;
// |server_id_| is a tuple (hostname, port, is_https) of the server.
QuicServerId server_id_;
// config_ and crypto_config_ contain configuration and cached state about
// servers.
QuicConfig config_;
QuicCryptoClientConfig crypto_config_;
// Address of the client if the client is connected to the server.
IPEndPoint client_address_;
// If initialized, the address to bind to.
IPAddressNumber bind_to_address_;
// Local port to bind to. Initialize to 0.
int local_port_;
// Writer used to actually send packets to the wire. Needs to outlive
// |session_|.
scoped_ptr<QuicPacketWriter> writer_;
// Session which manages streams.
scoped_ptr<QuicClientSession> session_;
// Listens for events on the client socket.
EpollServer* epoll_server_;
// UDP socket.
int fd_;
// Helper to be used by created connections.
scoped_ptr<QuicEpollConnectionHelper> helper_;
// Listens for full responses.
scoped_ptr<ResponseListener> response_listener_;
// Tracks if the client is initialized to connect.
bool initialized_;
// If overflow_supported_ is true, this will be the number of packets dropped
// during the lifetime of the server. This may overflow if enough packets
// are dropped.
uint32 packets_dropped_;
// True if the kernel supports SO_RXQ_OVFL, the number of packets dropped
// because the socket would otherwise overflow.
bool overflow_supported_;
// This vector contains QUIC versions which we currently support.
// This should be ordered such that the highest supported version is the first
// element, with subsequent elements in descending order (versions can be
// skipped as necessary). We will always pick supported_versions_[0] as the
// initial version to use.
QuicVersionVector supported_versions_;
// If true, then the contents of each response will be printed to stdout
// when the stream is closed (in OnClose).
bool print_response_;
DISALLOW_COPY_AND_ASSIGN(QuicClient);
};
} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_CLIENT_H_
|