1 #include "hmbdc/Copyright.hpp" 3 #include "hmbdc/app/Base.hpp" 4 #include "hmbdc/tips/rmcast/Transport.hpp" 5 #include "hmbdc/tips/rmcast/Messages.hpp" 6 #include "hmbdc/tips/udpcast/Transport.hpp" 7 #include "hmbdc/app/utils/EpollTask.hpp" 8 #include "hmbdc/comm/inet/Endpoint.hpp" 9 #include "hmbdc/time/Time.hpp" 10 #include "hmbdc/time/Rater.hpp" 11 #include "hmbdc/pattern/LockFreeBufferT.hpp" 14 #include <boost/bind.hpp> 19 namespace hmbdc {
namespace tips {
namespace rmcast {
21 namespace mcsendtransport_detail {
27 using ptr = std::shared_ptr<McSendTransport>;
29 ,
size_t maxMessageSize
32 , ToCleanupAttQueue& toCleanupAttQueue)
34 , maxMessageSize_(maxMessageSize)
39 , config_.getExt<uint16_t>(
"mcastPort")).v)
42 , maxSendBatch_(config_.getExt<
size_t>(
"maxSendBatch"))
44 , seqAlertPending_(
false)
46 , startSending_(
false)
47 , toCleanupAttQueue_(toCleanupAttQueue) {
48 toSend_.msg_name = &mcAddr_;
49 toSend_.msg_namelen =
sizeof(mcAddr_);
51 if (maxMessageSize_ + totalHead > mtu_) {
52 HMBDC_THROW(std::out_of_range,
"maxMessageSize need <= " << mtu_ - totalHead);
55 auto addr = seqAlertBuf_;
59 h->setSeq(std::numeric_limits<HMBDC_SEQ_TYPE>::max());
60 seqAlert_ = &(h->wrapped<
SeqAlert>());
62 toSendMsgs_.reserve((maxSendBatch_ + 2) * 2);
64 auto ttl = config_.
getExt<
int>(
"ttl");
65 if (ttl > 0 && setsockopt(mcFd_.fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
sizeof(ttl)) < 0) {
66 HMBDC_THROW(std::runtime_error,
"failed to set set ttl=" << ttl <<
" errno=" << errno);
68 char loopch = config_.
getExt<
bool>(
"loopback")?1:0;
69 if (setsockopt(mcFd_.fd, IPPROTO_IP, IP_MULTICAST_LOOP, (
char *)&loopch,
sizeof(loopch)) < 0) {
70 HMBDC_THROW(std::runtime_error,
"failed to set loopback=" << config_.
getExt<
bool>(
"loopback"));
73 auto sz = config_.
getExt<
int>(
"udpSendBufferBytes");
75 if (setsockopt(mcFd_.fd, SOL_SOCKET, SO_SNDBUF, &sz,
sizeof(sz)) < 0) {
76 HMBDC_LOG_C(
"failed to set send buffer size=", sz);
79 hmbdc::app::utils::EpollTask::instance().add(
80 hmbdc::app::utils::EpollTask::EPOLLOUT
81 | hmbdc::app::utils::EpollTask::EPOLLET, mcFd_);
91 template <
typename AdvertisingMessages>
92 void setAds(AdvertisingMessages
const& ads) {
93 decltype(adBufs_) newAdBufs;
94 for (
auto const& ad : ads) {
95 newAdBufs.emplace_back();
96 auto addr = newAdBufs.rbegin()->data();
101 h->setSeq(std::numeric_limits<HMBDC_SEQ_TYPE>::max());
103 std::swap(adBufs_, newAdBufs);
106 void setAdPending() {
110 void setSeqAlertPending() {
111 seqAlertPending_ =
true;
115 void runOnce(
size_t sessionCount) HMBDC_RESTRICT {
116 resumeSend(sessionCount);
125 size_t maxMessageSize_;
126 Buffer& HMBDC_RESTRICT buffer_;
133 size_t maxSendBatch_;
138 bool seqAlertPending_;
141 std::vector<iovec> toSendMsgs_;
142 ToCleanupAttQueue& toCleanupAttQueue_;
145 resumeSend(
size_t sessionCount) {
147 if (hmbdc_likely(toSendMsgs_.size())) {
148 if (hmbdc_unlikely(!mcFd_.isFdReady()))
return;
150 toSend_.msg_iov = &(toSendMsgs_[0]);
151 toSend_.msg_iovlen = toSendMsgs_.size();
152 if (sendmsg(mcFd_.fd, &toSend_, MSG_DONTWAIT) < 0) {
153 if (!mcFd_.checkErr()) {
154 HMBDC_LOG_C(
"sendmmsg failed errno=", errno);
158 buffer_.wasteAfterPeek(0, wasteSize_);
164 size_t batchBytes = 0;
165 if (hmbdc_unlikely(adPending_)) {
166 for (
auto& adBuf : adBufs_) {
167 toSendMsgs_.push_back(iovec{(
void*)adBuf.data(), adBuf.size()});
168 batchBytes +=
sizeof(adBuf);
173 if (hmbdc_likely(startSending_) && !toSendMsgs_.size()) {
175 buffer_.peek(0, begin, end, maxSendBatch_);
176 if (hmbdc_unlikely(!sessionCount)) {
177 buffer_.wasteAfterPeek(0u, end - begin);
184 if (hmbdc_unlikely(!rater_.check(item->wireSize())))
break;
185 batchBytes += item->wireSize();
186 if (hmbdc_unlikely(batchBytes > mtu_))
break;
187 if (hmbdc_unlikely(item->typeTag() == app::MemorySeg::typeTag)) {
188 toSendMsgs_.push_back(iovec{(
void*)item->wireBytes(), item->wireSize() - item->wireSizeMemorySeg()});
189 toSendMsgs_.push_back(iovec{(
void*)item->wireBytesMemorySeg(), item->wireSizeMemorySeg()});
191 if (hmbdc_unlikely(item->typeTag() == app::StartMemorySegTrain::typeTag)) {
192 auto& trainHead = item->template wrapped<app::StartMemorySegTrain>();
193 auto itActual = it; itActual.seq_ += trainHead.segCount + 1;
195 toCleanupAttQueue_.push_back(std::make_tuple(itActual.seq_
196 , &actual->template wrapped<app::hasMemoryAttachment>()
197 , trainHead.att.afterConsumedCleanupFunc));
199 toSendMsgs_.push_back(iovec{(
void*)item->wireBytes(), item->wireSize()});
203 seqAlert_->expectSeq = item->getSeq() + 1;
206 wasteSize_ = it - begin;
208 if (hmbdc_unlikely(seqAlertPending_)) {
210 toSendMsgs_.push_back(iovec{seqAlertBuf_,
sizeof(seqAlertBuf_)});
211 batchBytes +=
sizeof(seqAlertBuf_);
213 seqAlertPending_ =
false;
215 }
while (hmbdc_likely(toSendMsgs_.size()));
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: Endpoint.hpp:17
Definition: McSendTransport.hpp:25
Definition: Message.hpp:212
Definition: Messages.hpp:163
Definition: Transport.hpp:21
Definition: Message.hpp:263
Definition: Transport.hpp:15
Definition: LockFreeBufferMisc.hpp:89