void Ctransaction::send_scrape(data_ref r) { if (read_int(8, &r[uti_connection_id], r.end()) != connection_id()) return; if (!m_server.config().m_anonymous_scrape) { send_error(r, "access denied"); return; } const int cb_d = 2 << 10; char d[cb_d]; write_int(4, d + uto_action, uta_scrape); write_int(4, d + uto_transaction_id, read_int(4, &r[uti_transaction_id], r.end())); char* w = d + utos_size; for (r.advance_begin(utis_size); r.size() >= 20 && w + 12 <= d + cb_d; r.advance_begin(20)) { if (const Cserver::t_torrent* t = m_server.torrent(r.substr(0, 20).s())) { w = write_int(4, w, t->seeders); w = write_int(4, w, t->completed); w = write_int(4, w, t->leechers); } else { w = write_int(4, w, 0); w = write_int(4, w, 0); w = write_int(4, w, 0); } } m_server.stats().scraped_udp++; send(data_ref(d, w)); }
void Ctransaction::send_connect(data_ref r) { if (read_int(8, &r[uti_connection_id], r.end()) != 0x41727101980ll) return; const int cb_d = 2 << 10; char d[cb_d]; write_int(4, d + uto_action, uta_connect); write_int(4, d + uto_transaction_id, read_int(4, &r[uti_transaction_id], r.end())); write_int(8, d + utoc_connection_id, connection_id()); send(data_ref(d, utoc_size)); }
void Ctransaction::send_announce(data_ref r) { if (read_int(8, &r[uti_connection_id], r.end()) != connection_id()) return; if (!m_server.config().m_anonymous_announce) { send_error(r, "access denied"); return; } Ctracker_input ti; ti.m_downloaded = read_int(8, &r[utia_downloaded], r.end()); ti.m_event = static_cast<Ctracker_input::t_event>(read_int(4, &r[utia_event], r.end())); ti.m_info_hash.assign(reinterpret_cast<const char*>(&r[utia_info_hash]), 20); ti.m_ipa = read_int(4, &r[utia_ipa], r.end()) && is_private_ipa(m_a.sin_addr.s_addr) ? htonl(read_int(4, &r[utia_ipa], r.end())) : m_a.sin_addr.s_addr; ti.m_left = read_int(8, &r[utia_left], r.end()); ti.m_num_want = read_int(4, &r[utia_num_want], r.end()); ti.m_peer_id.assign(reinterpret_cast<const char*>(&r[utia_peer_id]), 20); ti.m_port = htons(read_int(2, &r[utia_port], r.end())); ti.m_uploaded = read_int(8, &r[utia_uploaded], r.end()); std::string error = m_server.insert_peer(ti, true, NULL); if (!error.empty()) { send_error(r, error); return; } const Cserver::t_torrent* torrent = m_server.torrent(ti.m_info_hash); if (!torrent) return; const int cb_d = 2 << 10; char d[cb_d]; write_int(4, d + uto_action, uta_announce); write_int(4, d + uto_transaction_id, read_int(4, &r[uti_transaction_id], r.end())); write_int(4, d + utoa_interval, m_server.config().m_announce_interval); write_int(4, d + utoa_leechers, torrent->leechers); write_int(4, d + utoa_seeders, torrent->seeders); std::string peers = torrent->select_peers(ti); memcpy(d + utoa_size, peers.data(), peers.size()); send(data_ref(d, d + utoa_size + peers.size())); }
int main(int argc, char **argv){ /* extract program name from path. e.g. /path/to/MArCd -> MArCd */ const char* separator = strrchr(argv[0], '/'); if ( separator ){ program_name = separator + 1; } else { program_name = argv[0]; } struct filter filter; if ( filter_from_argv(&argc, argv, &filter) != 0 ){ return 0; /* error already shown */ } int op, option_index = -1; while ( (op = getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1 ){ switch (op){ case 0: /* long opt */ case '?': /* unknown opt */ break; case '1': case '2': case '3': case '4': { const unsigned int mask = (7<<FORMAT_LAYER_BIT); flags &= ~mask; /* reset all layer bits */ flags |= (op-'0')<<FORMAT_LAYER_BIT; break; } case 'd': /* --calender */ flags |= FORMAT_DATE_STR | FORMAT_DATE_UTC; break; case 'D': /* --localtime */ flags |= FORMAT_DATE_STR | FORMAT_DATE_LOCALTIME; break; case 'a': /* --absolute */ flags &= ~FORMAT_REL_TIMESTAMP; break; case 'r': /* --relative */ flags |= FORMAT_REL_TIMESTAMP; break; case 'H': /* --headers */ flags |= FORMAT_HEADER; break; case 'p': /* --packets */ max_packets = atoi(optarg); break; case 'c': /* --packets */ max_matched_packets = atoi(optarg); break; case 't': /* --timeout */ { int tmp = atoi(optarg); timeout.tv_sec = tmp / 1000; timeout.tv_usec = tmp % 1000 * 1000; } break; case 'x': /* --hexdump */ flags |= FORMAT_HEXDUMP; break; case 'i': /* --iface */ iface = optarg; break; case ARGUMENT_VERSION: /* --version */ show_version(); return 0; case 'h': /* --help */ show_usage(); return 0; default: fprintf (stderr, "%s: argument '-%c' declared but not handled\n", argv[0], op); } } int ret; /* Open stream(s) */ struct stream* stream; if ( (ret=stream_from_getopt(&stream, argv, optind, argc, iface, "-", program_name, 0)) != 0 ) { return ret; /* Error already shown */ } const stream_stat_t* stat = stream_get_stat(stream); stream_print_info(stream, stderr); /* handle C-c */ signal(SIGINT, handle_sigint); /* setup formatter */ struct format format; format_setup(&format, flags); uint64_t matched = 0; while ( keep_running ) { /* A short timeout is used to allow the application to "breathe", i.e * terminate if SIGINT was received. */ struct timeval tv = timeout; /* Read the next packet */ cap_head* cp; ret = stream_read(stream, &cp, NULL, &tv); if ( ret == EAGAIN ){ continue; /* timeout */ } else if ( ret != 0 ){ break; /* shutdown or error */ } /* identify connection even if filter doesn't match so id will be * deterministic when changing the filter */ connection_id(cp); if ( filter_match(&filter, cp->payload, cp) ){ format_pkg(stdout, &format, cp); matched++; } else { format_ignore(stdout, &format, cp); } if ( max_packets > 0 && stat->matched >= max_packets) { /* Read enough pkts lets break. */ break; } if ( max_matched_packets > 0 && matched >= max_matched_packets) { /* Read enough pkts lets break. */ break; } } /* if ret == -1 the stream was closed properly (e.g EOF or TCP shutdown) * In addition EINTR should not give any errors because it is implied when the * user presses C-c */ if ( ret > 0 && ret != EINTR ){ fprintf(stderr, "stream_read() returned 0x%08X: %s\n", ret, caputils_error_string(ret)); } /* Write stats */ fprintf(stderr, "%"PRIu64" packets read.\n", stat->read); fprintf(stderr, "%"PRIu64" packets matched filter.\n", matched); /* Release resources */ stream_close(stream); filter_close(&filter); return 0; }