From ce247fc7d59ccc195c7e1c0e49861c443b8d526c Mon Sep 17 00:00:00 2001 From: Naim A Date: Mon, 26 Nov 2012 23:33:12 +0200 Subject: [PATCH] Various changes. SEGFAULT fixed. --- src/db/database.h | 4 +- src/db/driver_sqlite.c | 48 +++++++++++++++++++----- src/main.c | 29 ++++++++++++++- src/multiplatform.h | 1 + src/udpTracker.c | 84 ++++++++++++++++++++++++++++++++++-------- src/udpTracker.h | 15 +++++++- 6 files changed, 151 insertions(+), 30 deletions(-) diff --git a/src/db/database.h b/src/db/database.h index b74c2c2..f175ec4 100644 --- a/src/db/database.h +++ b/src/db/database.h @@ -36,7 +36,7 @@ int db_add_peer (dbConnection *, uint8_t [20], db_peerEntry*); * lst: pointer to an array whose maximum size is passed to sZ. * sZ returns the amount of peers returned. */ -int db_load_peers (dbConnection *, uint8_t [20], db_peerEntry **lst, int *sZ); +int db_load_peers (dbConnection *, uint8_t [20], db_peerEntry *lst, int *sZ); int db_get_stats (dbConnection *, uint8_t [20], uint32_t *seeders, uint32_t *leechers, uint32_t *completed); @@ -45,4 +45,6 @@ int db_get_stats (dbConnection *, uint8_t [20], uint32_t *seeders, uint32_t *lee */ int db_cleanup (dbConnection *); +int db_remove_peer (dbConnection *, uint8_t hash [20], db_peerEntry *); + #endif /* DATABASE_H_ */ diff --git a/src/db/driver_sqlite.c b/src/db/driver_sqlite.c index 0cb218b..b7c0294 100644 --- a/src/db/driver_sqlite.c +++ b/src/db/driver_sqlite.c @@ -14,7 +14,7 @@ struct dbConnection static const char hexadecimal[] = "0123456789abcdef"; -static void _to_hex_str (const uint8_t *hash, char *data) +void _to_hex_str (const uint8_t *hash, char *data) { int i; for (i = 0;i < 20;i++) @@ -34,7 +34,7 @@ static int _db_make_torrent_table (sqlite3 *db, char *hash) strcat(sql, hash); strcat (sql, "' ("); - strcat (sql, "peer_id blob(20) UNIQUE," + strcat (sql, "peer_id blob(20)," "ip blob(4)," "port blob(2)," "uploaded blob(8)," // uint64 @@ -42,12 +42,12 @@ static int _db_make_torrent_table (sqlite3 *db, char *hash) "left blob(8)," "last_seen INT DEFAULT 0"); - strcat(sql, ")"); + strcat(sql, ", CONSTRAINT c1 UNIQUE (ip,port) ON CONFLICT REPLACE)"); // create table. char *err_msg; int r = sqlite3_exec(db, sql, NULL, NULL, &err_msg); -// printf("E:%s\n", err_msg); + printf("E:%s\n", err_msg); return r; } @@ -131,7 +131,7 @@ int db_add_peer (dbConnection *db, uint8_t info_hash[20], db_peerEntry *pE) return r; } -int db_load_peers (dbConnection *db, uint8_t info_hash[20], db_peerEntry **lst, int *sZ) +int db_load_peers (dbConnection *db, uint8_t info_hash[20], db_peerEntry *lst, int *sZ) { char sql [1000]; sql[0] = '\0'; @@ -150,16 +150,16 @@ int db_load_peers (dbConnection *db, uint8_t info_hash[20], db_peerEntry **lst, int i = 0; int r; - while (1) + while (*sZ > i) { r = sqlite3_step(stmt); if (r == SQLITE_ROW) { - const void *ip = sqlite3_column_blob (stmt, 0); - const void *port = sqlite3_column_blob (stmt, 1); + const char *ip = (const char*)sqlite3_column_blob (stmt, 0); + const char *port = (const char*)sqlite3_column_blob (stmt, 1); - memcpy(&lst[i]->ip, ip, 4); - memcpy(&lst[i]->port, port, 2); + memcpy(&lst[i].ip, ip, 4); + memcpy(&lst[i].port, port, 2); i++; } @@ -167,6 +167,8 @@ int db_load_peers (dbConnection *db, uint8_t info_hash[20], db_peerEntry **lst, break; } + printf("%d Clients Dumped.\n", i); + sqlite3_finalize(stmt); *sZ = i; @@ -286,3 +288,29 @@ int db_cleanup (dbConnection *db) return 0; } + +int db_remove_peer (dbConnection *db, uint8_t hash[20], db_peerEntry *pE) +{ + char sql [1000]; + char xHash [50]; + + _to_hex_str (hash, xHash); + + strcpy (sql, "DELETE FROM 't"); + strcat (sql, xHash); + strcat (sql, "' WHERE ip=? AND port=? AND peer_id=?"); + + sqlite3_stmt *stmt; + + sqlite3_prepare (db->db, sql, -1, &stmt, NULL); + + sqlite3_bind_blob(stmt, 0, (const void*)&pE->ip, 4, NULL); + sqlite3_bind_blob(stmt, 1, (const void*)&pE->port, 2, NULL); + sqlite3_bind_blob(stmt, 2, (const void*)pE->peer_id, 20, NULL); + + sqlite3_step(stmt); + + sqlite3_finalize(stmt); + + return 0; +} diff --git a/src/main.c b/src/main.c index 25dfe46..9f342f5 100644 --- a/src/main.c +++ b/src/main.c @@ -18,17 +18,42 @@ #include #include -int main(void) +int main(int argc, char *argv[]) { printf("UDP BitTorrentTracker %s\t\tCopyright: (C) 2012 Naim Abda.\n\n", VERSION); +#ifdef linux + if (argc > 1) + { + if (strcmp(argv[1], "d") == 0) + { + pid_t pid; + pid = fork (); + + if (pid < 0) + { + printf ("Failed to start daemon.\n"); + exit (EXIT_FAILURE); + } + if (pid > 0) + { + printf("Daemon Started; pid=%d.\n", pid); + fclose (stdin); + fclose (stdout); + fclose (stderr); + exit (EXIT_SUCCESS); + } + } + } +#endif + #ifdef WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(2, 2), &wsadata); #endif udpServerInstance usi; - UDPTracker_init(&usi, 6969, 1); + UDPTracker_init(&usi, 6969, 5); if (UDPTracker_start(&usi) != 0) { diff --git a/src/multiplatform.h b/src/multiplatform.h index 32e6526..5a21192 100644 --- a/src/multiplatform.h +++ b/src/multiplatform.h @@ -18,6 +18,7 @@ #define INVALID_SOCKET 0 #define SOCKET_ERROR -1 #define DWORD uint64_t +#define closesocket(s) close(s) typedef struct hostent HOSTENT; typedef struct sockaddr SOCKADDR; typedef struct sockaddr_in SOCKADDR_IN; diff --git a/src/udpTracker.c b/src/udpTracker.c index 6472230..4f1ff6e 100644 --- a/src/udpTracker.c +++ b/src/udpTracker.c @@ -145,6 +145,30 @@ static int _handle_connection (udpServerInstance *usi, SOCKADDR_IN *remote, char return 0; } +static int _is_good_peer (uint32_t ip, uint16_t port) +{ + SOCKADDR_IN addr; + addr.sin_family = AF_INET; +#ifdef WIN32 + addr.sin_addr.S_un.S_addr = htonl( ip ); +#elif defined (linux) + addr.sin_addr.s_addr = htonl( ip ); +#endif + addr.sin_port = htons (port); + + SOCKET cli = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (cli == INVALID_SOCKET) + return 1; + if (connect(cli, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) + { + closesocket (cli); + return 1; + } + printf ("Client Verified.\n"); + closesocket (cli); + return 0; +} + static int _handle_announce (udpServerInstance *usi, SOCKADDR_IN *remote, char *data) { AnnounceRequest *req = (AnnounceRequest*)data; @@ -162,20 +186,36 @@ static int _handle_announce (udpServerInstance *usi, SOCKADDR_IN *remote, char * req->uploaded = m_hton64 (req->uploaded); req->num_want = m_hton32 (req->num_want); req->left = m_hton64 (req->left); + if (req->ip_address == 0) // default + { + req->ip_address = m_hton32 (remote->sin_addr.s_addr); + } +// if (_is_good_peer(req->ip_address, req->port) != 0) +// { +// _send_error (usi, remote, req->transaction_id, "Couldn't verify your client."); +// return 0; +// } // load peers int q = 30; if (req->num_want >= 1) q = min (q, req->num_want); - db_peerEntry *peers = malloc (sizeof(db_peerEntry) * q); - - db_load_peers(usi->conn, req->info_hash, &peers, &q); -// printf("%d peers found.\n", q); - + db_peerEntry *peers = NULL; int bSize = 20; // header is 20 bytes - bSize += (6 * q); // + 6 bytes per peer. + + if (req->event == 3) // stopped; they don't need anymore peers! + { + q = 0; // don't need any peers! + } + else + { + peers = malloc (sizeof(db_peerEntry) * q); + db_load_peers(usi->conn, req->info_hash, peers, &q); + } + + bSize += (6 * q); // + 6 bytes per peer (ip->4, port->2). uint32_t seeders, leechers, completed; db_get_stats (usi->conn, req->info_hash, &seeders, &leechers, &completed); @@ -206,24 +246,29 @@ static int _handle_announce (udpServerInstance *usi, SOCKADDR_IN *remote, char * // printf("%u.%u.%u.%u:%u\n", buff[20 + x], buff[21 + x], buff[22 + x], buff[23 + x], peers[i].port); } - free (peers); + + if (peers != NULL) + free (peers); + sendto(usi->sock, (char*)buff, bSize, 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN)); + // Add peer to list: db_peerEntry pE; pE.downloaded = req->downloaded; pE.uploaded = req->uploaded; pE.left = req->left; pE.peer_id = req->peer_id; - if (req->ip_address == 0) // default - { - pE.ip = m_hton32 (remote->sin_addr.s_addr); - } - else - { - pE.ip = req->ip_address; - } + pE.ip = req->ip_address; pE.port = req->port; + + if (req->event == 3) // stopped + { + // just remove client from swarm, and return empty peer list... + db_remove_peer(usi->conn, req->info_hash, &pE); + return 0; + } + db_add_peer(usi->conn, req->info_hash, &pE); return 0; @@ -233,7 +278,14 @@ static int _handle_scrape (udpServerInstance *usi, SOCKADDR_IN *remote, char *da { ScrapeRequest *sR = (ScrapeRequest*)data; - _send_error (usi, remote, sR->transaction_id, "Scrape wasn't implemented yet!"); +// _send_error (usi, remote, sR->transaction_id, "Scrape wasn't implemented yet!"); + + ScrapeResponse resp; + resp.resp_part = NULL; + resp.action = 2; + resp.transaction_id = sR->transaction_id; + + sendto (usi->sock, (const char*)&resp, 8, 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN)); return 0; } diff --git a/src/udpTracker.h b/src/udpTracker.h index ad659c3..f910c26 100644 --- a/src/udpTracker.h +++ b/src/udpTracker.h @@ -59,8 +59,20 @@ struct udp_scrape_request uint64_t connection_id; uint32_t action; uint32_t transaction_id; + struct reqD { + uint8_t info_hash [20]; + } *req_part; +}; - uint8_t *torrent_list_data; +struct udp_scrape_response +{ + uint32_t action; + uint32_t transaction_id; + struct respD { + uint32_t seeders; + uint32_t completed; + uint32_t leechers; + } *resp_part; }; struct udp_error_response @@ -89,6 +101,7 @@ typedef struct udp_connection_response ConnectionResponse; typedef struct udp_announce_request AnnounceRequest; typedef struct udp_announce_response AnnounceResponse; typedef struct udp_scrape_request ScrapeRequest; +typedef struct udp_scrape_response ScrapeResponse; typedef struct udp_error_response ErrorResponse; void UDPTracker_init (udpServerInstance *, uint16_t port, uint8_t threads);