From ad541c67761b8aa6da1566802c347cac4018d0c2 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Mon, 2 Nov 2026 20:50:24 +0100 Subject: Move the build sources into src/ --- trackerlogic.c | 628 --------------------------------------------------------- 1 file changed, 628 deletions(-) delete mode 100644 trackerlogic.c (limited to 'trackerlogic.c') diff --git a/trackerlogic.c b/trackerlogic.c deleted file mode 100644 index 9565090..0000000 --- a/trackerlogic.c +++ /dev/null @@ -1,628 +0,0 @@ -/* This software was written by Dirk Engling - It is considered beerware. Prost. Skol. Cheers or whatever. */ - -/* System */ -#include -#include -#include -#include -#include - - -/* Opentracker */ -#include "ot_accesslist.h" -#include "ot_clean.h" -#include "ot_fmt.h" -#include "ot_fullscrape.h" -#include "ot_http.h" -#include "ot_ip.h" -#include "ot_livesync.h" -#include "ot_mutex.h" -#include "ot_workqueue.h" -#include "ot_random.h" -#include "ot_stats.h" -#include "ot_udp.h" -#include "ot_vector.h" -#include "trackerlogic.h" - -/* Forward declaration */ -size_t return_peers_for_torrent(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto); - -void free_peerlist(ot_peerlist *peer_list) { - if (peer_list && peer_list->peers.data) { - if (OT_PEERLIST_HASBUCKETS(peer_list)) - vector_clean_list((ot_vector *)peer_list->peers.data, peer_list->peers.size); - else - free(peer_list->peers.data); - } - free(peer_list); -} - -void add_torrent_from_saved_state(ot_hash const hash, ot_time base, size_t down_count) { - int exactmatch; - ot_torrent *torrent; - ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); - - if (!accesslist_hashisvalid(hash)) { - mutex_bucket_unlock_by_hash(hash, 0); - return; - } - - torrent = vector_find_or_insert(torrents_list, (void *)hash, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); - if (!torrent || exactmatch) { - mutex_bucket_unlock_by_hash(hash, 0); - return; - } - - /* Create a new torrent entry, then */ - memset(torrent, 0, sizeof(ot_torrent)); - memcpy(torrent->hash, hash, sizeof(ot_hash)); - - if (!(torrent->peer_list6 = malloc(sizeof(ot_peerlist))) || !(torrent->peer_list4 = malloc(sizeof(ot_peerlist)))) { - vector_remove_torrent(torrents_list, torrent); - mutex_bucket_unlock_by_hash(hash, 0); - return; - } - - memset(torrent->peer_list6, 0, sizeof(ot_peerlist)); - memset(torrent->peer_list4, 0, sizeof(ot_peerlist)); - torrent->peer_list6->base = base; - torrent->peer_list4->base = base; - torrent->peer_list6->down_count = down_count; - torrent->peer_list4->down_count = down_count; - - mutex_bucket_unlock_by_hash(hash, 1); -} - -size_t add_peer_to_torrent_and_return_peers(PROTO_FLAG proto, struct ot_workstruct *ws, size_t amount) { - int exactmatch, delta_torrentcount = 0; - ot_torrent *torrent; - ot_peer *peer_dest; - ot_vector *torrents_list = mutex_bucket_lock_by_hash(*ws->hash); - ot_peerlist *peer_list; - size_t peer_size; /* initialized in next line */ - ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); - - if (!accesslist_hashisvalid(*ws->hash)) { - mutex_bucket_unlock_by_hash(*ws->hash, 0); - if (proto == FLAG_TCP) { - const char invalid_hash[] = "d14:failure reason63:Requested download is not authorized for use with this tracker.e"; - memcpy(ws->reply, invalid_hash, strlen(invalid_hash)); - return strlen(invalid_hash); - } - return 0; - } - - torrent = vector_find_or_insert(torrents_list, (void *)ws->hash, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); - if (!torrent) { - mutex_bucket_unlock_by_hash(*ws->hash, 0); - return 0; - } - - if (!exactmatch) { - /* Create a new torrent entry, then */ - memset(torrent, 0, sizeof(ot_torrent)); - memcpy(torrent->hash, *ws->hash, sizeof(ot_hash)); - - if (!(torrent->peer_list6 = malloc(sizeof(ot_peerlist))) || !(torrent->peer_list4 = malloc(sizeof(ot_peerlist)))) { - vector_remove_torrent(torrents_list, torrent); - mutex_bucket_unlock_by_hash(*ws->hash, 0); - return 0; - } - - memset(torrent->peer_list6, 0, sizeof(ot_peerlist)); - memset(torrent->peer_list4, 0, sizeof(ot_peerlist)); - delta_torrentcount = 1; - } else - clean_single_torrent(torrent); - - torrent->peer_list6->base = time_now_minutes(); - torrent->peer_list4->base = time_now_minutes(); - - peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; - - /* Check for peer in torrent */ - peer_dest = vector_find_or_insert_peer(&(peer_list->peers), peer_src, peer_size, &exactmatch); - if (!peer_dest) { - mutex_bucket_unlock_by_hash(*ws->hash, delta_torrentcount); - return 0; - } - - /* Tell peer that it's fresh */ - OT_PEERTIME(ws->peer, OT_PEER_SIZE6) = 0; - - /* Sanitize flags: Whoever claims to have completed download, must be a seeder */ - if ((OT_PEERFLAG(ws->peer) & (PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING)) == PEER_FLAG_COMPLETED) - OT_PEERFLAG(ws->peer) ^= PEER_FLAG_COMPLETED; - - /* If we hadn't had a match create peer there */ - if (!exactmatch) { - -#ifdef WANT_SYNC_LIVE - if (proto == FLAG_MCA) - OT_PEERFLAG(ws->peer) |= PEER_FLAG_FROM_SYNC; - else - livesync_tell(ws); -#endif - - peer_list->peer_count++; - if (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED) { - peer_list->down_count++; - stats_issue_event(ws, EVENT_COMPLETED, 0, 0); - } - if (OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING) - peer_list->seed_count++; - - } else { - stats_issue_event(ws, EVENT_RENEW, 0, OT_PEERTIME(peer_dest, peer_size)); -#ifdef WANT_SPOT_WOODPECKER - if ((OT_PEERTIME(peer_dest, peer_size) > 0) && (OT_PEERTIME(peer_dest, peer_size) < 20)) - stats_issue_event(ws, EVENT_WOODPECKER, 0, (uintptr_t)&ws->peer); -#endif -#ifdef WANT_SYNC_LIVE - /* Won't live sync peers that come back too fast. Only exception: - fresh "completed" reports */ - if (proto != FLAG_MCA) { - if (OT_PEERTIME(peer_dest, peer_size) > OT_CLIENT_SYNC_RENEW_BOUNDARY || - (!(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED))) - livesync_tell(ws); - } -#endif - - if ((OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING) && !(OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING)) - peer_list->seed_count--; - if (!(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_SEEDING) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_SEEDING)) - peer_list->seed_count++; - if (!(OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED) && (OT_PEERFLAG(ws->peer) & PEER_FLAG_COMPLETED)) { - peer_list->down_count++; - stats_issue_event(ws, EVENT_COMPLETED, 0, 0); - } - if (OT_PEERFLAG_D(peer_dest, peer_size) & PEER_FLAG_COMPLETED) - OT_PEERFLAG(ws->peer) |= PEER_FLAG_COMPLETED; - } - - memcpy(peer_dest, peer_src, peer_size); -#ifdef WANT_SYNC - if (proto == FLAG_MCA) { - mutex_bucket_unlock_by_hash(*ws->hash, delta_torrentcount); - return 0; - } -#endif - - ws->reply_size = return_peers_for_torrent(ws, torrent, amount, ws->reply, proto); - mutex_bucket_unlock_by_hash(*ws->hash, delta_torrentcount); - return ws->reply_size; -} - -static size_t return_peers_all(ot_peerlist *peer_list, size_t peer_size, char *reply) { - size_t bucket, num_buckets = 1; - ot_vector *bucket_list = &peer_list->peers; - size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); - size_t result = compare_size * peer_list->peer_count; - char *r_end = reply + result; - - if (OT_PEERLIST_HASBUCKETS(peer_list)) { - num_buckets = bucket_list->size; - bucket_list = (ot_vector *)bucket_list->data; - } - - for (bucket = 0; bucket < num_buckets; ++bucket) { - ot_peer *peers = bucket_list[bucket].data; - size_t peer_count = bucket_list[bucket].size; - while (peer_count--) { - if (OT_PEERFLAG_D(peers, peer_size) & PEER_FLAG_SEEDING) { - r_end -= compare_size; - memcpy(r_end, peers, compare_size); - } else { - memcpy(reply, peers, compare_size); - reply += compare_size; - } - peers += peer_size; - } - } - return result; -} - -static size_t return_peers_selection(struct ot_workstruct *ws, ot_peerlist *peer_list, size_t peer_size, size_t amount, char *reply) { - size_t bucket_offset, bucket_index = 0, num_buckets = 1; - ot_vector *bucket_list = &peer_list->peers; - unsigned int shifted_pc = peer_list->peer_count; - unsigned int shifted_step = 0; - unsigned int shift = 0; - size_t compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size); - size_t result = compare_size * amount; - char *r_end = reply + result; - - if (OT_PEERLIST_HASBUCKETS(peer_list)) { - num_buckets = bucket_list->size; - bucket_list = (ot_vector *)bucket_list->data; - } - - /* Make fixpoint arithmetic as exact as possible */ -#define MAXPRECBIT (1 << (8 * sizeof(int) - 3)) - while (!(shifted_pc & MAXPRECBIT)) { - shifted_pc <<= 1; - shift++; - } - shifted_step = shifted_pc / amount; -#undef MAXPRECBIT - - /* Initialize somewhere in the middle of peers so that - fixpoint's aliasing doesn't alway miss the same peers */ - bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count; - - while (amount--) { - ot_peer *peer; - - /* This is the aliased, non shifted range, next value may fall into */ - unsigned int diff = (((amount + 1) * shifted_step) >> shift) - ((amount * shifted_step) >> shift); - bucket_offset += 1 + nrand48(ws->rand48_state) % diff; - - while (bucket_offset >= bucket_list[bucket_index].size) { - bucket_offset -= bucket_list[bucket_index].size; - bucket_index = (bucket_index + 1) % num_buckets; - } - peer = (ot_peer*)bucket_list[bucket_index].data + peer_size * bucket_offset; - if (OT_PEERFLAG_D(peer, peer_size) & PEER_FLAG_SEEDING) { - r_end -= compare_size; - memcpy(r_end, peer, compare_size); - } else { - memcpy(reply, peer, compare_size); - reply += compare_size; - } - } - return result; -} - -static size_t return_peers_for_torrent_udp(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply) { - char *r = reply; - size_t peer_size = peer_size_from_peer6(&ws->peer); - ot_peerlist *peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; - size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; - size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; - - if (amount > peer_list->peer_count) - amount = peer_list->peer_count; - - *(uint32_t *)(r + 0) = htonl(OT_CLIENT_REQUEST_INTERVAL_RANDOM); - *(uint32_t *)(r + 4) = htonl(peer_count - seed_count); - *(uint32_t *)(r + 8) = htonl(seed_count); - r += 12; - - if (amount) { - if (amount == peer_list->peer_count) - r += return_peers_all(peer_list, peer_size, r); - else - r += return_peers_selection(ws, peer_list, peer_size, amount, r); - } - return r - reply; -} - -static size_t return_peers_for_torrent_tcp(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply) { - char *r = reply; - const char *r_end = ws->outbuf + G_OUTBUF_SIZE; - int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; - size_t seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; - size_t down_count = torrent->peer_list6->down_count + torrent->peer_list4->down_count; - size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - seed_count; - - /* Simple case: amount of peers in both lists is less than requested, here we return all results */ - size_t amount_v4 = torrent->peer_list4->peer_count; - size_t amount_v6 = torrent->peer_list6->peer_count; - - /* Complex case: both lists have more than enough entries and we need to split between v4 and v6 clients */ - if (amount_v4 + amount_v6 > amount) { - size_t amount_left, percent_v6 = 0, percent_v4 = 0, left_v6, left_v4; - const size_t SCALE = 1024; - - /* If possible, fill at least a quarter of peer from each family */ - if (amount / 4 <= amount_v4) - amount_v4 = amount / 4; - if (amount / 4 <= amount_v6) - amount_v6 = amount / 4; - - /* Fill the rest according to which family's pool provides more peers */ - amount_left = amount - (amount_v4 + amount_v6); - - left_v4 = torrent->peer_list4->peer_count - amount_v4; - left_v6 = torrent->peer_list6->peer_count - amount_v6; - - if (left_v4 + left_v6) { - percent_v4 = (SCALE * left_v4) / (left_v4 + left_v6); - percent_v6 = (SCALE * left_v6) / (left_v4 + left_v6); - } - - amount_v4 += (amount_left * percent_v4) / SCALE; - amount_v6 += (amount_left * percent_v6) / SCALE; - - /* Integer division rounding can leave out a peer */ - if (amount_v4 + amount_v6 < amount && amount_v6 < torrent->peer_list6->peer_count) - ++amount_v6; - if (amount_v4 + amount_v6 < amount && amount_v4 < torrent->peer_list4->peer_count) - ++amount_v4; - } - - fmt_append(&r, r_end, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie", seed_count, down_count, peer_count, erval, - erval / 2); - - if (amount_v4) { - fmt_append(&r, r_end, PEERS_BENCODED4 "%zd:", OT_PEER_COMPARE_SIZE4 * amount_v4); - if (amount_v4 == torrent->peer_list4->peer_count) - r += return_peers_all(torrent->peer_list4, OT_PEER_SIZE4, r); - else - r += return_peers_selection(ws, torrent->peer_list4, OT_PEER_SIZE4, amount_v4, r); - } - - if (amount_v6) { - fmt_append(&r, r_end, PEERS_BENCODED6 "%zd:", OT_PEER_COMPARE_SIZE6 * amount_v6); - if (amount_v6 == torrent->peer_list6->peer_count) - r += return_peers_all(torrent->peer_list6, OT_PEER_SIZE6, r); - else - r += return_peers_selection(ws, torrent->peer_list6, OT_PEER_SIZE6, amount_v6, r); - } - - fmt_append(&r, r_end, "e"); - - return r - reply; -} - -/* Compiles a list of random peers for a torrent - * Reply must have enough space to hold: - * 92 + 6 * amount bytes for TCP/IPv4 - * 92 + 18 * amount bytes for TCP/IPv6 - * 12 + 6 * amount bytes for UDP/IPv4 - * 12 + 18 * amount bytes for UDP/IPv6 - * Does not yet check not to return self - */ -size_t return_peers_for_torrent(struct ot_workstruct *ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto) { - return proto == FLAG_TCP ? return_peers_for_torrent_tcp(ws, torrent, amount, reply) : return_peers_for_torrent_udp(ws, torrent, amount, reply); -} - -/* Fetches scrape info for a specific torrent */ -size_t return_udp_scrape_for_torrent(ot_hash const hash, char *reply) { - int exactmatch, delta_torrentcount = 0; - ot_vector *torrents_list = mutex_bucket_lock_by_hash(hash); - ot_torrent *torrent = vector_binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); - - if (!exactmatch) { - memset(reply, 0, 12); - } else { - uint32_t *r = (uint32_t *)reply; - - if (clean_single_torrent(torrent)) { - vector_remove_torrent(torrents_list, torrent); - memset(reply, 0, 12); - delta_torrentcount = -1; - } else { - r[0] = htonl(torrent->peer_list6->seed_count + torrent->peer_list4->seed_count); - r[1] = htonl(torrent->peer_list6->down_count + torrent->peer_list4->down_count); - r[2] = htonl(torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); - } - } - mutex_bucket_unlock_by_hash(hash, delta_torrentcount); - return 12; -} - -/* Fetches scrape info for a specific torrent */ -void return_tcp_scrape_for_torrent(ot_hash const *hash_list, size_t amount, char **reply, const char *reply_end) { - int exactmatch; - size_t i; - - fmt_append(reply, reply_end, "d5:filesd"); - - for (i = 0; i < amount; ++i) { - int delta_torrentcount = 0; - ot_hash const *hash = hash_list + i; - ot_vector *torrents_list = mutex_bucket_lock_by_hash(*hash); - ot_torrent *torrent = vector_binary_search(hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); - - if (exactmatch) { - if (clean_single_torrent(torrent)) { - vector_remove_torrent(torrents_list, torrent); - delta_torrentcount = -1; - } else { - fmt_append(reply, reply_end, "20:"); - fmt_bytes(reply, reply_end, hash, sizeof(ot_hash)); - fmt_append(reply, reply_end, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", - torrent->peer_list6->seed_count + torrent->peer_list4->seed_count, torrent->peer_list6->down_count + torrent->peer_list4->down_count, - torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - torrent->peer_list6->seed_count - torrent->peer_list4->seed_count); - } - } - mutex_bucket_unlock_by_hash(*hash, delta_torrentcount); - } - - fmt_append(reply, reply_end, "ee"); -} - -static ot_peerlist dummy_list; -size_t remove_peer_from_torrent(PROTO_FLAG proto, struct ot_workstruct *ws) { - int exactmatch; - ot_vector *torrents_list = mutex_bucket_lock_by_hash(*ws->hash); - ot_torrent *torrent = vector_binary_search(ws->hash, torrents_list->data, torrents_list->size, sizeof(ot_torrent), OT_HASH_COMPARE_SIZE, &exactmatch); - ot_peerlist *peer_list = &dummy_list; - size_t peer_size; /* initialized in next line */ - ot_peer const *peer_src = peer_from_peer6(&ws->peer, &peer_size); - size_t peer_count = 0, seed_count = 0; - -#ifdef WANT_SYNC_LIVE - if (proto != FLAG_MCA) { - OT_PEERFLAG(ws->peer) |= PEER_FLAG_STOPPED; - livesync_tell(ws); - } -#endif - - if (exactmatch) { - peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; - switch (vector_remove_peer(&peer_list->peers, peer_src, peer_size)) { - case 2: - peer_list->seed_count--; /* Intentional fallthrough */ - case 1: - peer_list->peer_count--; /* Intentional fallthrough */ - default: - break; - } - - peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; - seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count; - } - - if (proto == FLAG_TCP) { - int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM; - char *r = ws->reply; - - fmt_append(&r, ws->outbuf + G_OUTBUF_SIZE, "d8:completei%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s0:e", seed_count, peer_count - seed_count, - erval, erval / 2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4); - ws->reply_size = r - ws->reply; - } - - /* Handle UDP reply */ - if (proto == FLAG_UDP) { - ((uint32_t *)ws->reply)[2] = htonl(OT_CLIENT_REQUEST_INTERVAL_RANDOM); - ((uint32_t *)ws->reply)[3] = htonl(peer_count - seed_count); - ((uint32_t *)ws->reply)[4] = htonl(seed_count); - ws->reply_size = 20; - } - - mutex_bucket_unlock_by_hash(*ws->hash, 0); - return ws->reply_size; -} - -void iterate_all_torrents(int (*for_each)(ot_torrent *torrent, uintptr_t data), uintptr_t data) { - size_t bucket, j; - - for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { - ot_vector *torrents_list = mutex_bucket_lock(bucket); - ot_torrent *torrents = (ot_torrent *)(torrents_list->data); - - for (j = 0; j < torrents_list->size; ++j) - if (for_each(torrents + j, data)) - break; - - mutex_bucket_unlock(bucket, 0); - if (!g_opentracker_running) - return; - } -} - -ot_peer *peer_from_peer6(ot_peer6 *peer, size_t *peer_size) { - ot_ip6 *ip = (ot_ip6 *)peer; - if (!ip_is_v4mapped(ip)) { - *peer_size = OT_PEER_SIZE6; - return (ot_peer *)peer; - } - *peer_size = OT_PEER_SIZE4; - return (ot_peer *)(((uint8_t *)peer) + 12); -} - -size_t peer_size_from_peer6(ot_peer6 *peer) { - ot_ip6 *ip = (ot_ip6 *)peer; - if (!ip_is_v4mapped(ip)) - return OT_PEER_SIZE6; - return OT_PEER_SIZE4; -} - -#ifdef _DEBUG_RANDOMTORRENTS -void trackerlogic_add_random_torrents(size_t amount) { - struct ot_workstruct ws; - memset(&ws, 0, sizeof(ws)); - - ws.inbuf = malloc(G_INBUF_SIZE); - ws.outbuf = malloc(G_OUTBUF_SIZE); - ws.reply = ws.outbuf; - ws.hash = (ot_hash *)ws.inbuf; - - while (amount--) { - random_bytes(ws.hash, sizeof(ot_hash)); - random_bytes(&ws.peer, sizeof(ws.peer)); - - OT_PEERFLAG(ws.peer) &= PEER_FLAG_SEEDING | PEER_FLAG_COMPLETED | PEER_FLAG_STOPPED; - - add_peer_to_torrent_and_return_peers(FLAG_TCP, &ws, 1); - } - - free(ws.inbuf); - free(ws.outbuf); -} -#endif - -void exerr(const char *message) { - fprintf(stderr, "%s\n", message); - exit(111); -} - -void trackerlogic_init(void) { - g_tracker_id = random_uint32(); - - if (!g_stats_path) - g_stats_path = "stats"; - g_stats_path_len = strlen(g_stats_path); - - /* Initialise background worker threads */ - mutex_init(); - workqueue_init(); - clean_init(); - fullscrape_init(); - accesslist_init(); - livesync_init(); - stats_init(); -} - -int workstruct_init(struct ot_workstruct *ws) { - memset(ws, 0, sizeof(*ws)); - ws->inbuf = malloc(G_INBUF_SIZE); - ws->outbuf = malloc(G_OUTBUF_SIZE); -#ifdef _DEBUG_HTTPERROR - ws->debugbuf = malloc(G_DEBUGBUF_SIZE); -#endif - if (!ws->inbuf || !ws->outbuf) - return -1; - - /* Picking which peers to hand out starts here, so two workers seeded alike - would hand out alike */ - random_bytes(ws->rand48_state, sizeof(ws->rand48_state)); - - stats_counters_register(ws); - return 0; -} - -void workstruct_deinit(struct ot_workstruct *ws) { - /* The tally goes to the global before this struct goes out of scope */ - stats_counters_retire(ws); - - free(ws->inbuf); - free(ws->outbuf); -#ifdef _DEBUG_HTTPERROR - free(ws->debugbuf); -#endif -} - -void trackerlogic_deinit(void) { - int delta_torrentcount = 0; - size_t bucket, j; - - /* Stop the background workers first */ - stats_deinit(); - livesync_deinit(); - accesslist_deinit(); - fullscrape_deinit(); - clean_deinit(); - - /* Free all torrents... */ - for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { - ot_vector *torrents_list = mutex_bucket_lock(bucket); - if (torrents_list->size) { - for (j = 0; j < torrents_list->size; ++j) { - ot_torrent *torrent = ((ot_torrent *)(torrents_list->data)) + j; - free_peerlist(torrent->peer_list6); - free_peerlist(torrent->peer_list4); - delta_torrentcount -= 1; - } - free(torrents_list->data); - } - mutex_bucket_unlock(bucket, delta_torrentcount); - } - - /* Release mutexes */ - workqueue_deinit(); - mutex_deinit(); -} -- cgit v1.3