mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-24 04:01:07 +03:00
Summary: instead of the folly one Reviewed By: sharmafb Differential Revision: D80305359 fbshipit-source-id: 02f4780ed32874e00bcea13b5af4103560d7d205
681 lines
22 KiB
C++
681 lines
22 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include <errno.h> // For errno
|
|
#include <folly/io/async/AsyncSocketException.h>
|
|
#include <quic/QuicException.h> // For QuicError, QuicErrorCode, TransportErrorCode
|
|
#include <quic/common/Expected.h>
|
|
#include <quic/common/StringUtils.h>
|
|
#include <quic/common/udpsocket/FollyQuicAsyncUDPSocket.h>
|
|
#include <memory>
|
|
|
|
namespace quic {
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::init(
|
|
sa_family_t family) {
|
|
try {
|
|
follySocket_.init(family);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly init failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::bind(
|
|
const folly::SocketAddress& address) {
|
|
try {
|
|
follySocket_.bind(address);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly bind failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] bool FollyQuicAsyncUDPSocket::isBound() const {
|
|
return follySocket_.isBound();
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::connect(
|
|
const folly::SocketAddress& address) {
|
|
try {
|
|
follySocket_.connect(address);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly connect failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::close() {
|
|
try {
|
|
follySocket_.close();
|
|
readCallbackWrapper_.reset(); // Ensure wrapper is cleared on close
|
|
errCallbackWrapper_.reset();
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly close failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::resumeRead(ReadCallback* callback) {
|
|
try {
|
|
// TODO: We could skip this check and rely on the one in AsyncUDPSocket
|
|
CHECK(!readCallbackWrapper_) << "Already registered a read callback";
|
|
readCallbackWrapper_ =
|
|
std::make_unique<FollyReadCallbackWrapper>(callback, this);
|
|
follySocket_.resumeRead(readCallbackWrapper_.get());
|
|
// TODO: This should return Expected<Unit, QuicError>
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// TODO: Convert to QuicError and return quic::make_unexpected
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::resumeRead failed: " << ex.what();
|
|
throw; // Re-throw for now until signature is updated
|
|
}
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::pauseRead() {
|
|
follySocket_.pauseRead();
|
|
readCallbackWrapper_.reset();
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setErrMessageCallback(
|
|
ErrMessageCallback* callback) {
|
|
try {
|
|
if (errCallbackWrapper_) {
|
|
errCallbackWrapper_.reset();
|
|
}
|
|
if (callback) {
|
|
errCallbackWrapper_ = std::make_unique<FollyErrCallbackWrapper>(callback);
|
|
follySocket_.setErrMessageCallback(errCallbackWrapper_.get());
|
|
} else {
|
|
follySocket_.setErrMessageCallback(nullptr);
|
|
}
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly setErrMessageCallback failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
ssize_t FollyQuicAsyncUDPSocket::write(
|
|
const folly::SocketAddress& address,
|
|
const struct iovec* vec,
|
|
size_t iovec_len) {
|
|
try {
|
|
folly::AsyncUDPSocket::WriteOptions writeOptions(
|
|
0 /*gsoVal*/, false /* zerocopyVal*/);
|
|
return follySocket_.writev(address, vec, iovec_len, writeOptions);
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Log the error, set errno, return -1 for syscall-like behavior
|
|
errno = ex.getErrno();
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::write failed: " << ex.what();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int FollyQuicAsyncUDPSocket::writem(
|
|
folly::Range<folly::SocketAddress const*> addrs,
|
|
iovec* iov,
|
|
size_t* numIovecsInBuffer,
|
|
size_t count) {
|
|
try {
|
|
return follySocket_.writemv(addrs, iov, numIovecsInBuffer, count);
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Log the error, set errno, return -1 for syscall-like behavior
|
|
errno = ex.getErrno();
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::writem failed: " << ex.what();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ssize_t FollyQuicAsyncUDPSocket::writeGSO(
|
|
const folly::SocketAddress& address,
|
|
const struct iovec* vec,
|
|
size_t iovec_len,
|
|
WriteOptions options) {
|
|
try {
|
|
folly::AsyncUDPSocket::WriteOptions follyOptions(
|
|
options.gso, options.zerocopy);
|
|
follyOptions.txTime = options.txTime;
|
|
return follySocket_.writev(address, vec, iovec_len, follyOptions);
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Log the error, set errno, return -1 for syscall-like behavior
|
|
errno = ex.getErrno();
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::writeGSO failed: " << ex.what();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int FollyQuicAsyncUDPSocket::writemGSO(
|
|
folly::Range<folly::SocketAddress const*> addrs,
|
|
const BufPtr* bufs,
|
|
size_t count,
|
|
const WriteOptions* options) {
|
|
try {
|
|
std::vector<folly::AsyncUDPSocket::WriteOptions> follyOptions(count);
|
|
for (size_t i = 0; i < count; ++i) {
|
|
follyOptions[i].gso = options[i].gso;
|
|
follyOptions[i].zerocopy = options[i].zerocopy;
|
|
follyOptions[i].txTime = options[i].txTime;
|
|
}
|
|
return follySocket_.writemGSO(addrs, bufs, count, follyOptions.data());
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Log the error, set errno, return -1 for syscall-like behavior
|
|
errno = ex.getErrno();
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::writemGSO(IOBuf) failed: "
|
|
<< ex.what();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int FollyQuicAsyncUDPSocket::writemGSO(
|
|
folly::Range<folly::SocketAddress const*> addrs,
|
|
iovec* iov,
|
|
size_t* numIovecsInBuffer,
|
|
size_t count,
|
|
const WriteOptions* options) {
|
|
try {
|
|
std::vector<folly::AsyncUDPSocket::WriteOptions> follyOptions(count);
|
|
for (size_t i = 0; i < count; ++i) {
|
|
follyOptions[i].gso = options[i].gso;
|
|
follyOptions[i].zerocopy = options[i].zerocopy;
|
|
follyOptions[i].txTime = options[i].txTime;
|
|
}
|
|
return follySocket_.writemGSOv(
|
|
addrs, iov, numIovecsInBuffer, count, follyOptions.data());
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Log the error, set errno, return -1 for syscall-like behavior
|
|
errno = ex.getErrno();
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::writemGSO(iovec) failed: "
|
|
<< ex.what();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ssize_t FollyQuicAsyncUDPSocket::recvmsg(struct msghdr* msg, int flags) {
|
|
try {
|
|
return follySocket_.recvmsg(msg, flags);
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Log the error, set errno, return -1 for syscall-like behavior
|
|
errno = ex.getErrno();
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::recvmsg failed: " << ex.what();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int FollyQuicAsyncUDPSocket::recvmmsg(
|
|
struct mmsghdr* msgvec,
|
|
unsigned int vlen,
|
|
unsigned int flags,
|
|
struct timespec* timeout) {
|
|
try {
|
|
return follySocket_.recvmmsg(msgvec, vlen, flags, timeout);
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Log the error, set errno, return -1 for syscall-like behavior
|
|
errno = ex.getErrno();
|
|
LOG(ERROR) << "FollyQuicAsyncUDPSocket::recvmmsg failed: " << ex.what();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
quic::Expected<int, QuicError> FollyQuicAsyncUDPSocket::getGSO() {
|
|
try {
|
|
return follySocket_.getGSO();
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly getGSO failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
LOG(ERROR) << "getGSO failed: " << errorMsg;
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<int, QuicError> FollyQuicAsyncUDPSocket::getGRO() {
|
|
try {
|
|
return follySocket_.getGRO();
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly getGRO failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setGRO(bool bVal) {
|
|
try {
|
|
if (follySocket_.setGRO(bVal)) {
|
|
return {};
|
|
} else {
|
|
// Folly's setGRO returns bool, not throwing. Assume failure means error.
|
|
int errnoCopy = errno; // Capture errno immediately after failure
|
|
std::string errorMsg = "Folly setGRO failed";
|
|
if (errnoCopy != 0) {
|
|
errorMsg += ": " + quic::errnoStr(errnoCopy);
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
// Catch just in case future folly versions throw
|
|
std::string errorMsg = "Folly setGRO exception: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setRecvTos(
|
|
bool recvTos) {
|
|
try {
|
|
follySocket_.setRecvTos(recvTos);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly setRecvTos failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<bool, QuicError> FollyQuicAsyncUDPSocket::getRecvTos() {
|
|
try {
|
|
return follySocket_.getRecvTos();
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly getRecvTos failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setTosOrTrafficClass(
|
|
uint8_t tos) {
|
|
try {
|
|
follySocket_.setTosOrTrafficClass(tos);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly setTosOrTrafficClass failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] quic::Expected<folly::SocketAddress, QuicError>
|
|
FollyQuicAsyncUDPSocket::address() const {
|
|
try {
|
|
return follySocket_.address();
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly address() failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] const folly::SocketAddress& FollyQuicAsyncUDPSocket::addressRef()
|
|
const {
|
|
try {
|
|
return follySocket_.address();
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly address() failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
LOG(FATAL) << errorMsg;
|
|
}
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::attachEventBase( // Keep void, attach/detach
|
|
// usually don't throw socket
|
|
// errors
|
|
std::shared_ptr<QuicEventBase> evb) {
|
|
CHECK(evb != nullptr);
|
|
std::shared_ptr<FollyQuicEventBase> follyEvb =
|
|
std::dynamic_pointer_cast<FollyQuicEventBase>(evb);
|
|
CHECK(follyEvb != nullptr);
|
|
evb_ = follyEvb;
|
|
follySocket_.attachEventBase(follyEvb->getBackingEventBase());
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::detachEventBase() { // Keep void
|
|
follySocket_.detachEventBase();
|
|
}
|
|
|
|
[[nodiscard]] std::shared_ptr<QuicEventBase>
|
|
FollyQuicAsyncUDPSocket::getEventBase() const {
|
|
if (evb_) {
|
|
CHECK_EQ(evb_->getBackingEventBase(), follySocket_.getEventBase());
|
|
}
|
|
return evb_;
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setCmsgs(
|
|
const folly::SocketCmsgMap& cmsgs) {
|
|
try {
|
|
follySocket_.setCmsgs(cmsgs);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly setCmsgs failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::appendCmsgs(
|
|
const folly::SocketCmsgMap& cmsgs) {
|
|
try {
|
|
follySocket_.appendCmsgs(cmsgs);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly appendCmsgs failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setAdditionalCmsgsFunc(
|
|
std::function<Optional<folly::SocketCmsgMap>()>&& additionalCmsgsFunc) {
|
|
try {
|
|
auto adapter = [originalFunc = std::move(additionalCmsgsFunc)]()
|
|
-> folly::Optional<folly::SocketCmsgMap> {
|
|
if (!originalFunc) {
|
|
return folly::none;
|
|
}
|
|
|
|
auto result = originalFunc();
|
|
if (result.has_value()) {
|
|
return folly::Optional<folly::SocketCmsgMap>(std::move(result.value()));
|
|
} else {
|
|
return folly::none;
|
|
}
|
|
};
|
|
|
|
follySocket_.setAdditionalCmsgsFunc(std::move(adapter));
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly setAdditionalCmsgsFunc failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<int, QuicError> FollyQuicAsyncUDPSocket::getTimestamping() {
|
|
try {
|
|
return follySocket_.getTimestamping();
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly getTimestamping failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setReuseAddr(
|
|
bool reuseAddr) {
|
|
try {
|
|
follySocket_.setReuseAddr(reuseAddr);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly setReuseAddr failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setDFAndTurnOffPMTU() {
|
|
try {
|
|
follySocket_.setDFAndTurnOffPMTU();
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly setDFAndTurnOffPMTU failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::applyOptions(
|
|
const folly::SocketOptionMap& options,
|
|
folly::SocketOptionKey::ApplyPos pos) {
|
|
try {
|
|
follySocket_.applyOptions(options, pos);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly applyOptions failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setReusePort(
|
|
bool reusePort) {
|
|
try {
|
|
follySocket_.setReusePort(reusePort);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg =
|
|
"Folly setReusePort failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setRcvBuf(int rcvBuf) {
|
|
try {
|
|
follySocket_.setRcvBuf(rcvBuf);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly setRcvBuf failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setSndBuf(int sndBuf) {
|
|
try {
|
|
follySocket_.setSndBuf(sndBuf);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly setSndBuf failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
quic::Expected<void, QuicError> FollyQuicAsyncUDPSocket::setFD(
|
|
int fd,
|
|
FDOwnership ownership) {
|
|
folly::AsyncUDPSocket::FDOwnership follyOwnership;
|
|
switch (ownership) {
|
|
case FDOwnership::OWNS:
|
|
follyOwnership = folly::AsyncUDPSocket::FDOwnership::OWNS;
|
|
break;
|
|
case FDOwnership::SHARED:
|
|
follyOwnership = folly::AsyncUDPSocket::FDOwnership::SHARED;
|
|
break;
|
|
}
|
|
try {
|
|
follySocket_.setFD(folly::NetworkSocket::fromFd(fd), follyOwnership);
|
|
return {};
|
|
} catch (const folly::AsyncSocketException& ex) {
|
|
std::string errorMsg = "Folly setFD failed: " + std::string(ex.what());
|
|
if (ex.getErrno() != 0) {
|
|
errorMsg += ": " + quic::errnoStr(ex.getErrno());
|
|
}
|
|
return quic::make_unexpected(QuicError(
|
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
|
std::move(errorMsg)));
|
|
}
|
|
}
|
|
|
|
int FollyQuicAsyncUDPSocket::getFD() {
|
|
return follySocket_.getNetworkSocket().toFd();
|
|
}
|
|
|
|
folly::AsyncUDPSocket& FollyQuicAsyncUDPSocket::getFollySocket() {
|
|
return follySocket_;
|
|
}
|
|
|
|
// FollyReadCallbackWrapper implementation
|
|
|
|
void FollyQuicAsyncUDPSocket::FollyReadCallbackWrapper::getReadBuffer(
|
|
void** buf,
|
|
size_t* len) noexcept {
|
|
return wrappedReadCallback_->getReadBuffer(buf, len);
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::FollyReadCallbackWrapper::onDataAvailable(
|
|
const folly::SocketAddress& client,
|
|
size_t len,
|
|
bool truncated,
|
|
folly::AsyncUDPSocket::ReadCallback::OnDataAvailableParams
|
|
params) noexcept {
|
|
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
|
|
// TODO: Can this be moved to a static compile time check?
|
|
CHECK_EQ(
|
|
QuicAsyncUDPSocket::ReadCallback::OnDataAvailableParams::kCmsgSpace,
|
|
folly::AsyncUDPSocket::ReadCallback::OnDataAvailableParams::kCmsgSpace);
|
|
#endif
|
|
QuicAsyncUDPSocket::ReadCallback::OnDataAvailableParams localParams;
|
|
localParams.gro = params.gro;
|
|
localParams.tos = params.tos;
|
|
if (params.ts) {
|
|
localParams.ts.emplace(*params.ts);
|
|
}
|
|
|
|
return wrappedReadCallback_->onDataAvailable(
|
|
client, len, truncated, localParams);
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::FollyReadCallbackWrapper::onNotifyDataAvailable(
|
|
folly::AsyncUDPSocket&) noexcept {
|
|
CHECK(parentSocket_ != nullptr);
|
|
return wrappedReadCallback_->onNotifyDataAvailable(*parentSocket_);
|
|
}
|
|
|
|
bool FollyQuicAsyncUDPSocket::FollyReadCallbackWrapper::shouldOnlyNotify() {
|
|
return wrappedReadCallback_->shouldOnlyNotify();
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::FollyReadCallbackWrapper::onReadError(
|
|
const folly::AsyncSocketException& ex) noexcept {
|
|
return wrappedReadCallback_->onReadError(ex);
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::FollyReadCallbackWrapper::
|
|
onReadClosed() noexcept {
|
|
return wrappedReadCallback_->onReadClosed();
|
|
}
|
|
|
|
// FollyErrMessageCallbackWrapper implementation
|
|
void FollyQuicAsyncUDPSocket::FollyErrCallbackWrapper::errMessage(
|
|
const cmsghdr& cmsg) noexcept {
|
|
return wrappedErrorCallback_->errMessage(cmsg);
|
|
}
|
|
|
|
void FollyQuicAsyncUDPSocket::FollyErrCallbackWrapper::errMessageError(
|
|
const folly::AsyncSocketException& ex) noexcept {
|
|
return wrappedErrorCallback_->errMessageError(ex);
|
|
}
|
|
|
|
} // namespace quic
|