//------------------------------------------------------------------------------------- BundleBroadcast::BundleBroadcast(NetworkInterface & networkInterface, uint16 bindPort, uint32 recvWindowSize): Bundle(NULL, Network::PROTOCOL_UDP), epListen_(), networkInterface_(networkInterface), recvWindowSize_(recvWindowSize), good_(false), itry_(5) { epListen_.socket(SOCK_DGRAM); epBroadcast_.socket(SOCK_DGRAM); if (!epListen_.good() || !epBroadcast_.good()) { ERROR_MSG(fmt::format("BundleBroadcast::BundleBroadcast: init socket is error, {}\n", kbe_strerror())); networkInterface_.dispatcher().breakProcessing(); } else { int count = 0; while(true) { if (epListen_.bind(htons(bindPort), htonl(INADDR_ANY)) != 0) { good_ = false; KBEngine::sleep(10); count++; if(count > 30) { WARNING_MSG(fmt::format("BundleBroadcast::BundleBroadcast: Couldn't bind listener socket to port {}, {}\n", bindPort, kbe_strerror())); break; } } else { epListen_.addr(htons(bindPort), htonl(INADDR_ANY)); good_ = true; // DEBUG_MSG(fmt::format("BundleBroadcast::BundleBroadcast: epListen {}\n", epListen_.c_str())); break; } } } pCurrPacket()->data_resize(recvWindowSize_); }
//------------------------------------------------------------------------------------- bool BundleBroadcast::receive(MessageArgs* recvArgs, sockaddr_in* psin) { if (!epListen_.good()) return false; struct timeval tv; fd_set fds; int icount = 1; tv.tv_sec = 1; tv.tv_usec = 0; if(!pCurrPacket()) newPacket(); while (1) { FD_ZERO( &fds ); FD_SET((int)epListen_, &fds); int selgot = select(epListen_+1, &fds, NULL, NULL, &tv); if (selgot == 0) { if(icount > 5) { DEBUG_MSG("BundleBroadcast::receive: is failed, the app will be terminated.\n", icount, epListen_.addr().c_str()); networkInterface_.mainDispatcher().breakProcessing(); return false; } else { DEBUG_MSG("BundleBroadcast::receive: retries(%d), bind_addr(%s) ...\n", icount, epListen_.addr().c_str()); } icount++; continue; } else if (selgot == -1) { ERROR_MSG("BundleBroadcast::receive: select error. %s.\n", kbe_strerror()); return false; } else { sockaddr_in sin; pCurrPacket()->resetPacket(); if(psin == NULL) psin = &sin; int len = epListen_.recvfrom(pCurrPacket()->data(), recvWindowSize_, *psin); if (len == -1) { ERROR_MSG("BundleBroadcast::receive: recvfrom error. %s.\n", kbe_strerror()); continue; } DEBUG_MSG("BundleBroadcast::receive: from %s, datalen=%d.\n", inet_ntoa((struct in_addr&)psin->sin_addr.s_addr), len); pCurrPacket()->wpos(len); if(recvArgs != NULL) recvArgs->createFromStream(*pCurrPacket()); break; } } return true; }
//------------------------------------------------------------------------------------- bool BundleBroadcast::receive(MessageArgs* recvArgs, sockaddr_in* psin, int32 timeout, bool showerr) { if (!epListen_.good()) return false; struct timeval tv; fd_set fds; int icount = 1; tv.tv_sec = 0; tv.tv_usec = timeout; if(!pCurrPacket()) newPacket(); while (1) { FD_ZERO( &fds ); FD_SET((int)epListen_, &fds); int selgot = select(epListen_+1, &fds, NULL, NULL, &tv); if (selgot == 0) { if(icount > itry_) { if(showerr) { ERROR_MSG("BundleBroadcast::receive: is failed(please check {firewall rule => broadcastaddr not is LAN ?})!\n"); } return false; } else { //DEBUG_MSG(fmt::format("BundleBroadcast::receive: retries({}), bind_addr({}) ...\n", // icount, epListen_.addr())); } icount++; continue; } else if (selgot == -1) { if(showerr) { ERROR_MSG(fmt::format("BundleBroadcast::receive: select error. {}.\n", kbe_strerror())); } return false; } else { sockaddr_in sin; pCurrPacket()->resetPacket(); if(psin == NULL) psin = &sin; pCurrPacket()->data_resize(recvWindowSize_); int len = epListen_.recvfrom(pCurrPacket()->data(), recvWindowSize_, *psin); if (len == -1) { if(showerr) { ERROR_MSG(fmt::format("BundleBroadcast::receive: recvfrom error. {}.\n", kbe_strerror())); } continue; } //DEBUG_MSG(fmt::format("BundleBroadcast::receive: from {}, datalen={}.\n", // inet_ntoa((struct in_addr&)psin->sin_addr.s_addr), len)); pCurrPacket()->wpos(len); if(recvArgs != NULL) { try { recvArgs->createFromStream(*pCurrPacket()); }catch(MemoryStreamException &) { ERROR_MSG(fmt::format("BundleBroadcast::receive: data is error. size={}.\n", len)); continue; } } break; } } return true; }