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" 7 #include "hmbdc/comm/inet/Misc.hpp" 10 #include <boost/lexical_cast.hpp> 19 namespace hmbdc {
namespace tips {
namespace tcpcast {
21 namespace recvsession_detail {
23 template <
typename OutputBuffer,
typename AttachmentAllocator>
25 using ptr = std::shared_ptr<RecvSession<OutputBuffer, AttachmentAllocator>>;
26 using CleanupFunc = std::function<void()>;
29 , OutputBuffer& outputBuffer)
31 , subscriptions_(subscriptions)
33 , outputBuffer_(outputBuffer)
36 , bufSize_(config.
getExt<
size_t>(
"maxTcpReadBytes"))
37 , buf_((
char*)memalign(SMP_CACHE_BYTES, bufSize_))
40 , currTransportHeadFlag_(0)
41 , hasMemoryAttachmentItemSpace_(
42 new char[std::max(outputBuffer_.maxItemSize()
50 hasMemoryAttachment_->release();
51 HMBDC_LOG_N(
"RecvSession retired: ",
id());
54 void start(in_addr_t ip, uint16_t port) {
55 sockaddr_in remoteAddr = {0};
56 remoteAddr.sin_family = AF_INET;
57 remoteAddr.sin_addr.s_addr = ip;
58 remoteAddr.sin_port = htons(port);
59 if (connect(writeFd_.fd, (sockaddr*)&remoteAddr,
sizeof(remoteAddr)) < 0) {
60 if (errno != EINPROGRESS) {
61 HMBDC_THROW(std::runtime_error,
"connect fail, errno=" << errno);
65 auto forRead = dup(writeFd_.fd);
67 HMBDC_THROW(std::runtime_error,
"dup failed errno=" << errno);
71 hmbdc::app::utils::EpollTask::instance().add(
72 hmbdc::app::utils::EpollTask::EPOLLOUT
73 | hmbdc::app::utils::EpollTask::EPOLLET, writeFd_);
74 hmbdc::app::utils::EpollTask::instance().add(
75 hmbdc::app::utils::EpollTask::EPOLLIN
76 | hmbdc::app::utils::EpollTask::EPOLLET, readFd_);
80 if (currTransportHeadFlag_ == hmbdc::app::hasMemoryAttachment::flag) {
81 currTransportHeadFlag_ = 0;
83 outputBuffer_.putSome(sessionDropped_);
87 if (!initialized_)
return;
88 char const* hb =
"+\t";
89 if (hmbdc_unlikely(2 != send(writeFd_.fd, hb, 2, MSG_NOSIGNAL))){
90 HMBDC_LOG_C(
"error when sending heartbeat to ",
id(),
" errno=", errno);
95 char const* id()
const {
100 if (hmbdc_unlikely(stopped_))
return false;
101 if (hmbdc_unlikely(!initialized_ && writeFd_.isFdReady())) {
104 }
catch (std::exception
const& e) {
105 HMBDC_LOG_W(e.what());
108 HMBDC_LOG_C(
"unknown exception");
116 void initializeConn() {
117 int flags = fcntl(writeFd_.fd, F_GETFL, 0);
118 flags &= ~O_NONBLOCK;
119 if (fcntl(writeFd_.fd, F_SETFL, flags) < 0) {
120 HMBDC_THROW(std::runtime_error,
"fcntl failed errno=" << errno);
123 auto sz = config_.
getExt<
int>(
"tcpRecvBufferBytes");
125 if (setsockopt(readFd_.fd, SOL_SOCKET, SO_RCVBUF, &sz,
sizeof(sz)) < 0) {
126 HMBDC_LOG_C(
"failed to set send buffer size=", sz);
130 auto addrPort = hmbdc::comm::inet::getPeerIpPort(writeFd_.fd);
131 id_ = addrPort.first +
":" + std::to_string(addrPort.second);
132 strncpy(sessionStarted_.payload.ip, id_.c_str()
133 ,
sizeof(sessionStarted_.payload.ip));
134 sessionStarted_.payload.ip[
sizeof(sessionStarted_.payload.ip) - 1] = 0;
135 strncpy(sessionDropped_.payload.ip, id_.c_str()
136 ,
sizeof(sessionDropped_.payload.ip));
137 sessionDropped_.payload.ip[
sizeof(sessionDropped_.payload.ip) - 1] = 0;
138 outputBuffer_.putSome(sessionStarted_);
139 HMBDC_LOG_N(
"RecvSession started: ",
id());
144 void sendSubscriptions() {
145 std::ostringstream oss;
146 subscriptions_.exportTo([&oss](uint16_t tag,
auto&& count) {
148 oss <<
'+' << tag <<
'\t';
151 auto s = oss.str() +
"+\t";
152 auto sz = size_t(send(writeFd_.fd, s.c_str(), s.size(), MSG_NOSIGNAL));
153 if (hmbdc_unlikely(sz != s.size())) {
154 HMBDC_LOG_C(
"error when sending subscriptions to ",
id());
161 if (hmbdc_unlikely(currTransportHeadFlag_ == hmbdc::app::hasMemoryAttachment::flag
163 auto s = memoryAttachment_.write(bufCur_, filledLen_);
164 if (memoryAttachment_.writeDone()) {
165 memoryAttachment_.close();
166 currTransportHeadFlag_ = 0;
168 hasMemoryAttachmentItemSpace_.get(), outputBuffer_.maxItemSize());
173 while (currTransportHeadFlag_ == 0
176 auto wireSize = h->wireSize();
177 if (hmbdc_likely(filledLen_ >= wireSize)) {
178 if (hmbdc_likely(subscriptions_.check(h->typeTag()))) {
179 if (hmbdc_unlikely(h->flag == hmbdc::app::hasMemoryAttachment::flag)) {
180 currTransportHeadFlag_ = h->flag;
181 auto l = std::min<size_t>(outputBuffer_.maxItemSize(), h->messagePayloadLen);
182 memcpy(hasMemoryAttachmentItemSpace_.get(), h->payload(), l);
183 memoryAttachment_.open(h->typeTag(), hasMemoryAttachment_);
188 auto l = std::min<size_t>(outputBuffer_.maxItemSize(), h->messagePayloadLen);
189 outputBuffer_.put(h->payload(), l);
190 currTransportHeadFlag_ = 0;
195 filledLen_ -= wireSize;
200 memmove(buf_, bufCur_, filledLen_);
203 if (readFd_.isFdReady()) {
204 auto l = recv(readFd_.fd, buf_ + filledLen_, bufSize_ - filledLen_
205 , MSG_NOSIGNAL|MSG_DONTWAIT);
206 if (hmbdc_unlikely(l < 0)) {
207 if (hmbdc_unlikely(!readFd_.checkErr())) {
208 HMBDC_LOG_C(
"recv failed errno=", errno);
211 }
else if (hmbdc_unlikely(l == 0)) {
212 HMBDC_LOG_W(
"peer dropped:",
id());
220 }
while (filledLen_);
228 OutputBuffer& outputBuffer_;
234 size_t const bufSize_;
238 uint8_t currTransportHeadFlag_;
239 std::unique_ptr<char[]> hasMemoryAttachmentItemSpace_;
250 addr_ = (
char*)alloc_(typeTag, att);
258 bool writeDone()
const {
259 return fullLen_ == len_;
262 size_t write(
void const* mem,
size_t l) {
263 auto wl = std::min(l, fullLen_ - len_);
265 memcpy(addr_ + len_, mem, wl);
278 AttachmentAllocator alloc_;
286 template <
typename OutputBuffer,
typename AttachmentAllocator>
Definition: RecvSession.hpp:242
T getExt(const path_type ¶m, bool throwIfMissing=true) const
get a value from the config
Definition: Config.hpp:238
class to hold an hmbdc configuration
Definition: Config.hpp:44
Definition: RecvSession.hpp:24
Definition: EpollTask.hpp:87
Definition: Message.hpp:212
Definition: Transport.hpp:20
if a specific hmbdc network transport (for example tcpcast, rmcast, and rnetmap) supports message wit...
Definition: Message.hpp:125