blob: e5e1b0180e26ec4be10dd202782ca7e2488da306 [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 "lib/fsl/socket/blocking_drain.h"
#include <vector>
#include <lib/fit/function.h>
#include <lib/zx/socket.h>
#include "lib/fxl/logging.h"
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) {
FXL_LOG(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 {
FXL_LOG(ERROR) << "Unhandled error " << result << " in BlockingDrainFrom";
// Some other error occurred.
return false;
}
}
}
} // namespace fsl