1 #include "hmbdc/Copyright.hpp" 3 #include "hmbdc/app/Logger.hpp" 4 #include "hmbdc/tips/tcpcast/Transport.hpp" 5 #include "hmbdc/tips/tcpcast/Messages.hpp" 6 #include "hmbdc/tips/TypeTagSet.hpp" 8 #include "hmbdc/time/Time.hpp" 9 #include "hmbdc/pattern/MonoLockFreeBuffer.hpp" 10 #include "hmbdc/comm/inet/Misc.hpp" 12 #include <boost/lexical_cast.hpp> 13 #include <boost/circular_buffer.hpp> 21 namespace hmbdc {
namespace tips {
namespace tcpcast {
23 namespace sendserver_detail {
27 using ToSend = std::vector<iovec>;
28 using ToSendQueue = boost::circular_buffer<std::tuple<uint16_t
35 namespace sendsession_detail {
38 using ptr = std::shared_ptr<SendSession>;
40 , ToSendQueue & toSendQueue
45 , toSendQueue_(toSendQueue)
46 , toSendQueueIndex_(0)
50 , outboundSubscriptions_(outboundSubscriptions) {
51 msghdrRelic_.msg_iov =
new iovec[maxSendBatch * 2];
52 auto addrPort = hmbdc::comm::inet::getPeerIpPort(fd);
53 id_ = addrPort.first +
":" + std::to_string(addrPort.second);
54 auto forRead = dup(fd);
56 HMBDC_THROW(std::runtime_error,
"dup failed errno=" << errno);
60 hmbdc::app::utils::EpollTask::instance().add(
61 hmbdc::app::utils::EpollTask::EPOLLIN
62 | hmbdc::app::utils::EpollTask::EPOLLET, readFd_);
64 hmbdc::app::utils::EpollTask::instance().add(
65 hmbdc::app::utils::EpollTask::EPOLLOUT
66 | hmbdc::app::utils::EpollTask::EPOLLET, writeFd_);
67 HMBDC_LOG_N(
"SendSession started: ",
id());
71 clientSubscriptions_.exportTo([
this](uint16_t tag,
auto&&) {
72 outboundSubscriptions_.sub(tag);
74 delete [] msghdrRelic_.msg_iov;
75 HMBDC_LOG_N(
"SendSession retired: ",
id());
78 bool runOnce() HMBDC_RESTRICT {
79 if (hmbdc_unlikely(!doRead()))
return false;
80 if (hmbdc_unlikely(writeFd_.isFdReady() && msghdrRelicSize_)) {
81 auto l = sendmsg(writeFd_.fd, &msghdrRelic_, MSG_NOSIGNAL|MSG_DONTWAIT);
82 if (hmbdc_unlikely(l < 0)) {
83 if (!writeFd_.checkErr()) {
84 HMBDC_LOG_C(
"sendmsg failed errno=", errno);
89 msghdrRelicSize_ -= size_t(l);
90 if (hmbdc_unlikely(msghdrRelicSize_)) {
91 comm::inet::extractRelicTo(msghdrRelic_, msghdrRelic_, l);
97 for (; !msghdrRelicSize_ && writeFd_.isFdReady()
98 && toSendQueueIndex_ != toSendQueue_.size();) {
99 if (clientSubscriptions_.check(std::get<0>(toSendQueue_[toSendQueueIndex_]))) {
100 msghdr_.msg_iov = &(std::get<1>(toSendQueue_[toSendQueueIndex_])[0]);
101 msghdr_.msg_iovlen = std::get<1>(toSendQueue_[toSendQueueIndex_]).size();
102 auto l = sendmsg(writeFd_.fd, &msghdr_, MSG_NOSIGNAL|MSG_DONTWAIT);
103 if (hmbdc_unlikely(l < 0)) {
104 if (!writeFd_.checkErr()) {
105 HMBDC_LOG_C(
"sendmsg failed errno=", errno);
110 msghdrRelicSize_ = std::get<2>(toSendQueue_[toSendQueueIndex_]) -
size_t(l);
111 if (hmbdc_unlikely(msghdrRelicSize_)) {
112 comm::inet::extractRelicTo(msghdrRelic_, msghdr_, l);
121 char const* id()
const {
131 doRead() HMBDC_RESTRICT {
132 if (hmbdc_unlikely(readFd_.isFdReady())) {
133 auto l = recv(readFd_.fd, data_ + readLen_,
sizeof(data_) - readLen_, MSG_NOSIGNAL|MSG_DONTWAIT);
134 if (hmbdc_unlikely(l < 0)) {
135 if (!readFd_.checkErr()) {
136 HMBDC_LOG_C(
"recv failed errno=", errno);
144 auto p = std::find(data_, data_ + readLen_,
'\t');
145 if (p != data_ + readLen_) {
147 std::string t(data_ + 1);
150 }
else if (data_[0] ==
'+') {
151 auto tag = (uint16_t)std::stoi(t);
152 if (clientSubscriptions_.set(tag)) {
153 outboundSubscriptions_.add(tag);
155 }
else if (data_[0] ==
'-') {
156 auto tag = (uint16_t)std::stoi(t);
157 if (clientSubscriptions_.unset(tag)) {
158 outboundSubscriptions_.sub(tag);
161 HMBDC_LOG_C(
"voilating protocle by ", id_);
164 memmove(data_, p + 1, readLen_ - (p - data_ + 1));
165 readLen_ -= p - data_ + 1;
174 char data_[16 * 1024];
180 ToSendQueue& toSendQueue_;
181 ToSendQueue::size_type toSendQueueIndex_;
184 size_t msghdrRelicSize_;
Definition: SendServer.hpp:22
Definition: SendSession.hpp:37
Definition: EpollTask.hpp:87
Definition: LockFreeBufferMisc.hpp:89