diff --git a/src/db/database.cpp b/src/db/database.cpp
new file mode 100644
index 0000000..a521a9f
--- /dev/null
+++ b/src/db/database.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright © 2012,2013 Naim A.
+ *
+ * This file is part of UDPT.
+ *
+ * UDPT is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * UDPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with UDPT. If not, see .
+ */
+
+#include "database.hpp"
+
+namespace UDPT
+{
+ namespace Data
+ {
+ DatabaseDriver::DatabaseDriver(Settings::SettingClass *sc, bool isDynamic)
+ {
+ this->dClass = sc;
+ this->is_dynamic = isDynamic;
+ }
+
+ bool DatabaseDriver::addTorrent(uint8_t hash [20])
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::removeTorrent(uint8_t hash[20])
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::isDynamic()
+ {
+ return this->is_dynamic;
+ }
+
+ bool DatabaseDriver::genConnectionId(uint64_t *cid, uint32_t ip, uint16_t port)
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::verifyConnectionId(uint64_t cid, uint32_t ip, uint16_t port)
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::updatePeer(uint8_t peer_id [20], uint8_t info_hash [20],
+ uint32_t ip, uint16_t port,
+ int64_t downloaded, int64_t left, int64_t uploaded,
+ enum TrackerEvents event)
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::removePeer (uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port)
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::getTorrentInfo (TorrentEntry *e)
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::getPeers (uint8_t info_hash [20], int *max_count, PeerEntry *pe)
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ void DatabaseDriver::cleanup()
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ bool DatabaseDriver::isTorrentAllowed(uint8_t info_hash[20])
+ {
+ throw DatabaseException (DatabaseException::E_NOT_IMPLEMENTED);
+ }
+
+ DatabaseDriver::~DatabaseDriver()
+ {
+ }
+
+ /*-- Exceptions --*/
+ static const char *EMessages[] = {
+ "Unknown Error",
+ "Not Implemented",
+ "Failed to connect to database"
+ };
+
+ DatabaseException::DatabaseException()
+ {
+ this->errorNum = E_UNKNOWN;
+ }
+
+ DatabaseException::DatabaseException(enum EType e)
+ {
+ this->errorNum = e;
+ }
+
+ enum DatabaseException::EType DatabaseException::getErrorType()
+ {
+ return this->errorNum;
+ }
+
+ const char* DatabaseException::getErrorMessage()
+ {
+ return EMessages[this->errorNum];
+ }
+ };
+};
diff --git a/src/db/database.h b/src/db/database.h
deleted file mode 100644
index f731eea..0000000
--- a/src/db/database.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright © 2012,2013 Naim A.
- *
- * This file is part of UDPT.
- *
- * UDPT is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * UDPT is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with UDPT. If not, see .
- */
-
-#ifndef DATABASE_H_
-#define DATABASE_H_
-
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct dbConnection dbConnection;
-
-/**
- * Opens a database connection.
- * @param pdb Pointer to database instance.
- * @param cStr Connection string for the active driver.
- * @return 0 on success; otherwise non-zero.
- */
-int db_open (dbConnection **pdb, const char *cStr);
-
-/**
- * Closes the database connection.
- * @param db Database instance.
- * @return 0 on success; otherwise non-zero.
- */
-int db_close (dbConnection *db);
-
-typedef struct {
- uint8_t *peer_id;
- uint64_t downloaded;
- uint64_t uploaded;
- uint64_t left;
-
- uint32_t ip; // currently only support IPv4.
- uint16_t port;
-} db_peerEntry;
-
-/**
- * Adds/Updates the list of peers.
- * @param db The database's instance.
- * @param hash The info_hash of the torrent.
- * @param pE Peer's information.
- * @return 0 on success; otherwise non-zero.
- */
-int db_add_peer (dbConnection *db, uint8_t hash[20], db_peerEntry *pE);
-
-/**
- * Loads peers for the requested torrent.
- * @param db Database instance.
- * @param hash The info_hash of the requested torrent.
- * @param lst A allocated array to store results in.
- * @param sZ in: The maximum amount of entries to load. out: Amount of loaded entries.
- * @return 0 on success; otherwise non-zero.
- */
-int db_load_peers (dbConnection *db, uint8_t hash[20], db_peerEntry *lst, int *sZ);
-
-/**
- * Gets stats for the requested torrent.
- * @param db The Database connection
- * @param hash info_hash of the torrent.
- * @param seeders Returns the Seeders for the requested torrent.
- * @param leechers Returns the Leechers for the requested torrent.
- * @param completed Returns the count of completed downloaded reported.
- * @return 0 on success, otherwise non-zero.
- */
-int db_get_stats (dbConnection *db, uint8_t hash[20], int32_t *seeders, int32_t *leechers, int32_t *completed);
-
-/**
- * Maintenance routine, Calculates stats & releases space from old entries.
- * @param db The database connection.
- * @return 0 on success; otherwise non-zero.
- */
-int db_cleanup (dbConnection *db);
-
-/**
- * Deletes a peer from the database.
- * @param db Database connection
- * @param hash info_hash of the torrent.
- * @param pE The peer's information.
- * @return 0 on success; otherwise non-zero.
- */
-int db_remove_peer (dbConnection *db, uint8_t hash [20], db_peerEntry *pE);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* DATABASE_H_ */
diff --git a/src/db/database.hpp b/src/db/database.hpp
new file mode 100644
index 0000000..ac4f9e5
--- /dev/null
+++ b/src/db/database.hpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright © 2012,2013 Naim A.
+ *
+ * This file is part of UDPT.
+ *
+ * UDPT is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * UDPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with UDPT. If not, see .
+ */
+
+#ifndef DATABASE_HPP_
+#define DATABASE_HPP_
+
+#include "../settings.hpp"
+
+namespace UDPT
+{
+ namespace Data
+ {
+ class DatabaseException
+ {
+ public:
+ enum EType {
+ E_UNKNOWN = 0, // Unknown error
+ E_NOT_IMPLEMENTED = 1, // not implemented
+ E_CONNECTION_FAILURE = 2
+ };
+
+ DatabaseException ();
+ DatabaseException (EType);
+ EType getErrorType ();
+ const char* getErrorMessage ();
+ private:
+ EType errorNum;
+ };
+
+ class DatabaseDriver
+ {
+ public:
+ typedef struct {
+ uint8_t *info_hash;
+ int32_t seeders;
+ int32_t leechers;
+ int32_t completed;
+ } TorrentEntry;
+ typedef struct {
+ uint32_t ip;
+ uint16_t port;
+ } PeerEntry;
+
+ enum TrackerEvents {
+ EVENT_UNSPEC = 0,
+ EVENT_COMPLETE = 1,
+ EVENT_START = 2,
+ EVENT_STOP = 3
+ };
+
+ /**
+ * Opens the DB's connection
+ * @param dClass Settings class ('database' class).
+ */
+ DatabaseDriver (Settings::SettingClass *dClass, bool isDynamic = false);
+
+ /**
+ * Adds a torrent to the Database. automatically done if in dynamic mode.
+ * @param hash The info_hash of the torrent.
+ * @return true on success. false on failure.
+ */
+ virtual bool addTorrent (uint8_t hash[20]);
+
+ /**
+ * Removes a torrent from the database. should be used only for non-dynamic trackers or by cleanup.
+ * @param hash The info_hash to drop.
+ * @return true if torrent's database was dropped or no longer exists. otherwise false (shouldn't happen - critical)
+ */
+ virtual bool removeTorrent (uint8_t hash[20]);
+
+ /**
+ * Checks if the Database is acting as a dynamic tracker DB.
+ * @return true if dynamic. otherwise false.
+ */
+ bool isDynamic ();
+
+ /**
+ * Checks if the torrent can be used in the tracker.
+ * @param info_hash The torrent's info_hash.
+ * @return true if allowed. otherwise false.
+ */
+ virtual bool isTorrentAllowed (uint8_t info_hash [20]);
+
+ /**
+ * Generate a Connection ID for the peer.
+ * @param connectionId (Output) the generated connection ID.
+ * @param ip The peer's IP (requesting peer. not remote)
+ * @param port The peer's IP (remote port if tracker accepts)
+ * @return
+ */
+ virtual bool genConnectionId (uint64_t *connectionId, uint32_t ip, uint16_t port);
+
+ virtual bool verifyConnectionId (uint64_t connectionId, uint32_t ip, uint16_t port);
+
+ /**
+ * Updates/Adds a peer to/in the database.
+ * @param peer_id the peer's peer_id
+ * @param info_hash the torrent info_hash
+ * @param ip IP of peer (remote ip if tracker accepts)
+ * @param port TCP port of peer (remote port if tracker accepts)
+ * @param downloaded total Bytes downloaded
+ * @param left total bytes left
+ * @param uploaded total bytes uploaded
+ * @return true on success, false on failure.
+ */
+ virtual bool updatePeer (uint8_t peer_id [20], uint8_t info_hash [20],
+ uint32_t ip, uint16_t port,
+ int64_t downloaded, int64_t left, int64_t uploaded,
+ enum TrackerEvents event);
+
+ /**
+ * Remove a peer from a torrent (if stop action occurred, or if peer is inactive in cleanup)
+ * @param peer_id The peer's peer_id
+ * @param info_hash Torrent's info_hash
+ * @param ip The IP of the peer (remote IP if tracker accepts)
+ * @param port The TCP port (remote port if tracker accepts)
+ * @return true on success. false on failure (shouldn't happen - critical)
+ */
+ virtual bool removePeer (uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port);
+
+ /**
+ * Gets stats on a torrent
+ * @param e TorrentEntry, only this info_hash has to be set
+ * @return true on success, false on failure.
+ */
+ virtual bool getTorrentInfo (TorrentEntry *e);
+
+ /**
+ * Gets a list of peers from the database.
+ * @param info_hash The torrent's info_hash
+ * @param max_count The maximum amount of peers to load from the database. The amount of loaded peers is returned through this variable.
+ * @param pe The list of peers. Must be pre-allocated to the size of max_count.
+ * @return true on success, otherwise false (shouldn't happen).
+ */
+ virtual bool getPeers (uint8_t info_hash [20], int *max_count, PeerEntry *pe);
+
+ /**
+ * Cleanup the database.
+ * Other actions may be locked when using this depending on the driver.
+ */
+ virtual void cleanup ();
+
+ /**
+ * Closes the connections, and releases all other resources.
+ */
+ virtual ~DatabaseDriver ();
+
+ protected:
+ Settings::SettingClass *dClass;
+ private:
+ bool is_dynamic;
+ };
+ };
+};
+
+
+#endif /* DATABASE_HPP_ */
diff --git a/src/db/driver_sqlite.c b/src/db/driver_sqlite.c
deleted file mode 100644
index 56aef7a..0000000
--- a/src/db/driver_sqlite.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright © 2012,2013 Naim A.
- *
- * This file is part of UDPT.
- *
- * UDPT is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * UDPT is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with UDPT. If not, see .
- */
-
-#include "database.h"
-#include "../multiplatform.h"
-#include "../tools.h"
-#include
-#include
-#include
-#include
-#include
-
-struct dbConnection
-{
- sqlite3 *db;
- HANDLE janitor;
-};
-
-static const char hexadecimal[] = "0123456789abcdef";
-
-void _to_hex_str (const uint8_t *hash, char *data)
-{
- int i;
- for (i = 0;i < 20;i++)
- {
- data[i * 2] = hexadecimal[hash[i] / 16];
- data[i * 2 + 1] = hexadecimal[hash[i] % 16];
- }
- data[40] = '\0';
-}
-
-static int _db_make_torrent_table (sqlite3 *db, char *hash)
-{
- char sql [2000];
- char *err_msg;
- int r;
-
- sql[0] = '\0';
-
- strcat(sql, "CREATE TABLE IF NOT EXISTS 't");
- strcat(sql, hash);
- strcat (sql, "' (");
-
- strcat (sql, "peer_id blob(20),"
- "ip blob(4),"
- "port blob(2),"
- "uploaded blob(8)," // uint64
- "downloaded blob(8),"
- "left blob(8),"
- "last_seen INT DEFAULT 0");
-
- strcat(sql, ", CONSTRAINT c1 UNIQUE (ip,port) ON CONFLICT REPLACE)");
-
- // create table.
- r = sqlite3_exec(db, sql, NULL, NULL, &err_msg);
- printf("E:%s\n", err_msg);
-
- return r;
-}
-
-static void _db_setup (sqlite3 *db)
-{
- sqlite3_exec(db, "CREATE TABLE stats ("
- "info_hash blob(20) UNIQUE,"
- "completed INTEGER DEFAULT 0,"
- "leechers INTEGER DEFAULT 0,"
- "seeders INTEGER DEFAULT 0,"
- "last_mod INTEGER DEFAULT 0"
- ")", NULL, NULL, NULL);
-}
-
-int db_open (dbConnection **db, const char *cStr)
-{
- FILE *f;
- int doSetup, // check if to build DB, or it already exists?
- r;
-
- f = fopen (cStr, "rb");
- doSetup = 0;
- if (f == NULL)
- doSetup = 1;
- else
- fclose (f);
-
- *db = malloc (sizeof(struct dbConnection));
- r = sqlite3_open (cStr, &((*db)->db));
- if (doSetup)
- _db_setup((*db)->db);
-
- return r;
-}
-
-int db_close (dbConnection *db)
-{
- int r = sqlite3_close(db->db);
- free (db);
- return r;
-}
-
-int db_add_peer (dbConnection *db, uint8_t info_hash[20], db_peerEntry *pE)
-{
- char xHash [50]; // we just need 40 + \0 = 41.
- sqlite3_stmt *stmt;
- char sql [1000];
- int r;
-
- char *hash = xHash;
- to_hex_str(info_hash, hash);
-
- _db_make_torrent_table(db->db, hash);
-
-
- sql[0] = '\0';
- strcat(sql, "REPLACE INTO 't");
- strcat(sql, hash);
- strcat(sql, "' (peer_id,ip,port,uploaded,downloaded,left,last_seen) VALUES (?,?,?,?,?,?,?)");
-
-// printf("IP->%x::%u\n", pE->ip, pE->port);
-
- sqlite3_prepare(db->db, sql, -1, &stmt, NULL);
-
- sqlite3_bind_blob(stmt, 1, (void*)pE->peer_id, 20, NULL);
- sqlite3_bind_blob(stmt, 2, (void*)&pE->ip, 4, NULL);
- sqlite3_bind_blob(stmt, 3, (void*)&pE->port, 2, NULL);
- sqlite3_bind_blob(stmt, 4, (void*)&pE->uploaded, 8, NULL);
- sqlite3_bind_blob(stmt, 5, (void*)&pE->downloaded, 8, NULL);
- sqlite3_bind_blob(stmt, 6, (void*)&pE->left, 8, NULL);
- sqlite3_bind_int(stmt, 7, time(NULL));
-
- r = sqlite3_step(stmt);
- sqlite3_finalize(stmt);
-
- strcpy(sql, "REPLACE INTO stats (info_hash,last_mod) VALUES (?,?)");
- sqlite3_prepare (db->db, sql, -1, &stmt, NULL);
- sqlite3_bind_blob (stmt, 1, hash, 20, NULL);
- sqlite3_bind_int (stmt, 2, time(NULL));
- sqlite3_step (stmt);
- sqlite3_finalize (stmt);
-
- return r;
-}
-
-int db_load_peers (dbConnection *db, uint8_t info_hash[20], db_peerEntry *lst, int *sZ)
-{
- char sql [1000];
- char hash [50];
- sqlite3_stmt *stmt;
- int r,
- i;
-
- sql[0] = '\0';
-
- to_hex_str(info_hash, hash);
-
- strcat(sql, "SELECT ip,port FROM 't");
- strcat(sql, hash);
- strcat(sql, "' LIMIT ?");
-
- sqlite3_prepare(db->db, sql, -1, &stmt, NULL);
- sqlite3_bind_int(stmt, 1, *sZ);
-
- i = 0;
- while (*sZ > i)
- {
- r = sqlite3_step(stmt);
- if (r == SQLITE_ROW)
- {
- 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);
-
- i++;
- }
- else
- break;
- }
-
- printf("%d Clients Dumped.\n", i);
-
- sqlite3_finalize(stmt);
-
- *sZ = i;
-
- return 0;
-}
-
-int db_get_stats (dbConnection *db, uint8_t hash[20], int32_t *seeders, int32_t *leechers, int32_t *completed)
-{
- const char sql[] = "SELECT seeders,leechers,completed FROM 'stats' WHERE info_hash=?";
- sqlite3_stmt *stmt;
-
- *seeders = 0;
- *leechers = 0;
- *completed = 0;
-
-
- sqlite3_prepare (db->db, sql, -1, &stmt, NULL);
- sqlite3_bind_blob (stmt, 1, (void*)hash, 20, NULL);
-
- if (sqlite3_step(stmt) == SQLITE_ROW)
- {
- *seeders = sqlite3_column_int (stmt, 0);
- *leechers = sqlite3_column_int (stmt, 1);
- *completed = sqlite3_column_int (stmt, 2);
- }
-
- sqlite3_finalize (stmt);
-
- return 0;
-}
-
-int db_cleanup (dbConnection *db)
-{
- const char sql[] = "SELECT info_hash FROM stats WHERE last_mod";
- char hash [50],
- temp [1000];
- sqlite3_stmt *stmt;
- int timeframe;
- uint32_t leechers, seeders;
- sqlite3_stmt *sTmp, *uStat;
-
- return 0; // TODO: Fix problems and than allow use of this function.
- printf("Cleanup...\n");
-
- timeframe = time(NULL);
-
- // remove "dead" torrents (non-active for two hours).
- sqlite3_prepare (db->db, sql, -1, &stmt, NULL);
- sqlite3_bind_int (stmt, 1, timeframe - 7200);
-
- while (sqlite3_step(stmt) == SQLITE_ROW)
- {
- to_hex_str(sqlite3_column_blob(stmt, 0), hash);
-
- // drop table:
- strcpy(temp, "DROP TABLE IF EXISTS 't");
- strcat(temp, hash);
- strcat(temp, "'");
- sqlite3_exec(db->db, temp, NULL, NULL, NULL);
- }
- sqlite3_finalize (stmt);
-
- // update 'dead' torrents
- sqlite3_prepare(db->db, "UPDATE stats SET seeders=0,leechers=0 WHERE last_mod", -1, &stmt, NULL);
- sqlite3_bind_int (stmt, 1, timeframe - 7200);
- sqlite3_step (stmt);
- sqlite3_finalize (stmt);
-
- // update regular torrents.
- sqlite3_prepare(db->db, "SELECT info_hash FROM stats WHERE last_mod>=?", -1, &stmt, NULL);
- sqlite3_bind_int (stmt, 1, timeframe - 7200);
-
- sqlite3_prepare (db->db, "UPDATE stats SET seeders=?,leechers=?,last_mod=? WHERE info_hash=?", -1, &uStat, NULL);
-
- while (sqlite3_step(stmt) == SQLITE_ROW)
- {
- uint8_t *binHash = (uint8_t*)sqlite3_column_blob(stmt, 0);
- to_hex_str (binHash, hash);
-
- // total users...
- strcpy (temp, "SELECT COUNT(*) FROM 't");
- strcat (temp, hash);
- strcat (temp, "'");
-
- sqlite3_prepare (db->db, temp, -1, &sTmp, NULL);
- if (sqlite3_step(sTmp) == SQLITE_ROW)
- {
- leechers = sqlite3_column_int (sTmp, 0);
- }
- sqlite3_finalize (sTmp);
-
- // seeders...
- strcpy (temp, "SELECT COUNT(*) FROM 't");
- strcat (temp, hash);
- strcat (temp, "' WHERE left=0");
-
- sqlite3_prepare (db->db, temp, -1, &sTmp, NULL);
- if (sqlite3_step(sTmp) == SQLITE_ROW)
- {
- seeders = sqlite3_column_int (sTmp, 0);
- }
- sqlite3_finalize (sTmp);
-
- leechers -= seeders;
-
- sqlite3_bind_int (uStat, 1, seeders);
- sqlite3_bind_int (uStat, 2, leechers);
- sqlite3_bind_int (uStat, 3, timeframe);
- sqlite3_bind_blob (uStat, 4, binHash, 20, NULL);
- sqlite3_step (uStat);
- sqlite3_reset (uStat);
-
- printf("%s: %d seeds/%d leechers;\n", hash, seeders, leechers);
- }
- sqlite3_finalize (stmt);
-
- sqlite3_finalize (stmt);
-
- return 0;
-}
-
-int db_remove_peer (dbConnection *db, uint8_t hash[20], db_peerEntry *pE)
-{
- char sql [1000];
- char xHash [50];
- sqlite3_stmt *stmt;
-
- _to_hex_str (hash, xHash);
-
- strcpy (sql, "DELETE FROM 't");
- strcat (sql, xHash);
- strcat (sql, "' WHERE ip=? AND port=? AND peer_id=?");
-
- 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/db/driver_sqlite.cpp b/src/db/driver_sqlite.cpp
new file mode 100644
index 0000000..8d6f83e
--- /dev/null
+++ b/src/db/driver_sqlite.cpp
@@ -0,0 +1,430 @@
+/*
+ * Copyright © 2012,2013 Naim A.
+ *
+ * This file is part of UDPT.
+ *
+ * UDPT is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * UDPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with UDPT. If not, see .
+ */
+
+#include "driver_sqlite.hpp"
+#include "../multiplatform.h"
+#include "../tools.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+namespace UDPT
+{
+ namespace Data
+ {
+ static const char hexadecimal[] = "0123456789abcdef";
+
+ static char* _to_hex_str (const uint8_t *hash, char *data)
+ {
+ int i;
+ for (i = 0;i < 20;i++)
+ {
+ data[i * 2] = hexadecimal[hash[i] / 16];
+ data[i * 2 + 1] = hexadecimal[hash[i] % 16];
+ }
+ data[40] = '\0';
+ return data;
+ }
+
+ static uint8_t* _hash_to_bin (const char *hash, uint8_t *data)
+ {
+ for (int i = 0;i < 20;i++)
+ {
+ data [i] = 0;
+ char a = hash[i * 2];
+ char b = hash[i * 2 + 1];
+
+ assert ( (a >= 'a' && a <= 'f') || (a >= '0' && a <= '9') );
+ assert ( (b >= 'a' && b <= 'f') || (b >= '0' && b <= '9') );
+
+ data[i] = ( (a >= '0' && a <= 'f') ? (a - '0') : (a - 'f' + 10) );
+ data[i] <<= 4;
+ data[i] = ( (b >= '0' && b <= 'f') ? (b - '0') : (b - 'f' + 10) );
+ }
+
+ return data;
+ }
+
+ SQLite3Driver::SQLite3Driver (Settings::SettingClass *sc, bool isDyn) : DatabaseDriver(sc, isDyn)
+ {
+ int r;
+ bool doSetup;
+
+ fstream fCheck;
+ string filename = sc->get("file");
+
+ fCheck.open(filename.c_str(), ios::binary | ios::in);
+ if (fCheck.is_open())
+ {
+ doSetup = false;
+ fCheck.close();
+ }
+ else
+ doSetup = true;
+
+ r = sqlite3_open(filename.c_str(), &this->db);
+ if (r != SQLITE_OK)
+ {
+ sqlite3_close(this->db);
+ throw DatabaseException (DatabaseException::E_CONNECTION_FAILURE);
+ }
+
+ if (doSetup)
+ this->doSetup();
+ }
+
+ void SQLite3Driver::doSetup()
+ {
+// cout << "Creating DB..." << endl;
+ char *eMsg = NULL;
+ // for quicker stats.
+ sqlite3_exec(this->db, "CREATE TABLE stats ("
+ "info_hash blob(20) UNIQUE,"
+ "completed INTEGER DEFAULT 0,"
+ "leechers INTEGER DEFAULT 0,"
+ "seeders INTEGER DEFAULT 0,"
+ "last_mod INTEGER DEFAULT 0"
+ ")", NULL, NULL, &eMsg);
+// cout << "stats: " << (eMsg == NULL ? "OK" : eMsg) << endl;
+ // for non-Dynamic trackers
+ sqlite3_exec(this->db, "CREATE TABLE torrents ("
+ "info_hash blob(20) UNIQUE,"
+ "created INTEGER"
+ ")", NULL, NULL, &eMsg);
+// cout << "torrents: " << (eMsg == NULL ? "OK" : eMsg) << endl;
+ }
+
+ bool SQLite3Driver::getTorrentInfo(TorrentEntry *e)
+ {
+ bool gotInfo = false;
+
+ const char sql[] = "SELECT seeders,leechers,completed FROM 'stats' WHERE info_hash=?";
+ sqlite3_stmt *stmt;
+
+ e->seeders = 0;
+ e->leechers = 0;
+ e->completed = 0;
+
+
+ sqlite3_prepare (this->db, sql, -1, &stmt, NULL);
+ sqlite3_bind_blob (stmt, 1, (void*)e->info_hash, 20, NULL);
+
+ if (sqlite3_step(stmt) == SQLITE_ROW)
+ {
+ e->seeders = sqlite3_column_int (stmt, 0);
+ e->leechers = sqlite3_column_int (stmt, 1);
+ e->completed = sqlite3_column_int (stmt, 2);
+
+ gotInfo = true;
+ }
+
+ sqlite3_finalize (stmt);
+
+ return gotInfo;
+ }
+
+ bool SQLite3Driver::getPeers (uint8_t info_hash [20], int *max_count, PeerEntry *pe)
+ {
+ char sql [1000];
+ char hash [50];
+ sqlite3_stmt *stmt;
+ int r,
+ i;
+
+ sql[0] = '\0';
+
+ to_hex_str(info_hash, hash);
+
+ strcat(sql, "SELECT ip,port FROM 't");
+ strcat(sql, hash);
+ strcat(sql, "' LIMIT ?");
+
+ sqlite3_prepare(this->db, sql, -1, &stmt, NULL);
+ sqlite3_bind_int(stmt, 1, *max_count);
+
+ i = 0;
+ while (*max_count > i)
+ {
+ r = sqlite3_step(stmt);
+ if (r == SQLITE_ROW)
+ {
+ const char *ip = (const char*)sqlite3_column_blob (stmt, 0);
+ const char *port = (const char*)sqlite3_column_blob (stmt, 1);
+
+ memcpy(&pe[i].ip, ip, 4);
+ memcpy(&pe[i].port, port, 2);
+
+ i++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ printf("%d Clients Dumped.\n", i);
+
+ sqlite3_finalize(stmt);
+
+ *max_count = i;
+
+ return true;
+ }
+
+ bool SQLite3Driver::updatePeer(uint8_t peer_id[20], uint8_t info_hash[20], uint32_t ip, uint16_t port, int64_t downloaded, int64_t left, int64_t uploaded, enum TrackerEvents event)
+ {
+ char xHash [50]; // we just need 40 + \0 = 41.
+ sqlite3_stmt *stmt;
+ char sql [1000];
+ int r;
+
+ char *hash = xHash;
+ to_hex_str(info_hash, hash);
+
+ addTorrent (info_hash);
+
+
+ sql[0] = '\0';
+ strcat(sql, "REPLACE INTO 't");
+ strcat(sql, hash);
+ strcat(sql, "' (peer_id,ip,port,uploaded,downloaded,left,last_seen) VALUES (?,?,?,?,?,?,?)");
+
+ // printf("IP->%x::%u\n", pE->ip, pE->port);
+
+ sqlite3_prepare(this->db, sql, -1, &stmt, NULL);
+
+ sqlite3_bind_blob(stmt, 1, (void*)peer_id, 20, NULL);
+ sqlite3_bind_blob(stmt, 2, (void*)&ip, 4, NULL);
+ sqlite3_bind_blob(stmt, 3, (void*)&port, 2, NULL);
+ sqlite3_bind_blob(stmt, 4, (void*)&uploaded, 8, NULL);
+ sqlite3_bind_blob(stmt, 5, (void*)&downloaded, 8, NULL);
+ sqlite3_bind_blob(stmt, 6, (void*)&left, 8, NULL);
+ sqlite3_bind_int(stmt, 7, time(NULL));
+
+ r = sqlite3_step(stmt);
+ sqlite3_finalize(stmt);
+
+ strcpy(sql, "REPLACE INTO stats (info_hash,last_mod) VALUES (?,?)");
+ sqlite3_prepare (this->db, sql, -1, &stmt, NULL);
+ sqlite3_bind_blob (stmt, 1, hash, 20, NULL);
+ sqlite3_bind_int (stmt, 2, time(NULL));
+ sqlite3_step (stmt);
+ sqlite3_finalize (stmt);
+
+ return r;
+ }
+
+ bool SQLite3Driver::addTorrent (uint8_t info_hash[20])
+ {
+ char xHash [41];
+ char *err_msg;
+ int r;
+
+ _to_hex_str(info_hash, xHash);
+
+ // if non-dynamic, called only when adding to DB.
+ if (!this->isDynamic())
+ {
+ sqlite3_stmt *stmt;
+ sqlite3_prepare(this->db, "INSERT INTO torrents (info_hash,created) VALUES (?,?)", -1, &stmt, NULL);
+ sqlite3_bind_blob(stmt, 1, info_hash, 20, NULL);
+ sqlite3_bind_int(stmt, 1, time(NULL));
+ sqlite3_step(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ string sql = "CREATE TABLE IF NOT EXISTS 't";
+ sql += xHash;
+ sql += "' (";
+ sql += "peer_id blob(20),"
+ "ip blob(4),"
+ "port blob(2),"
+ "uploaded blob(8)," // uint64
+ "downloaded blob(8),"
+ "left blob(8),"
+ "last_seen INT DEFAULT 0";
+
+ sql += ", CONSTRAINT c1 UNIQUE (ip,port) ON CONFLICT REPLACE)";
+
+ // create table.
+ r = sqlite3_exec(this->db, sql.c_str(), NULL, NULL, &err_msg);
+ printf("E:%s\n", err_msg);
+
+ return (r == SQLITE_OK);
+ }
+
+ bool SQLite3Driver::isTorrentAllowed(uint8_t info_hash[20])
+ {
+ if (this->isDynamic())
+ return true;
+ sqlite3_stmt *stmt;
+ sqlite3_prepare(this->db, "SELECT COUNT(*) FROM torrents WHERE info_hash=?", -1, &stmt, NULL);
+ sqlite3_bind_blob(stmt, 1, info_hash, 20, NULL);
+ sqlite3_step(stmt);
+
+ int n = sqlite3_column_int(stmt, 1);
+ sqlite3_finalize(stmt);
+ return (n == 1);
+ }
+
+ void SQLite3Driver::cleanup()
+ {
+ int exp = time (NULL) - 7200; // 2 hours, expired.
+
+ // drop all peers with no activity for 2 hours.
+ sqlite3_stmt *getTables;
+ // torrent table names: t
+ sqlite3_prepare(this->db, "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 't________________________________________'", -1, &getTables, NULL);
+
+ uint8_t buff [20];
+ sqlite3_stmt *updateStats;
+ assert (sqlite3_prepare(this->db, "REPLACE INTO stats (info_hash,seeders,leechers,last_mod) VALUES (?,?,?,?)", -1, &updateStats, NULL) == SQLITE_OK);
+
+
+ while (sqlite3_step(getTables) == SQLITE_ROW)
+ {
+ char* tblN = (char*)sqlite3_column_text(getTables, 0);
+ stringstream sStr;
+ sStr << "DELETE FROM " << tblN << " WHERE last_seen<" << exp;
+
+ assert (sqlite3_exec(this->db, sStr.str().c_str(), NULL, NULL, NULL) == SQLITE_OK);
+
+ sStr.str (string());
+ sStr << "SELECT left,COUNT(*) FROM " << tblN << " GROUP BY left==0";
+
+ sqlite3_stmt *collectStats;
+
+ sqlite3_prepare(this->db, sStr.str().c_str(), sStr.str().length(), &collectStats, NULL);
+ cout << "[" << sqlite3_errmsg(this->db) << "]" << endl;
+ int seeders = 0, leechers = 0;
+ while (sqlite3_step(collectStats) == SQLITE_ROW) // expecting two results.
+ {
+ if (sqlite3_column_int(collectStats, 0) == 0)
+ seeders = sqlite3_column_int (collectStats, 1);
+ else
+ leechers = sqlite3_column_int (collectStats, 1);
+ }
+ sqlite3_finalize(collectStats);
+
+ sqlite3_bind_blob(updateStats, 1, _hash_to_bin((const char*)(tblN + 1), buff), 20, NULL);
+ sqlite3_bind_int(updateStats, 2, seeders);
+ sqlite3_bind_int(updateStats, 3, leechers);
+ sqlite3_bind_int(updateStats, 4, time (NULL));
+
+ sqlite3_step(updateStats);
+ sqlite3_reset (updateStats);
+ }
+ sqlite3_finalize(updateStats);
+ sqlite3_finalize(getTables);
+ }
+
+ bool SQLite3Driver::removeTorrent(uint8_t info_hash[20])
+ {
+ // if non-dynamic, remove from table
+ if (!this->isDynamic())
+ {
+ sqlite3_stmt *stmt;
+ sqlite3_prepare(this->db, "DELETE FROM torrents WHERE info_hash=?", -1, &stmt, NULL);
+ sqlite3_bind_blob(stmt, 1, info_hash, 20, NULL);
+ sqlite3_step(stmt);
+ sqlite3_finalize(stmt);
+ }
+
+ // remove from stats
+ sqlite3_stmt *rmS;
+ if (sqlite3_prepare(this->db, "DELETE FROM stats WHERE info_hash=?", -1, &rmS, NULL) != SQLITE_OK)
+ {
+ sqlite3_finalize(rmS);
+ return false;
+ }
+ sqlite3_bind_blob(rmS, 1, (const void*)info_hash, 20, NULL);
+ sqlite3_step(rmS);
+ sqlite3_finalize(rmS);
+
+ // remove table
+ string str = "DROP TABLE IF EXISTS 't";
+ char buff [41];
+ str += _to_hex_str(info_hash, buff);
+ str += "'";
+
+ sqlite3_exec(this->db, str.c_str(), NULL, NULL, NULL);
+
+ return true;
+ }
+
+ bool SQLite3Driver::removePeer(uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port)
+ {
+ char sql [1000];
+ char xHash [50];
+ sqlite3_stmt *stmt;
+
+ _to_hex_str (info_hash, xHash);
+
+ strcpy (sql, "DELETE FROM 't");
+ strcat (sql, xHash);
+ strcat (sql, "' WHERE ip=? AND port=? AND peer_id=?");
+
+ sqlite3_prepare (this->db, sql, -1, &stmt, NULL);
+
+ sqlite3_bind_blob(stmt, 0, (const void*)&ip, 4, NULL);
+ sqlite3_bind_blob(stmt, 1, (const void*)&port, 2, NULL);
+ sqlite3_bind_blob(stmt, 2, (const void*)peer_id, 20, NULL);
+
+ sqlite3_step(stmt);
+
+ sqlite3_finalize(stmt);
+
+ return true;
+ }
+
+ static uint64_t _genCiD (uint32_t ip, uint16_t port)
+ {
+ uint64_t x;
+ x = (time(NULL) / 3600) * port; // x will probably overload.
+ x = (ip ^ port);
+ x <<= 16;
+ x |= (~port);
+ return x;
+ }
+
+ bool SQLite3Driver::genConnectionId (uint64_t *connectionId, uint32_t ip, uint16_t port)
+ {
+ *connectionId = _genCiD(ip, port);
+ return true;
+ }
+
+ bool SQLite3Driver::verifyConnectionId(uint64_t cId, uint32_t ip, uint16_t port)
+ {
+ if (cId == _genCiD(ip, port))
+ return true;
+ else
+ return false;
+ }
+
+ SQLite3Driver::~SQLite3Driver()
+ {
+ sqlite3_close(this->db);
+ }
+ };
+};
diff --git a/src/db/driver_sqlite.hpp b/src/db/driver_sqlite.hpp
new file mode 100644
index 0000000..34b28d9
--- /dev/null
+++ b/src/db/driver_sqlite.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2012,2013 Naim A.
+ *
+ * This file is part of UDPT.
+ *
+ * UDPT is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * UDPT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with UDPT. If not, see .
+ */
+
+#ifndef DATABASE_H_
+#define DATABASE_H_
+
+#include
+#include "database.hpp"
+#include
+
+namespace UDPT
+{
+ namespace Data
+ {
+ class SQLite3Driver : public DatabaseDriver
+ {
+ public:
+ SQLite3Driver (Settings::SettingClass *sc, bool isDyn = false);
+ bool addTorrent (uint8_t info_hash[20]);
+ bool removeTorrent (uint8_t info_hash[20]);
+ bool genConnectionId (uint64_t *connId, uint32_t ip, uint16_t port);
+ bool verifyConnectionId (uint64_t connId, uint32_t ip, uint16_t port);
+ bool updatePeer (uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port, int64_t downloaded, int64_t left, int64_t uploaded, enum TrackerEvents event);
+ bool removePeer (uint8_t peer_id [20], uint8_t info_hash [20], uint32_t ip, uint16_t port);
+ bool getTorrentInfo (TorrentEntry *e);
+ bool isTorrentAllowed (uint8_t info_hash[20]);
+ bool getPeers (uint8_t info_hash [20], int *max_count, PeerEntry *pe);
+ void cleanup ();
+
+ ~SQLite3Driver ();
+ private:
+ sqlite3 *db;
+
+ void doSetup ();
+ };
+ };
+};
+
+#endif /* DATABASE_H_ */
diff --git a/src/udpTracker.cpp b/src/udpTracker.cpp
index 55efe2b..391a80f 100644
--- a/src/udpTracker.cpp
+++ b/src/udpTracker.cpp
@@ -25,6 +25,7 @@
#include
using namespace std;
+using namespace UDPT::Data;
#define UDP_BUFFER_SIZE 2048
@@ -91,8 +92,6 @@ namespace UDPT
this->port = (s_port == "" ? 6969 : atoi (s_port.c_str()));
this->thread_count = (s_threads == "" ? 5 : atoi (s_threads.c_str())) + 1;
- cout << "port=" << this->port << endl;
-
this->threads = new HANDLE[this->thread_count];
this->isRunning = false;
@@ -131,7 +130,7 @@ namespace UDPT
cout << "Thread (" << ( i + 1) << "/" << ((int)this->thread_count) << ") terminated." << endl;
}
if (this->conn != NULL)
- db_close(this->conn);
+ delete this->conn;
delete[] this->threads;
}
@@ -148,11 +147,7 @@ namespace UDPT
if (sock == INVALID_SOCKET)
return START_ESOCKET_FAILED;
- #ifdef WIN32
- recvAddr.sin_addr.S_un.S_addr = 0L;
- #elif defined (linux)
recvAddr.sin_addr.s_addr = 0L;
- #endif
recvAddr.sin_family = AF_INET;
recvAddr.sin_port = m_hton16 (this->port);
@@ -173,11 +168,7 @@ namespace UDPT
this->sock = sock;
- dbname = this->o_settings->get ("database", "file");
- if (dbname == "")
- dbname = "tracker.db";
-
- db_open(&this->conn, dbname.c_str());
+ this->conn = new Data::SQLite3Driver (this->o_settings->getClass("database"), true);
this->isRunning = true;
cout << "Starting maintenance thread (1/" << ((int)this->thread_count) << ")" << endl;
@@ -186,7 +177,7 @@ namespace UDPT
#ifdef WIN32
this->threads[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_maintainance_start, (LPVOID)this, 0, NULL);
#elif defined (linux)
- pthread_create (&usi->threads[0], NULL, _maintainance_start, usi);
+ pthread_create (&usi->threads[0], NULL, _maintainance_start, (void*)this);
#endif
for (i = 1;i < this->thread_count; i++)
@@ -195,26 +186,13 @@ namespace UDPT
#ifdef WIN32
this->threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_thread_start, (LPVOID)this, 0, NULL);
#elif defined (linux)
- pthread_create (&(this->threads[i]), NULL, _thread_start, this);
+ pthread_create (&(this->threads[i]), NULL, _thread_start, (void*)this);
#endif
}
return START_OK;
}
-static uint64_t _get_connID (SOCKADDR_IN *remote)
-{
- int base;
- uint64_t x;
-
- base = time(NULL);
- base /= 3600; // changes every hour.
-
- x = base;
- x += remote->sin_addr.s_addr;
- return x;
-}
-
int UDPTracker::sendError (UDPTracker *usi, SOCKADDR_IN *remote, uint32_t transactionID, const string &msg)
{
struct udp_error_response error;
@@ -248,7 +226,13 @@ static uint64_t _get_connID (SOCKADDR_IN *remote)
resp.action = m_hton32(0);
resp.transaction_id = req->transaction_id;
- resp.connection_id = _get_connID(remote);
+
+ if (!usi->conn->genConnectionId(&resp.connection_id,
+ m_hton32(remote->sin_addr.s_addr),
+ m_hton16(remote->sin_port)))
+ {
+ return 1;
+ }
sendto(usi->sock, (char*)&resp, sizeof(ConnectionResponse), 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN));
@@ -262,16 +246,16 @@ static uint64_t _get_connID (SOCKADDR_IN *remote)
int q, // peer counts
bSize, // message size
i; // loop index
- db_peerEntry *peers;
- int32_t seeders,
- leechers,
- completed;
- db_peerEntry pE; // info for DB
+ DatabaseDriver::PeerEntry *peers;
+ DatabaseDriver::TorrentEntry tE;
+
uint8_t buff [1028]; // Reasonable buffer size. (header+168 peers)
req = (AnnounceRequest*)data;
- if (req->connection_id != _get_connID(remote))
+ if (!usi->conn->verifyConnectionId(req->connection_id,
+ m_hton32(remote->sin_addr.s_addr),
+ m_hton16(remote->sin_port)))
{
return 1;
}
@@ -291,25 +275,54 @@ static uint64_t _get_connID (SOCKADDR_IN *remote)
return 0;
}
+ if (!usi->conn->isTorrentAllowed(req->info_hash))
+ {
+ UDPTracker::sendError(usi, remote, req->transaction_id, "info_hash not registered.");
+ return 0;
+ }
+
// load peers
q = 30;
if (req->num_want >= 1)
q = min (q, req->num_want);
- peers = (db_peerEntry*)malloc (sizeof(db_peerEntry) * q);
+ peers = new DatabaseDriver::PeerEntry [q];
- db_load_peers(usi->conn, req->info_hash, peers, &q);
+
+ DatabaseDriver::TrackerEvents event;
+ switch (req->event)
+ {
+ case 1:
+ event = DatabaseDriver::EVENT_COMPLETE;
+ break;
+ case 2:
+ event = DatabaseDriver::EVENT_START;
+ break;
+ case 3:
+ event = DatabaseDriver::EVENT_STOP;
+ break;
+ default:
+ event = DatabaseDriver::EVENT_UNSPEC;
+ break;
+ }
+
+ if (event == DatabaseDriver::EVENT_STOP)
+ q = 0; // no need for peers when stopping.
+
+ if (q > 0)
+ usi->conn->getPeers(req->info_hash, &q, peers);
bSize = 20; // header is 20 bytes
bSize += (6 * q); // + 6 bytes per peer.
- db_get_stats (usi->conn, req->info_hash, &seeders, &leechers, &completed);
+ tE.info_hash = req->info_hash;
+ usi->conn->getTorrentInfo(&tE);
resp = (AnnounceResponse*)buff;
resp->action = m_hton32(1);
resp->interval = m_hton32 ( usi->announce_interval );
- resp->leechers = m_hton32(leechers);
- resp->seeders = m_hton32 (seeders);
+ resp->leechers = m_hton32(tE.leechers);
+ resp->seeders = m_hton32 (tE.seeders);
resp->transaction_id = req->transaction_id;
for (i = 0;i < q;i++)
@@ -328,24 +341,17 @@ static uint64_t _get_connID (SOCKADDR_IN *remote)
buff[25 + x] = (peers[i].port & 0xff);
}
- free (peers);
+ delete[] peers;
sendto(usi->sock, (char*)buff, bSize, 0, (SOCKADDR*)remote, sizeof(SOCKADDR_IN));
- // Add peer to list:
- pE.downloaded = req->downloaded;
- pE.uploaded = req->uploaded;
- pE.left = req->left;
- pE.peer_id = req->peer_id;
+ // update DB.
+ uint32_t ip;
if (req->ip_address == 0) // default
- {
- pE.ip = m_hton32 (remote->sin_addr.s_addr);
- }
+ ip = m_hton32 (remote->sin_addr.s_addr);
else
- {
- pE.ip = req->ip_address;
- }
- pE.port = req->port;
- db_add_peer(usi->conn, req->info_hash, &pE);
+ ip = req->ip_address;
+ usi->conn->updatePeer(req->peer_id, req->info_hash, ip, req->port,
+ req->downloaded, req->left, req->uploaded, event);
return 0;
}
@@ -373,6 +379,13 @@ static uint64_t _get_connID (SOCKADDR_IN *remote)
return 0;
}
+ if (!usi->conn->verifyConnectionId(sR->connection_id,
+ m_hton32(remote->sin_addr.s_addr),
+ m_hton16(remote->sin_port)))
+ {
+ return 1;
+ }
+
// get torrent count.
c = v / 20;
@@ -382,7 +395,6 @@ static uint64_t _get_connID (SOCKADDR_IN *remote)
for (i = 0;i < c;i++)
{
- int32_t s, c, l;
int32_t *seeders,
*completed,
*leechers;
@@ -398,11 +410,17 @@ static uint64_t _get_connID (SOCKADDR_IN *remote)
completed = (int32_t*)&buffer[i*12+12];
leechers = (int32_t*)&buffer[i*12+16];
- db_get_stats (usi->conn, hash, &s, &l, &c);
+ DatabaseDriver::TorrentEntry tE;
+ tE.info_hash = hash;
+ if (!usi->conn->getTorrentInfo(&tE))
+ {
+ sendError(usi, remote, sR->transaction_id, "Scrape Failed: couldn't retrieve torrent data");
+ return 0;
+ }
- *seeders = m_hton32 (s);
- *completed = m_hton32 (c);
- *leechers = m_hton32 (l);
+ *seeders = m_hton32 (tE.seeders);
+ *completed = m_hton32 (tE.completed);
+ *leechers = m_hton32 (tE.leechers);
}
cout.flush();
@@ -436,7 +454,7 @@ static int _isIANA_IP (uint32_t ip)
}
}
- cout << ":: " << (void*)remote->sin_addr.s_addr << ": " << remote->sin_port << " ACTION=" << action << endl;
+ cout << ":: " << (void*)m_hton32(remote->sin_addr.s_addr) << ": " << m_hton16(remote->sin_port) << " ACTION=" << action << endl;
if (action == 0 && r >= 16)
return UDPTracker::handleConnection (usi, remote, data);
@@ -499,10 +517,10 @@ static int _isIANA_IP (uint32_t ip)
while (usi->isRunning)
{
- db_cleanup (usi->conn);
+ usi->conn->cleanup();
#ifdef WIN32
- Sleep (usi->cleanup_interval * 1000); // wait 2 minutes between every cleanup.
+ Sleep (usi->cleanup_interval * 1000);
#elif defined (linux)
sleep (usi->cleanup_interval);
#else
diff --git a/src/udpTracker.hpp b/src/udpTracker.hpp
index 864886f..f0bd18e 100644
--- a/src/udpTracker.hpp
+++ b/src/udpTracker.hpp
@@ -23,7 +23,7 @@
#include
#include "multiplatform.h"
-#include "db/database.h"
+#include "db/driver_sqlite.hpp"
#include "settings.hpp"
#include
@@ -142,7 +142,7 @@ namespace UDPT
uint8_t settings;
Settings *o_settings;
- dbConnection *conn;
+ Data::DatabaseDriver *conn;
#ifdef WIN32
static DWORD _thread_start (LPVOID arg);