1 #include "hmbdc/Copyright.hpp" 3 #include "hmbdc/tips/udpcast/Transport.hpp" 4 #include "hmbdc/tips/udpcast/DefaultUserConfig.hpp" 5 #include "hmbdc/tips/TypeTagSet.hpp" 6 #include "hmbdc/pattern/MonoLockFreeBuffer.hpp" 7 #include "hmbdc//MetaUtils.hpp" 9 #include <boost/lexical_cast.hpp> 12 #include <type_traits> 15 namespace hmbdc {
namespace tips {
namespace udpcast {
21 using Transport::Transport;
25 namespace recvtransportengine_detail {
34 template <
typename OutputBuffer>
38 , OutputBuffer& outputBuffer)
41 , outputBuffer_(outputBuffer)
42 , maxItemSize_(outputBuffer.maxItemSize())
43 , buf_(
new char[mtu_])
47 if (setsockopt(fd, SOL_SOCKET,SO_REUSEADDR, &yes,
sizeof(yes)) < 0) {
48 HMBDC_LOG_C(
"failed to set reuse address errno=", errno);
50 auto sz = config_.
getExt<
int>(
"udpRecvBufferBytes");
52 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sz,
sizeof(sz)) < 0) {
53 HMBDC_LOG_C(
"failed to set send buffer size=", sz);
57 auto udpcastListenPort = config_.
getExt<uint16_t>(
"udpcastListenPort");
58 struct sockaddr_in udpcastListenAddrPort;
59 memset(&udpcastListenAddrPort, 0,
sizeof(udpcastListenAddrPort));
60 udpcastListenAddrPort.sin_family = AF_INET;
61 auto ipStr = cfg.
getExt<std::string>(
"udpcastListenAddr") == std::string(
"ifaceAddr")
62 ? comm::inet::getLocalIpMatchMask(cfg.
getExt<std::string>(
"ifaceAddr"))
63 :cfg.
getExt<std::string>(
"udpcastListenAddr");
64 udpcastListenAddrPort.sin_addr.s_addr = inet_addr(ipStr.c_str());
65 udpcastListenAddrPort.sin_port = htons(udpcastListenPort);
66 if (::bind(fd, (
struct sockaddr *)&udpcastListenAddrPort,
sizeof(udpcastListenAddrPort)) < 0) {
67 HMBDC_THROW(std::runtime_error,
"failed to bind unicast udpcast listen address " 68 << ipStr <<
':' << cfg.
getExt<
short>(
"udpcastListenPort") <<
" errno=" << errno);
71 if ((udpcastListenAddrPort.sin_addr.s_addr & 0x000000F0) == 0xE0) {
74 mreq.imr_multiaddr.s_addr = udpcastListenAddrPort.sin_addr.s_addr;
76 comm::inet::getLocalIpMatchMask(config_.
getExt<std::string>(
"ifaceAddr"));
77 mreq.imr_interface.s_addr=inet_addr(iface.c_str());
78 if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0) {
79 HMBDC_THROW(std::runtime_error,
"failed to join " << ipStr <<
':' 80 << cfg.
getExt<
short>(
"udpcastPort"));
83 HMBDC_LOG_N(
"listen at ", cfg.
getExt<std::string>(
"ifaceAddr"));
88 template <MessageTupleC Messages,
typename CcNode>
89 void subscribeFor(CcNode
const& node, uint16_t mod, uint16_t res) {
90 subscriptions_.markSubsFor<Messages>(node, mod, res);
93 template <MessageC Message>
95 subscriptions_.add(Message::typeTag);
106 hmbdc::app::utils::EpollTask::instance().add(
107 hmbdc::app::utils::EpollTask::EPOLLIN
108 | hmbdc::app::utils::EpollTask::EPOLLET, *
this);
111 void runOnce(
bool alwaysPoll =
false) HMBDC_RESTRICT {
112 if (hmbdc_unlikely(alwaysPoll || !isFdReady())) {
113 hmbdc::app::utils::EpollTask::instance().poll();
118 sockaddr_in udpcastListenRemoteAddr = {0};
120 void resumeRead() HMBDC_RESTRICT {
122 while (bytesRecved_) {
123 auto h =
reinterpret_cast<TransportMessageHeader*
>(bufCur_);
124 auto wireSize = h->wireSize();
126 if (hmbdc_likely(bytesRecved_ >= wireSize)) {
127 if (subscriptions_.check(h->typeTag())) {
128 if (hmbdc_unlikely(wireSize > bytesRecved_)) {
131 auto l = std::min<size_t>(maxItemSize_, h->messagePayloadLen());
132 outputBuffer_.put(h->payload(), l);
134 bytesRecved_ -= wireSize;
143 socklen_t addrLen =
sizeof(udpcastListenRemoteAddr);
144 auto l = recvfrom(fd, buf_, mtu_, MSG_NOSIGNAL|MSG_DONTWAIT
145 , (
struct sockaddr *)&udpcastListenRemoteAddr, &addrLen);
146 if (hmbdc_unlikely(l < 0)) {
148 HMBDC_LOG_C(
"recvmmsg failed errno=", errno);
157 }
while(bytesRecved_);
160 OutputBuffer& outputBuffer_;
165 TypeTagSet subscriptions_;
168 template <
typename OutputBuffer>
189 using Transport::hmbdcName;
197 HMBDC_LOG_C(e.what());
205 template <
typename OutputBuffer>
206 using RecvTransportImpl = recvtransportengine_detail::RecvTransportImpl<OutputBuffer>;
208 template <
typename OutputBuffer>
209 using RecvTransportEngine = recvtransportengine_detail::RecvTransportEngineImpl<OutputBuffer>;
T getExt(const path_type ¶m, bool throwIfMissing=true) const
get a value from the config
Definition: Config.hpp:238
Definition: MonoLockFreeBuffer.hpp:16
Definition: Transport.hpp:38
class to hold an hmbdc configuration
Definition: Config.hpp:44
void setAdditionalFallbackConfig(Config const &c)
set additional defaults
Definition: Config.hpp:153
void invokedCb(size_t) HMBDC_RESTRICT override
power the io_service and other things
Definition: RecvTransportEngine.hpp:185
Config & resetSection(char const *section, bool sectionExists=true)
change section name
Definition: Config.hpp:176
impl class
Definition: RecvTransportEngine.hpp:35
void start()
start the show by schedule the mesage recv
Definition: RecvTransportEngine.hpp:105
void stoppedCb(std::exception const &e) override
should not happen ever unless an exception thrown
Definition: RecvTransportEngine.hpp:196
interface to power a multicast transport receiving functions
Definition: RecvTransportEngine.hpp:20
Definition: RecvTransportEngine.hpp:169
A Client represents a thread of execution/a task. The execution is managed by a Context. a Client object could participate in message dispatching as the receiver of specifed message types.
Definition: Client.hpp:128