static void CountSSMLeave(const address &group, const address &source) { address source_addr; char tmp[64], tmp2[64]; GroupMap::iterator g = groupMap.find(group); assert(g != groupMap.end()); source_addr.set_family(source.family()); source_addr.copy_address(source); source_addr.set_port(0); SourceMap::iterator s = g->second.find(source_addr); assert(s != g->second.end()); SourceSet::iterator ss = s->second.find(source); if (ss == s->second.end()) { return; } if (verbose) info("Removing beacon %s from (%s, %s)", source.to_string(tmp, sizeof(tmp)), source_addr.to_string(tmp2, sizeof(tmp2)), group.to_string(tmp2, sizeof(tmp2))); s->second.erase(ss); if (s->second.empty()) { if (verbose) info("No more beacons for (%s, %s), leaving group", source_addr.to_string(tmp, sizeof(tmp)), group.to_string(tmp2, sizeof(tmp2))); SSMLeave(ssmMcastSock,group, source_addr); g->second.erase(s); } if (g->second.empty()) { if (verbose) info("No more sources, unregistering group %s, ", group.to_string(tmp, sizeof(tmp))); groupMap.erase(g); } }
static void CountSSMJoin(const address &group, const address &source) { address source_addr; char tmp[64], tmp2[64], tmp3[64]; source_addr.set_family(source.family()); source_addr.copy_address(source); source_addr.set_port(0); GroupMap::iterator g = groupMap.find(group); if (g == groupMap.end()) { if (verbose) info("Registering SSM group %s", group.to_string(tmp, sizeof(tmp))); g = groupMap.insert(std::make_pair(group, SourceMap())).first; } SourceMap::iterator s = g->second.find(source_addr); if (s == g->second.end()) { if (verbose) info("Joining (%s, %s)", source_addr.to_string(tmp, sizeof(tmp)), group.to_string(tmp2, sizeof(tmp2))); if (SSMJoin(ssmMcastSock, group, source_addr) < 0) { if (verbose) info("Join failed, reason: %s", strerror(errno)); return; } else { s = g->second.insert(std::make_pair(source_addr, SourceSet())).first; } } SourceSet::iterator ss = s->second.find(source); if (ss == s->second.end()) { if (verbose) info("Adding beacon %s to (%s, %s)", source.to_string(tmp, sizeof(tmp)), source_addr.to_string(tmp2, sizeof(tmp2)), group.to_string(tmp3, sizeof(tmp3))); s->second.insert(source); } }
std::string to_string()const { std::string buf; std::stringstream sbuf; buf = ip.to_string(); buf += "/"; sbuf << mask.bits(); buf += sbuf.str(); return buf; }
void removeSource(const address &baddr, bool timeout) { Sources::iterator i = sources.find(baddr); if (i != sources.end()) { if (verbose) { char tmp[64]; if (i->second.identified) { info("Removing source %s [%s]%s", baddr.to_string(tmp, sizeof(tmp)), i->second.name.c_str(), (timeout ? " by Timeout" : "")); } else { info("Removing source %s%s", baddr.to_string(tmp, sizeof(tmp)), (timeout ? " by Timeout" : "")); } } if (IsSSMEnabled()) CountSSMLeave(ssmProbeAddr, baddr); sources.erase(i); } }
std::string ipport_to_string(address const& addr,int port) { error_code ec; std::string straddr = addr.to_string(ec); std::string ret; ret.reserve(straddr.length()+10); if (addr.is_v6()) { ret += '['; ret += straddr; ret += ']'; ret += ':'; ret += boost::lexical_cast<std::string>(port); } else { ret += straddr; ret += ':'; ret += boost::lexical_cast<std::string>(port); } return ret; }
void handle_nmsg(const address &from, uint64_t recvdts, int ttl, uint8_t *buff, int len, bool ssm) { if (len < 4) return; if (ntohs(*((uint16_t *)buff)) != 0xbeac) return; if (buff[2] != PROTO_VER) return; uint64_t now = get_timestamp(); if (buff[3] == 0) { if (len == 12) { uint32_t seq = read_u32(buff + 4); uint32_t ts = read_u32(buff + 8); getSource(from, 0, now, recvdts, true).update(ttl, seq, ts, now, recvdts, ssm); } return; } else if (buff[3] == 1) { if (len < 5) return; beaconSource &src = getSource(from, 0, now, recvdts, true); src.sttl = buff[4]; len -= 5; for (uint8_t *hd = tlv_begin(buff + 5, len); hd; hd = tlv_next(hd, len)) { if (verbose > 4) { char tmp[64]; from.to_string(tmp, sizeof(tmp)); fprintf(stderr, "Parsing TLV (%i, %i) for %s [len is now %i]\n", (int)hd[0], (int)hd[1], tmp, len); } if (hd[0] == T_BEAC_NAME) { string name; if (check_string((char *)hd + 2, hd[1], name)) src.setName(name); } else if (hd[0] == T_ADMIN_CONTACT) { check_string((char *)hd + 2, hd[1], src.adminContact); } else if (hd[0] == T_SOURCE_INFO || hd[0] == T_SOURCE_INFO_IPv4) { int blen = hd[0] == T_SOURCE_INFO ? 18 : 6; if (hd[1] < blen) continue; address addr; if (hd[0] == T_SOURCE_INFO) { sockaddr_in6 *a6 = (sockaddr_in6 *)&addr; a6->sin6_family = AF_INET6; memcpy(&a6->sin6_addr, hd + 2, sizeof(in6_addr)); memcpy(&a6->sin6_port, hd + 18, sizeof(uint16_t)); } else { sockaddr_in *a4 = (sockaddr_in *)&addr; a4->sin_family = AF_INET; memcpy(&a4->sin_addr, hd + 2, sizeof(in_addr)); memcpy(&a4->sin_port, hd + 6, sizeof(uint16_t)); } beaconExternalStats &stats = src.getExternal(addr, now, recvdts); int plen = hd[1] - blen; for (uint8_t *pd = tlv_begin(hd + 2 + blen, plen); pd; pd = tlv_next(pd, plen)) { if (pd[0] == T_BEAC_NAME) { if (check_string((char *)pd + 2, pd[1], stats.name)) { stats.identified = !stats.name.empty(); } } else if (pd[0] == T_ADMIN_CONTACT) { check_string((char *)pd + 2, pd[1], stats.contact); } else if (pd[0] == T_ASM_STATS || pd[0] == T_SSM_STATS) { Stats *st = (pd[0] == T_ASM_STATS ? &stats.ASM : &stats.SSM); if (!read_tlv_stats(pd, stats, *st)) break; st->lastupdate = now; } } // trigger local SSM join if (!addr.is_equal(beaconUnicastAddr)) { beaconSource &t = getSource(addr, stats.identified ? stats.name.c_str() : 0, now, recvdts, false); if (t.adminContact.empty()) t.adminContact = stats.contact; } } else if (hd[0] == T_WEBSITE_GENERIC || hd[0] == T_WEBSITE_LG || hd[0] == T_WEBSITE_MATRIX) { string url; if (check_string((char *)hd + 2, hd[1], url)) { src.webSites[hd[0]] = url; } } else if (hd[0] == T_CC) { if (hd[1] == 2) { src.CC = string((char *)hd + 2, 2); } } else if (hd[0] == T_SOURCE_FLAGS) { if (hd[1] == 4) src.Flags = read_u32(hd + 2); } else if (hd[0] == T_LEAVE) { removeSource(from, false); break; } } } }
void run_test(HandleAlerts const& on_alert, Test const& test) { using namespace libtorrent; using asio::ip::address; address const peer0 = addr("50.0.0.1"); address const peer1 = addr("50.0.0.2"); // setup the simulation sim::default_config network_cfg; sim::simulation sim{network_cfg}; sim::asio::io_service ios0 { sim, peer0 }; sim::asio::io_service ios1 { sim, peer1 }; lt::session_proxy zombie[2]; // setup settings pack to use for the session (customization point) lt::settings_pack pack = settings(); // disable utp by default pack.set_bool(settings_pack::enable_outgoing_utp, false); pack.set_bool(settings_pack::enable_incoming_utp, false); // disable encryption by default pack.set_bool(settings_pack::prefer_rc4, false); pack.set_int(settings_pack::in_enc_policy, settings_pack::pe_disabled); pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_disabled); pack.set_int(settings_pack::allowed_enc_level, settings_pack::pe_plaintext); pack.set_str(settings_pack::listen_interfaces, peer0.to_string() + ":6881"); // create session std::shared_ptr<lt::session> ses[2]; ses[0] = std::make_shared<lt::session>(pack, ios0); pack.set_str(settings_pack::listen_interfaces, peer1.to_string() + ":6881"); ses[1] = std::make_shared<lt::session>(pack, ios1); // only monitor alerts for session 0 (the downloader) print_alerts(*ses[0], [=](lt::session& ses, lt::alert const* a) { if (auto ta = alert_cast<lt::torrent_added_alert>(a)) { ta->handle.connect_peer(lt::tcp::endpoint(peer1, 6881)); } on_alert(ses, a); }); print_alerts(*ses[1]); // the first peer is a downloader, the second peer is a seed lt::add_torrent_params params = create_torrent(1); params.flags &= ~lt::add_torrent_params::flag_auto_managed; params.flags &= ~lt::add_torrent_params::flag_paused; params.save_path = save_path(0); ses[0]->async_add_torrent(params); params.save_path = save_path(1); ses[1]->async_add_torrent(params); sim::timer t(sim, lt::seconds(60), [&](boost::system::error_code const& ec) { test(ses); // shut down int idx = 0; for (auto& s : ses) { zombie[idx++] = s->abort(); s.reset(); } }); sim.run(); }
inline std::string print_address(address const& addr) { error_code ec; return addr.to_string(ec); }
int main(int argc, char **argv) { int res; srand(time(NULL)); char tmp[256]; if (gethostname(tmp, sizeof(tmp)) != 0) { perror("Failed to get hostname"); return -1; } beaconName = tmp; parse_arguments(argc, argv); MulticastStartup(); if (beaconName.empty()) fatal("No name supplied, check `dbeacon -h`."); if (!probeAddrLiteral.empty()) { if (!probeAddr.parse(probeAddrLiteral.c_str(), true)) return -1; probeAddr.to_string(sessionName, sizeof(sessionName)); if (!probeAddr.is_multicast()) fatal("Specified probe addr (%s) is not of a multicast group.", sessionName); if (adminContact.empty()) fatal("No administration contact supplied, check `dbeacon -h`."); mcastListen.push_back(ContentDesc(probeAddr, false)); insert_event(SENDING_EVENT, 100); insert_event(REPORT_EVENT, 10000); insert_event(MAP_REPORT_EVENT, 30000); insert_event(WEBSITE_REPORT_EVENT, 120000); redist.push_back(probeAddr); if (useSSM) { if (probeSSMAddrLiteral.empty()) { int family = forceFamily; if (family == AF_UNSPEC) { family = probeAddr.family(); } if (family == AF_INET) { probeSSMAddrLiteral = defaultIPv4SSMChannel; } else { probeSSMAddrLiteral = defaultIPv6SSMChannel; } } if (!ssmProbeAddr.parse(probeSSMAddrLiteral.c_str(), true)) { fatal("Bad address format for SSM channel."); } else if (!ssmProbeAddr.is_unspecified()) { insert_event(SSM_SENDING_EVENT, 100); insert_event(SSM_REPORT_EVENT, 15000); if (listenForSSM) { mcastListen.push_back(ContentDesc(ssmProbeAddr, true)); } } } } else { if (mcastListen.empty()) fatal("Nothing to do, check `dbeacon -h`."); else strcpy(sessionName, beaconName.c_str()); } address local; local.set_family(probeAddr.family()); mcastSock = SetupSocket(local, false, false); if (mcastSock < 0) return -1; if (beaconUnicastAddr.is_unspecified()) beaconUnicastAddr = get_local_address_for(probeAddr); if (bind(mcastSock, beaconUnicastAddr.saddr(), beaconUnicastAddr.addrlen()) != 0) { perror("Failed to bind local socket"); return -1; } if (beaconUnicastAddr.fromsocket(mcastSock) < 0) { perror("getsockname"); return -1; } for (McastListen::const_iterator i = mcastListen.begin(); i != mcastListen.end(); ++i) { int sock = SetupSocket(i->first, true, i->second); if (sock < 0) return -1; if (i->second) { ListenTo(sock, handle_ssm); ssmMcastSock = sock; } else { ListenTo(sock, handle_asm); } } if (useSSMPing) { if (SetupSSMPing() < 0) d_log(LOG_ERR, "Failed to setup SSM Ping."); else flags |= SSMPING_CAPABLE; } if (IsSSMEnabled()) { flags |= SSM_CAPABLE; uint64_t now = get_timestamp(); for (vector<address>::const_iterator i = ssmBootstrap.begin(); i != ssmBootstrap.end(); ++i) getSource(*i, 0, now, 0, false); } else if (!ssmBootstrap.empty()) d_log(LOG_WARNING, "Tried to bootstrap using SSM when SSM is not enabled."); if (daemonize || use_syslog) { use_syslog = true; openlog("dbeacon", LOG_NDELAY | LOG_PID, LOG_DAEMON); } past_init = true; if (daemonize) { if (dbeacon_daemonize(pidfile)) { perror("Failed to daemon()ize."); return -1; } } // Init timer events insert_event(GARBAGE_COLLECT_EVENT, 30000); if (!dumpFile.empty()) insert_event(DUMP_EVENT, dumpInterval * 1000); insert_event(DUMP_BW_EVENT, 10000); if (dumpBwReport) insert_event(DUMP_BIG_BW_EVENT, 600000); info("Local name is `%s` [Beacon group: %s, Local address: %s]", beaconName.c_str(), sessionName, beaconUnicastAddr.to_string(tmp, sizeof(tmp), false)); send_report(WEBSITE_REPORT_EVENT); signal(SIGUSR1, dumpBigBwStats); signal(SIGINT, sendLeaveReport); signal(SIGTERM, sendLeaveReport); signal(SIGCHLD, waitForMe); // bloody fork, we dont want to wait for thee startTime = lastDumpBwTS = lastDumpDumpBwTS = get_timestamp(); while (1) { fd_set readset; timeval eventm; FD_ZERO(&readset); for (McastSocks::const_iterator i = mcastSocks.begin(); i != mcastSocks.end(); ++i) FD_SET(i->first, &readset); next_event(&eventm); res = select(mcastSocks.rbegin()->first + 1, &readset, 0, 0, &eventm); if (res < 0) { if (errno == EINTR) continue; fatal("Select failed: %s", strerror(errno)); } else { for (McastSocks::const_iterator i = mcastSocks.begin(); res > 0 && i != mcastSocks.end(); ++i) { if (FD_ISSET(i->first, &readset)) { handle_mcast(*i); res--; } } handle_event(); } } return 0; }
void do_dump() { string tmpf = dumpFile; tmpf += ".working"; FILE *fp = fopen(tmpf.c_str(), "w"); if (!fp) return; uint64_t now = get_timestamp(); uint64_t diff = now - lastDumpDumpBwTS; lastDumpDumpBwTS = now; double rxRate = dumpBytesReceived * 8 / ((double)diff); double txRate = dumpBytesSent * 8 / ((double)diff); dumpBytesReceived = 0; dumpBytesSent = 0; fprintf(fp, "<beacons rxrate=\"%.2f\" txrate=\"%.2f\" versioninfo=\"%s\">\n", rxRate, txRate, versionInfo); fprintf(fp, "<group addr=\"%s\"", sessionName); char tmp[64]; if (IsSSMEnabled()) fprintf(fp, " ssmgroup=\"%s\"", ssmProbeAddr.to_string(tmp, sizeof(tmp))); fprintf(fp, " int=\"%.2f\">\n", beacInt); if (!probeAddr.is_unspecified()) { fprintf(fp, "\t<beacon name=\"%s\" addr=\"%s\"", beaconName.c_str(), beaconUnicastAddr.to_string(tmp, sizeof(tmp))); if (!adminContact.empty()) fprintf(fp, " contact=\"%s\"", adminContact.c_str()); if (!twoLetterCC.empty()) fprintf(fp, " country=\"%s\"", twoLetterCC.c_str()); fprintf(fp, " age=\"%lu\" lastupdate=\"0\" rxlocal=\"true\">\n", (now - startTime) / 1000); for (uint32_t k = 0; k < KnownFlags; k++) { if (flags & (1 << k)) { fprintf(fp, "\t\t<flag name=\"%s\" value=\"true\" />\n", Flags[k]); } } for (WebSites::const_iterator j = webSites.begin(); j != webSites.end(); j++) { const char *typnam = j->first == T_WEBSITE_GENERIC ? "generic" : (j->first == T_WEBSITE_LG ? "lg" : "matrix"); fprintf(fp, "\t\t<website type=\"%s\" url=\"%s\" />\n", typnam, j->second.c_str()); } fprintf(fp, "\t\t<sources>\n"); for (Sources::const_iterator i = sources.begin(); i != sources.end(); i++) { fprintf(fp, "\t\t\t<source addr=\"%s\"", i->first.to_string(tmp, sizeof(tmp))); if (i->second.identified) { fprintf(fp, " name=\"%s\"", i->second.name.c_str()); if (!i->second.adminContact.empty()) fprintf(fp, " contact=\"%s\"", i->second.adminContact.c_str()); } if (!i->second.CC.empty()) fprintf(fp, " country=\"%s\"", i->second.CC.c_str()); fprintf(fp, " age=\"%lu\"", (now - i->second.creation) / 1000); fprintf(fp, " lastupdate=\"%lu\">\n", (now - i->second.lastevent) / 1000); if (i->second.ASM.s.valid) dumpStats(fp, "asm", i->second.ASM.s, now, i->second.sttl, true); if (i->second.SSM.s.valid) dumpStats(fp, "ssm", i->second.SSM.s, now, i->second.sttl, true); fprintf(fp, "\t\t\t</source>\n"); } fprintf(fp, "\t\t</sources>\n"); fprintf(fp, "\t</beacon>\n"); fprintf(fp, "\n"); } for (Sources::const_iterator i = sources.begin(); i != sources.end(); i++) { fprintf(fp, "\t<beacon"); if (i->second.identified) { fprintf(fp, " name=\"%s\"", i->second.name.c_str()); if (!i->second.adminContact.empty()) fprintf(fp, " contact=\"%s\"", i->second.adminContact.c_str()); } fprintf(fp, " addr=\"%s\"", i->first.to_string(tmp, sizeof(tmp))); fprintf(fp, " age=\"%lu\"", (now - i->second.creation) / 1000); fprintf(fp, " rxlocal=\"%s\"", i->second.rxlocal(now) ? "true" : "false"); fprintf(fp, " lastupdate=\"%lu\">\n", (now - i->second.lastevent) / 1000); for (uint32_t k = 0; k < KnownFlags; k++) { if (i->second.Flags & (1 << k)) { fprintf(fp, "\t\t<flag name=\"%s\" value=\"true\" />\n", Flags[k]); } } for (WebSites::const_iterator j = i->second.webSites.begin(); j != i->second.webSites.end(); j++) { const char *typnam = j->first == T_WEBSITE_GENERIC ? "generic" : (j->first == T_WEBSITE_LG ? "lg" : "matrix"); fprintf(fp, "\t\t<website type=\"%s\" url=\"%s\" />\n", typnam, j->second.c_str()); } fprintf(fp, "\t\t<sources>\n"); for (beaconSource::ExternalSources::const_iterator j = i->second.externalSources.begin(); j != i->second.externalSources.end(); j++) { fprintf(fp, "\t\t\t<source"); if (j->second.identified) { fprintf(fp, " name=\"%s\"", j->second.name.c_str()); fprintf(fp, " contact=\"%s\"", j->second.contact.c_str()); } fprintf(fp, " addr=\"%s\"", j->first.to_string(tmp, sizeof(tmp))); fprintf(fp, " age=\"%u\">\n", j->second.age); if (j->second.ASM.valid) dumpStats(fp, "asm", j->second.ASM, now, i->second.sttl, false); if (j->second.SSM.valid) dumpStats(fp, "ssm", j->second.SSM, now, i->second.sttl, false); fprintf(fp, "\t\t\t</source>\n"); } fprintf(fp, "\t\t</sources>\n"); fprintf(fp, "\t</beacon>\n"); } fprintf(fp, "</group>\n</beacons>\n"); fclose(fp); rename(tmpf.c_str(), dumpFile.c_str()); if (!launchSomething.empty()) doLaunchSomething(); }