/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/io/async/AsyncTransport.h>
namespace folly {
/**
* Convenience class so that AsyncTransport can be decorated without
* having to redefine every single method.
*/
template <class T>
class DecoratedAsyncTransportWrapper : public folly::AsyncTransport {
public:
explicit DecoratedAsyncTransportWrapper(typename T::UniquePtr transport)
: transport_(std::move(transport)) {
if (FOLLY_LIKELY(nullptr != transport_)) {
transport_->decoratingTransport_ = this;
}
}
const AsyncTransport* getWrappedTransport() const override {
return transport_.get();
}
// folly::AsyncTransport
ReadCallback* getReadCallback() const override {
return transport_->getReadCallback();
}
void setReadCB(folly::AsyncTransport::ReadCallback* callback) override {
transport_->setReadCB(callback);
}
void write(
folly::AsyncTransport::WriteCallback* callback,
const void* buf,
size_t bytes,
folly::WriteFlags flags = folly::WriteFlags::NONE) override {
transport_->write(callback, buf, bytes, flags);
}
void writeChain(
folly::AsyncTransport::WriteCallback* callback,
std::unique_ptr<folly::IOBuf>&& buf,
folly::WriteFlags flags = folly::WriteFlags::NONE) override {
transport_->writeChain(callback, std::move(buf), flags);
}
void writev(
folly::AsyncTransport::WriteCallback* callback,
const iovec* vec,
size_t bytes,
folly::WriteFlags flags = folly::WriteFlags::NONE) override {
transport_->writev(callback, vec, bytes, flags);
}
// folly::AsyncSocketBase
folly::EventBase* getEventBase() const override {
return transport_->getEventBase();
}
// folly::AsyncTransport
void attachEventBase(folly::EventBase* eventBase) override {
transport_->attachEventBase(eventBase);
}
void close() override { transport_->close(); }
void closeNow() override { transport_->closeNow(); }
void closeWithReset() override {
transport_->closeWithReset();
// This will likely result in 2 closeNow() calls on the decorated transport,
// but otherwise it is very easy to miss the derived class's closeNow().
closeNow();
}
bool connecting() const override { return transport_->connecting(); }
void detachEventBase() override { transport_->detachEventBase(); }
bool error() const override { return transport_->error(); }
size_t getAppBytesReceived() const override {
return transport_->getAppBytesReceived();
}
size_t getAppBytesWritten() const override {
return transport_->getAppBytesWritten();
}
void getLocalAddress(folly::SocketAddress* address) const override {
return transport_->getLocalAddress(address);
}
void getPeerAddress(folly::SocketAddress* address) const override {
return transport_->getPeerAddress(address);
}
size_t getRawBytesReceived() const override {
return transport_->getRawBytesReceived();
}
size_t getRawBytesWritten() const override {
return transport_->getRawBytesWritten();
}
uint32_t getSendTimeout() const override {
return transport_->getSendTimeout();
}
bool good() const override { return transport_->good(); }
bool isDetachable() const override { return transport_->isDetachable(); }
bool isEorTrackingEnabled() const override {
return transport_->isEorTrackingEnabled();
}
bool readable() const override { return transport_->readable(); }
bool writable() const override { return transport_->writable(); }
void setEorTracking(bool track) override {
return transport_->setEorTracking(track);
}
void setSendTimeout(uint32_t timeoutInMs) override {
transport_->setSendTimeout(timeoutInMs);
}
void shutdownWrite() override { transport_->shutdownWrite(); }
void shutdownWriteNow() override { transport_->shutdownWriteNow(); }
std::string getApplicationProtocol() const noexcept override {
return transport_->getApplicationProtocol();
}
std::string getSecurityProtocol() const override {
return transport_->getSecurityProtocol();
}
std::unique_ptr<IOBuf> getExportedKeyingMaterial(
folly::StringPiece label,
std::unique_ptr<IOBuf> context,
uint16_t length) const override {
return transport_->getExportedKeyingMaterial(
label, std::move(context), length);
}
bool isReplaySafe() const override { return transport_->isReplaySafe(); }
void setReplaySafetyCallback(
folly::AsyncTransport::ReplaySafetyCallback* callback) override {
transport_->setReplaySafetyCallback(callback);
}
const AsyncTransportCertificate* getPeerCertificate() const override {
return transport_->getPeerCertificate();
}
void dropPeerCertificate() noexcept override {
transport_->dropPeerCertificate();
}
const AsyncTransportCertificate* getSelfCertificate() const override {
return transport_->getSelfCertificate();
}
void dropSelfCertificate() noexcept override {
transport_->dropSelfCertificate();
}
bool setZeroCopy(bool enable) override {
return transport_->setZeroCopy(enable);
}
bool getZeroCopy() const override { return transport_->getZeroCopy(); }
void setZeroCopyEnableFunc(ZeroCopyEnableFunc func) override {
transport_->setZeroCopyEnableFunc(func);
}
AsyncTransport::UniquePtr tryExchangeWrappedTransport(
AsyncTransport::UniquePtr& transport) override {
if (transport_) {
transport_->decoratingTransport_ = nullptr;
}
if (transport) {
transport->decoratingTransport_ = this;
}
return std::exchange(transport_, std::move(transport));
}
void destroy() override {
if (transport_) {
transport_->decoratingTransport_ = nullptr;
}
folly::AsyncTransport::destroy();
}
protected:
~DecoratedAsyncTransportWrapper() override {}
typename T::UniquePtr transport_;
};
} // namespace folly