X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fio%2Fasync%2FAsyncSocket.h;h=f8aa27f6019fa4955b6d90e4af789a42fcc08e86;hb=96791c4516497b4ea2ad08af12e4267bd1c4e796;hp=54b37705ae9b5879107485756fea1ed7df5f02e7;hpb=4aa405ec8db137b29d403aa204a91ed50aab5bb4;p=folly.git diff --git a/folly/io/async/AsyncSocket.h b/folly/io/async/AsyncSocket.h index 54b37705..f8aa27f6 100644 --- a/folly/io/async/AsyncSocket.h +++ b/folly/io/async/AsyncSocket.h @@ -139,6 +139,77 @@ class AsyncSocket : virtual public AsyncTransportWrapper { virtual void errMessageError(const AsyncSocketException& ex) noexcept = 0; }; + class SendMsgParamsCallback { + public: + virtual ~SendMsgParamsCallback() = default; + + /** + * getFlags() will be invoked to retrieve the desired flags to be passed + * to ::sendmsg() system call. This method was intentionally declared + * non-virtual, so there is no way to override it. Instead feel free to + * override getFlagsImpl(flags, defaultFlags) method instead, and enjoy + * the convenience of defaultFlags passed there. + * + * @param flags Write flags requested for the given write operation + */ + int getFlags(folly::WriteFlags flags) noexcept { + return getFlagsImpl(flags, getDefaultFlags(flags)); + } + + /** + * getAncillaryData() will be invoked to initialize ancillary data + * buffer referred by "msg_control" field of msghdr structure passed to + * ::sendmsg() system call. The function assumes that the size of buffer + * is not smaller than the value returned by getAncillaryDataSize() method + * for the same combination of flags. + * + * @param flags Write flags requested for the given write operation + * @param data Pointer to ancillary data buffer to initialize. + */ + virtual void getAncillaryData( + folly::WriteFlags /*flags*/, + void* /*data*/) noexcept {} + + /** + * getAncillaryDataSize() will be invoked to retrieve the size of + * ancillary data buffer which should be passed to ::sendmsg() system call + * + * @param flags Write flags requested for the given write operation + */ + virtual uint32_t getAncillaryDataSize(folly::WriteFlags /*flags*/) + noexcept { + return 0; + } + + static const size_t maxAncillaryDataSize{0x5000}; + + private: + /** + * getFlagsImpl() will be invoked by getFlags(folly::WriteFlags flags) + * method to retrieve the flags to be passed to ::sendmsg() system call. + * SendMsgParamsCallback::getFlags() is calling this method, and returns + * its results directly to the caller in AsyncSocket. + * Classes inheriting from SendMsgParamsCallback are welcome to override + * this method to force SendMsgParamsCallback to return its own set + * of flags. + * + * @param flags Write flags requested for the given write operation + * @param defaultflags A set of message flags returned by getDefaultFlags() + * method for the given "flags" mask. + */ + virtual int getFlagsImpl(folly::WriteFlags /*flags*/, int defaultFlags) { + return defaultFlags; + } + + /** + * getDefaultFlags() will be invoked by getFlags(folly::WriteFlags flags) + * to retrieve the default set of flags, and pass them to getFlagsImpl(...) + * + * @param flags Write flags requested for the given write operation + */ + int getDefaultFlags(folly::WriteFlags flags) noexcept; + }; + explicit AsyncSocket(); /** * Create a new unconnected AsyncSocket. @@ -189,6 +260,14 @@ class AsyncSocket : virtual public AsyncTransportWrapper { */ AsyncSocket(EventBase* evb, int fd); + /** + * Create an AsyncSocket from a different, already connected AsyncSocket. + * + * Similar to AsyncSocket(evb, fd) when fd was previously owned by an + * AsyncSocket. + */ + explicit AsyncSocket(AsyncSocket::UniquePtr); + /** * Helper function to create a shared_ptr. * @@ -264,6 +343,10 @@ class AsyncSocket : virtual public AsyncTransportWrapper { * error. The AsyncSocket may no longer be used after the file descriptor * has been extracted. * + * This method should be used with care as the resulting fd is not guaranteed + * to perfectly reflect the state of the AsyncSocket (security state, + * pre-received data, etc.). + * * Returns the file descriptor. The caller assumes ownership of the * descriptor, and it will not be closed when the AsyncSocket is destroyed. */ @@ -390,14 +473,28 @@ class AsyncSocket : virtual public AsyncTransportWrapper { * ) * */ - void setErrMessageCB(ErrMessageCallback* callback); + virtual void setErrMessageCB(ErrMessageCallback* callback); /** * Get a pointer to ErrMessageCallback implementation currently * registered with this socket. * */ - ErrMessageCallback* getErrMessageCallback() const; + virtual ErrMessageCallback* getErrMessageCallback() const; + + /** + * Set a pointer to SendMsgParamsCallback implementation which + * will be used to form ::sendmsg() system call parameters + * + */ + virtual void setSendMsgParamCB(SendMsgParamsCallback* callback); + + /** + * Get a pointer to SendMsgParamsCallback implementation currently + * registered with this socket. + * + */ + virtual SendMsgParamsCallback* getSendMsgParamsCB() const; // Read and write methods void setReadCB(ReadCallback* callback) override; @@ -601,8 +698,51 @@ class AsyncSocket : virtual public AsyncTransportWrapper { return setsockopt(fd_, level, optname, optval, sizeof(T)); } - virtual void setPeek(bool peek) { - peek_ = peek; + /** + * Virtual method for reading a socket option returning integer + * value, which is the most typical case. Convenient for overriding + * and mocking. + * + * @param level same as the "level" parameter in getsockopt(). + * @param optname same as the "optname" parameter in getsockopt(). + * @param optval same as "optval" parameter in getsockopt(). + * @param optlen same as "optlen" parameter in getsockopt(). + * @return same as the return value of getsockopt(). + */ + virtual int + getSockOptVirtual(int level, int optname, void* optval, socklen_t* optlen) { + return getsockopt(fd_, level, optname, optval, optlen); + } + + /** + * Virtual method for setting a socket option accepting integer + * value, which is the most typical case. Convenient for overriding + * and mocking. + * + * @param level same as the "level" parameter in setsockopt(). + * @param optname same as the "optname" parameter in setsockopt(). + * @param optval same as "optval" parameter in setsockopt(). + * @param optlen same as "optlen" parameter in setsockopt(). + * @return same as the return value of setsockopt(). + */ + virtual int setSockOptVirtual( + int level, + int optname, + void const* optval, + socklen_t optlen) { + return setsockopt(fd_, level, optname, optval, optlen); + } + + /** + * Set pre-received data, to be returned to read callback before any data + * from the socket. + */ + virtual void setPreReceivedData(std::unique_ptr data) { + if (preReceivedData_) { + preReceivedData_->prependChain(std::move(data)); + } else { + preReceivedData_ = std::move(data); + } } /** @@ -990,6 +1130,8 @@ class AsyncSocket : virtual public AsyncTransportWrapper { ConnectCallback* connectCallback_; ///< ConnectCallback ErrMessageCallback* errMessageCallback_; ///< TimestampCallback + SendMsgParamsCallback* ///< Callback for retreaving + sendMsgParamCallback_; ///< ::sendmsg() parameters ReadCallback* readCallback_; ///< ReadCallback WriteRequest* writeReqHead_; ///< Chain of WriteRequests WriteRequest* writeReqTail_; ///< End of WriteRequest chain @@ -998,9 +1140,11 @@ class AsyncSocket : virtual public AsyncTransportWrapper { size_t appBytesWritten_; ///< Num of bytes written to socket bool isBufferMovable_{false}; - bool peek_{false}; // Peek bytes. + // Pre-received data, to be returned to read callback before any data from the + // socket. + std::unique_ptr preReceivedData_; - int8_t readErr_{READ_NO_ERROR}; ///< The read error encountered, if any. + int8_t readErr_{READ_NO_ERROR}; ///< The read error encountered, if any std::chrono::steady_clock::time_point connectStartTime_; std::chrono::steady_clock::time_point connectEndTime_;