#pragma once
#include <folly/Portability.h>
#include <folly/experimental/coro/Baton.h>
#include <folly/experimental/coro/Task.h>
#include <folly/io/async/AsyncTransport.h>
#include <folly/io/async/ssl/SSLErrors.h>
#if FOLLY_HAS_COROUTINES
namespace folly {
namespace coro {
class TransportCallbackBase {
public:
explicit TransportCallbackBase(folly::AsyncTransport& transport)
: transport_{transport} {}
virtual ~TransportCallbackBase() noexcept = default;
folly::exception_wrapper& error() noexcept { return error_; }
void post() noexcept { baton_.post(); }
Task<folly::Unit> wait() {
auto cancelToken = co_await co_current_cancellation_token;
if (cancelToken.isCancellationRequested()) {
cancel();
co_yield folly::coro::co_cancelled;
}
folly::CancellationCallback cancellationCallback{
cancelToken, [this] {
this->post();
VLOG(5) << "Cancellation was called";
}};
co_await baton_;
VLOG(5) << "After baton await";
if (cancelToken.isCancellationRequested()) {
cancel();
co_yield folly::coro::co_cancelled;
}
co_return folly::unit;
}
protected:
Baton baton_;
folly::AsyncTransport& transport_;
folly::exception_wrapper error_;
void storeException(const folly::AsyncSocketException& ex) {
auto sslErr = dynamic_cast<const folly::SSLException*>(&ex);
if (sslErr) {
error_ = folly::make_exception_wrapper<folly::SSLException>(*sslErr);
} else {
error_ = folly::make_exception_wrapper<folly::AsyncSocketException>(ex);
}
}
private:
virtual void cancel() noexcept = 0;
};
}
}
#endif