void errMessage(const cmsghdr& cmsg) noexcept override {
if (cmsg.cmsg_level == SOL_SOCKET &&
cmsg.cmsg_type == SCM_TIMESTAMPING) {
- gotTimestamp_ = true;
+ gotTimestamp_++;
+ checkResetCallback();
} else if (
(cmsg.cmsg_level == SOL_IP && cmsg.cmsg_type == IP_RECVERR) ||
(cmsg.cmsg_level == SOL_IPV6 && cmsg.cmsg_type == IPV6_RECVERR)) {
- gotByteSeq_ = true;
+ gotByteSeq_++;
+ checkResetCallback();
}
}
exception_ = ex;
}
+ void checkResetCallback() noexcept {
+ if (socket_ != nullptr && resetAfter_ != -1 &&
+ gotTimestamp_ + gotByteSeq_ == resetAfter_) {
+ socket_->setErrMessageCB(nullptr);
+ }
+ }
+
+ folly::AsyncSocket* socket_{nullptr};
folly::AsyncSocketException exception_;
- bool gotTimestamp_{false};
- bool gotByteSeq_{false};
+ int gotTimestamp_{0};
+ int gotByteSeq_{0};
+ int resetAfter_{-1};
};
class TestSendMsgParamsCallback :
SOF_TIMESTAMPING_OPT_CMSG = (1 << 10),
SOF_TIMESTAMPING_OPT_TSONLY = (1 << 11),
};
+
TEST(AsyncSocketTest, ErrMessageCallback) {
TestServer server;
ASSERT_EQ(socket->getErrMessageCallback(),
static_cast<folly::AsyncSocket::ErrMessageCallback*>(&errMsgCB));
+ errMsgCB.socket_ = socket.get();
+ errMsgCB.resetAfter_ = 3;
+
// Enable timestamp notifications
ASSERT_GT(socket->getFd(), 0);
int flags = SOF_TIMESTAMPING_OPT_ID
// write()
std::vector<uint8_t> wbuf(128, 'a');
WriteCallback wcb;
- socket->write(&wcb, wbuf.data(), wbuf.size());
+ // Send two packets to get two EOM notifications
+ socket->write(&wcb, wbuf.data(), wbuf.size() / 2);
+ socket->write(&wcb, wbuf.data() + wbuf.size() / 2, wbuf.size() / 2);
// Accept the connection.
std::shared_ptr<BlockingSocket> acceptedSocket = server.accept();
// Check for the timestamp notifications.
ASSERT_EQ(errMsgCB.exception_.type_, folly::AsyncSocketException::UNKNOWN);
- ASSERT_TRUE(errMsgCB.gotByteSeq_);
- ASSERT_TRUE(errMsgCB.gotTimestamp_);
+ ASSERT_GT(errMsgCB.gotByteSeq_, 0);
+ ASSERT_GT(errMsgCB.gotTimestamp_, 0);
+ ASSERT_EQ(
+ errMsgCB.gotByteSeq_ + errMsgCB.gotTimestamp_, errMsgCB.resetAfter_);
}
#endif // MSG_ERRQUEUE