Chromium Code Reviews| Index: net/udp/fuzzed_datagram_client_socket.cc |
| diff --git a/net/udp/fuzzed_datagram_client_socket.cc b/net/udp/fuzzed_datagram_client_socket.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..800371970f6c44a415120fdc0a48f62afe147629 |
| --- /dev/null |
| +++ b/net/udp/fuzzed_datagram_client_socket.cc |
| @@ -0,0 +1,193 @@ |
| +// Copyright 2016 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. |
| + |
| +#include "net/udp/fuzzed_datagram_client_socket.h" |
| + |
| +#include <algorithm> |
| + |
| +#include "base/bind.h" |
| +#include "base/location.h" |
| +#include "base/logging.h" |
| +#include "base/strings/string_piece.h" |
| +#include "base/thread_task_runner_handle.h" |
| +#include "net/base/fuzzed_data_provider.h" |
| +#include "net/base/io_buffer.h" |
| +#include "net/base/ip_address.h" |
| +#include "net/base/net_errors.h" |
| + |
| +namespace net { |
| + |
| +// Subset of network errors that can occur on each operation. Less clear cut |
| +// than TCP errors, so some of these may not actually be possible. |
| +const Error kConnectErrors[] = {ERR_FAILED, ERR_ADDRESS_UNREACHABLE, |
| + ERR_ACCESS_DENIED}; |
| +const Error kReadErrors[] = {ERR_FAILED, ERR_ADDRESS_UNREACHABLE}; |
| +const Error kWriteErrors[] = {ERR_FAILED, ERR_ADDRESS_UNREACHABLE, |
| + ERR_MSG_TOO_BIG}; |
| + |
| +FuzzedDatagramClientSocket::FuzzedDatagramClientSocket( |
| + FuzzedDataProvider* data_provider) |
| + : data_provider_(data_provider), weak_factory_(this) {} |
| + |
| +FuzzedDatagramClientSocket::~FuzzedDatagramClientSocket() {} |
| + |
| +int FuzzedDatagramClientSocket::Connect(const IPEndPoint& address) { |
| + CHECK(!connected_); |
| + |
| + // Decide if the connect attempt succeeds. |
| + if (data_provider_->ConsumeBool()) { |
| + connected_ = true; |
| + remote_address_ = address; |
| + return OK; |
| + } |
| + |
| + // On failure, return a random connect error. |
| + return kConnectErrors[data_provider_->ConsumeValueInRange( |
|
eroman
2016/05/17 23:01:34
Might be handy to have a templetized helper that s
mmenke
2016/05/19 19:09:46
Done. I wasn't sure how to do this, or I would ha
|
| + 0, arraysize(kConnectErrors) - 1)]; |
| +} |
| + |
| +int FuzzedDatagramClientSocket::ConnectUsingNetwork( |
| + NetworkChangeNotifier::NetworkHandle network, |
| + const IPEndPoint& address) { |
| + CHECK(!connected_); |
| + return ERR_NOT_IMPLEMENTED; |
| +} |
| + |
| +int FuzzedDatagramClientSocket::FuzzedDatagramClientSocket:: |
| + ConnectUsingDefaultNetwork(const IPEndPoint& address) { |
| + CHECK(!connected_); |
| + return ERR_NOT_IMPLEMENTED; |
| +} |
| + |
| +NetworkChangeNotifier::NetworkHandle |
| +FuzzedDatagramClientSocket::GetBoundNetwork() const { |
| + return NetworkChangeNotifier::kInvalidNetworkHandle; |
| +} |
| + |
| +void FuzzedDatagramClientSocket::Close() { |
| + connected_ = false; |
| + read_pending_ = false; |
| + write_pending_ = false; |
| + remote_address_ = IPEndPoint(); |
| + weak_factory_.InvalidateWeakPtrs(); |
| +} |
| + |
| +int FuzzedDatagramClientSocket::GetPeerAddress(IPEndPoint* address) const { |
| + if (!connected_) |
| + return ERR_SOCKET_NOT_CONNECTED; |
| + *address = remote_address_; |
| + return OK; |
| +} |
| + |
| +int FuzzedDatagramClientSocket::GetLocalAddress(IPEndPoint* address) const { |
| + if (!connected_) |
| + return ERR_SOCKET_NOT_CONNECTED; |
| + *address = IPEndPoint(IPAddress(1, 2, 3, 4), 43210); |
| + return OK; |
| +} |
| + |
| +const BoundNetLog& FuzzedDatagramClientSocket::NetLog() const { |
| + return net_log_; |
| +} |
| + |
| +int FuzzedDatagramClientSocket::Read(IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + CHECK(!callback.is_null()); |
| + CHECK_GT(buf_len, 0); |
| + CHECK(!read_pending_); |
| + |
| + // Normally calling this on disconnected sockets is allowed, but code really |
| + // shouldn't be doing this. If it is, it's best to figure out why, and fix |
| + // it. Note that |connected_| is only set to false on calls to Close(), not on |
| + // errors. |
| + CHECK(connected_); |
| + |
| + // Get contents of response. |
| + base::StringPiece data(data_provider_->ConsumeBytes( |
| + data_provider_->ConsumeValueInRange(0, buf_len))); |
| + |
| + int result; |
| + if (data.length() > 0) { |
| + // If the response is not empty, consider it a successful read. |
| + result = data.length(); |
| + std::copy(data.begin(), data.end(), buf->data()); |
| + } else { |
| + // If the response is empty, pick a random read error. |
| + result = kReadErrors[data_provider_->ConsumeValueInRange( |
| + 0, arraysize(kReadErrors) - 1)]; |
| + } |
| + |
| + // Decide if result should be returned synchronously. |
| + if (data_provider_->ConsumeBool()) |
| + return result; |
| + |
| + read_pending_ = true; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&FuzzedDatagramClientSocket::OnReadComplete, |
| + weak_factory_.GetWeakPtr(), callback, result)); |
| + return ERR_IO_PENDING; |
| +} |
| + |
| +int FuzzedDatagramClientSocket::Write(IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + CHECK(!callback.is_null()); |
| + CHECK(!write_pending_); |
| + |
| + // Normally this is allowed, but code really shouldn't be doing this - if it |
| + // is, it's best to figure out why, and fix it. |
| + CHECK(connected_); |
| + |
| + int result; |
| + // Decide if success or failure. |
| + if (data_provider_->ConsumeBool()) { |
| + // On success, everything is written. |
| + result = buf_len; |
| + } else { |
| + // On failure, pick a random write error. |
| + result = kWriteErrors[data_provider_->ConsumeValueInRange( |
| + 0, arraysize(kWriteErrors) - 1)]; |
| + } |
| + |
| + // Decide if result should be returned synchronously. |
| + if (data_provider_->ConsumeBool()) |
| + return result; |
| + |
| + write_pending_ = true; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&FuzzedDatagramClientSocket::OnWriteComplete, |
| + weak_factory_.GetWeakPtr(), callback, result)); |
| + return ERR_IO_PENDING; |
| +} |
| + |
| +int FuzzedDatagramClientSocket::SetReceiveBufferSize(int32_t size) { |
| + return OK; |
| +} |
| + |
| +int FuzzedDatagramClientSocket::SetSendBufferSize(int32_t size) { |
| + return OK; |
| +} |
| + |
| +void FuzzedDatagramClientSocket::OnReadComplete( |
| + const net::CompletionCallback& callback, |
| + int result) { |
| + CHECK(connected_); |
| + CHECK(read_pending_); |
| + |
| + read_pending_ = false; |
| + callback.Run(result); |
| +} |
| + |
| +void FuzzedDatagramClientSocket::OnWriteComplete( |
| + const net::CompletionCallback& callback, |
| + int result) { |
| + CHECK(connected_); |
| + CHECK(write_pending_); |
| + |
| + write_pending_ = false; |
| + callback.Run(result); |
| +} |
| + |
| +} // namespace net |