mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 1 | // Copyright 2016 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 | #ifndef NET_SOCKET_FUZZED_SOCKET_H |
| 6 | #define NET_SOCKET_FUZZED_SOCKET_H |
| 7 | |
| 8 | #include <stdint.h> |
| 9 | |
| 10 | #include "base/macros.h" |
| 11 | #include "base/memory/weak_ptr.h" |
| 12 | #include "base/strings/string_piece.h" |
| 13 | #include "net/base/completion_callback.h" |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 14 | #include "net/base/ip_endpoint.h" |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 15 | #include "net/base/net_errors.h" |
| 16 | #include "net/log/net_log.h" |
| 17 | #include "net/socket/stream_socket.h" |
| 18 | |
| 19 | namespace net { |
| 20 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 21 | class FuzzedDataProvider; |
| 22 | class IPEndPoint; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 23 | class IOBuffer; |
| 24 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 25 | // A StreamSocket that uses a FuzzedDataProvider to generate responses. Writes |
| 26 | // can succeed synchronously or asynchronously, can write some or all of the |
| 27 | // provided data, and can fail with several different errors. Reads can do the |
| 28 | // same, but the read data is also generated from the FuzzedDataProvider. The |
| 29 | // number of bytes written/read from a single call is currently capped at 255 |
| 30 | // bytes. |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 31 | // |
| 32 | // Reads and writes are executed independently of one another, so to guarantee |
| 33 | // the fuzzer behaves the same across repeated runs with the same input, the |
| 34 | // reads and writes must be done in a deterministic order and for a |
| 35 | // deterministic number of bytes, every time the fuzzer is run with the same |
| 36 | // data. |
| 37 | class FuzzedSocket : public StreamSocket { |
| 38 | public: |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 39 | // |data_provider| is used as to determine behavior of the FuzzedSocket. It |
| 40 | // must remain valid until after the FuzzedSocket is destroyed. |
| 41 | FuzzedSocket(FuzzedDataProvider* data_provider, net::NetLog* net_log); |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 42 | ~FuzzedSocket() override; |
| 43 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 44 | // If set to true, the socket will fuzz the result of the Connect() call. |
| 45 | // It can fail or succeed, and return synchronously or asynchronously. If |
| 46 | // false, Connect() succeeds synchronously. Defaults to false. |
| 47 | void set_fuzz_connect_result(bool fuzz_connect_result) { |
| 48 | fuzz_connect_result_ = fuzz_connect_result; |
| 49 | } |
| 50 | |
| 51 | // Sets the remote address the socket claims to be using. |
| 52 | void set_remote_address(const IPEndPoint& remote_address) { |
| 53 | remote_address_ = remote_address; |
| 54 | } |
| 55 | |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 56 | // Socket implementation: |
| 57 | int Read(IOBuffer* buf, |
| 58 | int buf_len, |
| 59 | const CompletionCallback& callback) override; |
| 60 | int Write(IOBuffer* buf, |
| 61 | int buf_len, |
| 62 | const CompletionCallback& callback) override; |
| 63 | int SetReceiveBufferSize(int32_t size) override; |
| 64 | int SetSendBufferSize(int32_t size) override; |
| 65 | |
| 66 | // StreamSocket implementation: |
| 67 | int Connect(const CompletionCallback& callback) override; |
| 68 | void Disconnect() override; |
| 69 | bool IsConnected() const override; |
| 70 | bool IsConnectedAndIdle() const override; |
| 71 | int GetPeerAddress(IPEndPoint* address) const override; |
| 72 | int GetLocalAddress(IPEndPoint* address) const override; |
| 73 | const BoundNetLog& NetLog() const override; |
| 74 | void SetSubresourceSpeculation() override; |
| 75 | void SetOmniboxSpeculation() override; |
| 76 | bool WasEverUsed() const override; |
| 77 | void EnableTCPFastOpenIfSupported() override; |
| 78 | bool WasNpnNegotiated() const override; |
| 79 | NextProto GetNegotiatedProtocol() const override; |
| 80 | bool GetSSLInfo(SSLInfo* ssl_info) override; |
| 81 | void GetConnectionAttempts(ConnectionAttempts* out) const override; |
| 82 | void ClearConnectionAttempts() override; |
| 83 | void AddConnectionAttempts(const ConnectionAttempts& attempts) override; |
| 84 | int64_t GetTotalReceivedBytes() const override; |
| 85 | |
| 86 | private: |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 87 | // Returns a net::Error that can be returned by a read or a write. Reads and |
| 88 | // writes return basically the same set of errors, at the TCP socket layer. |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 89 | Error ConsumeReadWriteErrorFromData(); |
| 90 | |
| 91 | void OnReadComplete(const CompletionCallback& callback, int result); |
| 92 | void OnWriteComplete(const CompletionCallback& callback, int result); |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 93 | void OnConnectComplete(const CompletionCallback& callback, int result); |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 94 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 95 | FuzzedDataProvider* data_provider_; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 96 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 97 | // If true, the result of the Connect() call is fuzzed - it can succeed or |
| 98 | // fail with a variety of connection errors, and it can complete synchronously |
| 99 | // or asynchronously. |
| 100 | bool fuzz_connect_result_ = false; |
| 101 | |
| 102 | bool connect_pending_ = false; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 103 | bool read_pending_ = false; |
| 104 | bool write_pending_ = false; |
| 105 | |
| 106 | // This is true when the first callback returning an error is pending in the |
| 107 | // message queue. If true, the socket acts like it's connected until that task |
| 108 | // is run (Or Disconnect() is called), and reads / writes will return the same |
| 109 | // error asynchronously, until it becomes false, at which point they'll return |
| 110 | // it synchronously. |
| 111 | bool error_pending_ = false; |
| 112 | // If this is not OK, all reads/writes will fail with this error. |
| 113 | int net_error_ = ERR_CONNECTION_CLOSED; |
| 114 | |
| 115 | int64_t total_bytes_read_ = 0; |
| 116 | int64_t total_bytes_written_ = 0; |
| 117 | |
| 118 | BoundNetLog bound_net_log_; |
| 119 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 120 | IPEndPoint remote_address_; |
| 121 | |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 122 | base::WeakPtrFactory<FuzzedSocket> weak_factory_; |
| 123 | |
| 124 | DISALLOW_COPY_AND_ASSIGN(FuzzedSocket); |
| 125 | }; |
| 126 | |
| 127 | } // namespace net |
| 128 | |
| 129 | #endif // NET_SOCKET_FUZZED_SOCKET_H |