blob: f6e0ecdfd7d63de8b8170cc1fc1152b5db51c739 [file] [log] [blame]
// Copyright 2016 The Fuchsia 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 "src/lib/fsl/socket/blocking_drain.h"
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/socket.h>
#include <vector>
namespace fsl {
bool BlockingDrainFrom(zx::socket source,
fit::function<size_t(const void*, uint32_t)> write_bytes) {
std::vector<char> buffer(64 * 1024);
for (;;) {
size_t bytes_read;
zx_status_t result = source.read(0, buffer.data(), buffer.size(), &bytes_read);
if (result == ZX_OK) {
size_t bytes_written = write_bytes(buffer.data(), bytes_read);
if (bytes_written < bytes_read) {
FX_LOGS(ERROR) << "write_bytes callback wrote fewer bytes (" << bytes_written
<< ") than expected (" << bytes_read
<< ") in BlockingDrainFrom (socket closed? out of disk "
"space?)";
return false;
}
} else if (result == ZX_ERR_SHOULD_WAIT) {
result = source.wait_one(ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, zx::time::infinite(),
nullptr);
if (result != ZX_OK) {
// If the socket was closed, then treat as EOF.
return result == ZX_ERR_PEER_CLOSED;
}
} else if (result == ZX_ERR_PEER_CLOSED) {
// If the socket was closed, then treat as EOF.
return true;
} else {
FX_LOGS(ERROR) << "Unhandled error " << result << " in BlockingDrainFrom";
// Some other error occurred.
return false;
}
}
}
} // namespace fsl