+void AsyncSocket::setErrMessageCB(ErrMessageCallback* callback) {
+ VLOG(6) << "AsyncSocket::setErrMessageCB() this=" << this
+ << ", fd=" << fd_ << ", callback=" << callback
+ << ", state=" << state_;
+
+ // Short circuit if callback is the same as the existing errMessageCallback_.
+ if (callback == errMessageCallback_) {
+ return;
+ }
+
+ if (!msgErrQueueSupported) {
+ // Per-socket error message queue is not supported on this platform.
+ return invalidState(callback);
+ }
+
+ DestructorGuard dg(this);
+ eventBase_->dcheckIsInEventBaseThread();
+
+ if (callback == nullptr) {
+ // We should be able to reset the callback regardless of the
+ // socket state. It's important to have a reliable callback
+ // cancellation mechanism.
+ errMessageCallback_ = callback;
+ return;
+ }
+
+ switch ((StateEnum)state_) {
+ case StateEnum::CONNECTING:
+ case StateEnum::FAST_OPEN:
+ case StateEnum::ESTABLISHED: {
+ errMessageCallback_ = callback;
+ return;
+ }
+ case StateEnum::CLOSED:
+ case StateEnum::ERROR:
+ // We should never reach here. SHUT_READ should always be set
+ // if we are in STATE_CLOSED or STATE_ERROR.
+ assert(false);
+ return invalidState(callback);
+ case StateEnum::UNINIT:
+ // We do not allow setReadCallback() to be called before we start
+ // connecting.
+ return invalidState(callback);
+ }
+
+ // We don't put a default case in the switch statement, so that the compiler
+ // will warn us to update the switch statement if a new state is added.
+ return invalidState(callback);
+}
+
+AsyncSocket::ErrMessageCallback* AsyncSocket::getErrMessageCallback() const {
+ return errMessageCallback_;
+}
+
+void AsyncSocket::setSendMsgParamCB(SendMsgParamsCallback* callback) {
+ sendMsgParamCallback_ = callback;
+}
+
+AsyncSocket::SendMsgParamsCallback* AsyncSocket::getSendMsgParamsCB() const {
+ return sendMsgParamCallback_;
+}
+