Merging with HTTP API
This commit is contained in:
commit
52a399acc1
|
@ -239,16 +239,12 @@ namespace UDPT
|
||||||
|
|
||||||
_to_hex_str(info_hash, xHash);
|
_to_hex_str(info_hash, xHash);
|
||||||
|
|
||||||
// if non-dynamic, called only when adding to DB.
|
sqlite3_stmt *stmt;
|
||||||
if (!this->isDynamic())
|
sqlite3_prepare(this->db, "INSERT INTO torrents (info_hash,created) VALUES (?,?)", -1, &stmt, NULL);
|
||||||
{
|
sqlite3_bind_blob(stmt, 1, info_hash, 20, NULL);
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_bind_int(stmt, 1, time(NULL));
|
||||||
sqlite3_prepare(this->db, "INSERT INTO torrents (info_hash,created) VALUES (?,?)", -1, &stmt, NULL);
|
sqlite3_step(stmt);
|
||||||
sqlite3_bind_blob(stmt, 1, info_hash, 20, NULL);
|
sqlite3_finalize(stmt);
|
||||||
sqlite3_bind_int(stmt, 1, time(NULL));
|
|
||||||
sqlite3_step(stmt);
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
string sql = "CREATE TABLE IF NOT EXISTS 't";
|
string sql = "CREATE TABLE IF NOT EXISTS 't";
|
||||||
sql += xHash;
|
sql += xHash;
|
||||||
|
@ -338,14 +334,11 @@ namespace UDPT
|
||||||
bool SQLite3Driver::removeTorrent(uint8_t info_hash[20])
|
bool SQLite3Driver::removeTorrent(uint8_t info_hash[20])
|
||||||
{
|
{
|
||||||
// if non-dynamic, remove from table
|
// 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_stmt *stmt;
|
sqlite3_bind_blob(stmt, 1, info_hash, 20, NULL);
|
||||||
sqlite3_prepare(this->db, "DELETE FROM torrents WHERE info_hash=?", -1, &stmt, NULL);
|
sqlite3_step(stmt);
|
||||||
sqlite3_bind_blob(stmt, 1, info_hash, 20, NULL);
|
sqlite3_finalize(stmt);
|
||||||
sqlite3_step(stmt);
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove from stats
|
// remove from stats
|
||||||
sqlite3_stmt *rmS;
|
sqlite3_stmt *rmS;
|
||||||
|
|
|
@ -1,203 +1,503 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2012,2013 Naim A.
|
* Copyright © 2013 Naim A.
|
||||||
*
|
*
|
||||||
* This file is part of UDPT.
|
* This file is part of UDPT.
|
||||||
*
|
*
|
||||||
* UDPT is free software: you can redistribute it and/or modify
|
* UDPT is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* UDPT is distributed in the hope that it will be useful,
|
* UDPT is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
|
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "httpserver.hpp"
|
#include <iostream>
|
||||||
#include "../tools.h"
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
namespace UDPT
|
#include <cstring>
|
||||||
{
|
#include <map>
|
||||||
namespace API
|
#include "httpserver.hpp"
|
||||||
{
|
|
||||||
HTTPServer::HTTPServer (uint16_t port, int threads)
|
using namespace std;
|
||||||
{
|
|
||||||
int r;
|
namespace UDPT
|
||||||
|
{
|
||||||
this->thread_count = threads;
|
namespace Server
|
||||||
this->threads = new HANDLE [threads];
|
{
|
||||||
|
/* HTTPServer */
|
||||||
SOCKADDR_IN endpoint;
|
HTTPServer::HTTPServer (uint16_t port, int threads)
|
||||||
endpoint.sin_family = AF_INET;
|
{
|
||||||
endpoint.sin_port = m_hton16(port);
|
int r;
|
||||||
endpoint.sin_addr.s_addr = 0L;
|
SOCKADDR_IN sa;
|
||||||
|
|
||||||
this->sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
this->thread_count = threads;
|
||||||
if (this->sock == INVALID_SOCKET)
|
this->threads = new HANDLE[threads];
|
||||||
throw APIException("Invalid Socket");
|
this->isRunning = false;
|
||||||
|
|
||||||
r = bind(this->sock, (SOCKADDR*)&endpoint, sizeof(SOCKADDR_IN));
|
this->rootNode.callback = NULL;
|
||||||
if (r == SOCKET_ERROR)
|
|
||||||
throw APIException("Failed to bind port.");
|
this->srv = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (this->srv == INVALID_SOCKET)
|
||||||
this->isRunning = true;
|
{
|
||||||
|
throw ServerException (1, "Failed to create Socket");
|
||||||
this->rootNode.name = "";
|
}
|
||||||
this->rootNode.children.clear();
|
|
||||||
this->rootNode.callback = NULL;
|
sa.sin_addr.s_addr = 0L;
|
||||||
|
sa.sin_family = AF_INET;
|
||||||
for (int i = 0;i < threads;i++)
|
sa.sin_port = htons (port);
|
||||||
{
|
|
||||||
#ifdef WIN32
|
r = bind (this->srv, (SOCKADDR*)&sa, sizeof(sa));
|
||||||
this->threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&HTTPServer::doServe, (LPVOID)this, 0, NULL);
|
if (r == SOCKET_ERROR)
|
||||||
#else
|
{
|
||||||
pthread_create (&this->threads[0], NULL, HTTPServer::doServe, (void*)this);
|
throw ServerException (2, "Failed to bind socket");
|
||||||
#endif
|
}
|
||||||
}
|
|
||||||
}
|
this->isRunning = true;
|
||||||
|
for (int i = 0;i < threads;i++)
|
||||||
#ifdef WIN32
|
{
|
||||||
DWORD HTTPServer::doServe (LPVOID arg)
|
#ifdef WIN32
|
||||||
#else
|
this->threads[i] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)_thread_start, this, 0, NULL);
|
||||||
void* HTTPServer::doServe (void* arg)
|
#else
|
||||||
#endif
|
pthread_create (&this->threads[i], NULL, &HTTPServer::_thread_start, this);
|
||||||
{
|
#endif
|
||||||
HTTPServer *srv = (HTTPServer*)arg;
|
}
|
||||||
int r;
|
}
|
||||||
SOCKADDR addr;
|
|
||||||
int addrSz = sizeof (addr);
|
#ifdef WIN32
|
||||||
SOCKET conn;
|
DWORD HTTPServer::_thread_start (LPVOID arg)
|
||||||
|
#else
|
||||||
while (srv->isRunning)
|
void* HTTPServer::_thread_start (void *arg)
|
||||||
{
|
#endif
|
||||||
r = listen (srv->sock, SOMAXCONN);
|
{
|
||||||
if (r == SOCKET_ERROR)
|
HTTPServer *s = (HTTPServer*)arg;
|
||||||
throw APIException("Failed to listen");
|
doSrv:
|
||||||
|
try {
|
||||||
addrSz = sizeof (addr);
|
HTTPServer::handleConnections (s);
|
||||||
|
} catch (ServerException &se)
|
||||||
conn = accept(srv->sock, &addr, &addrSz);
|
{
|
||||||
if (conn == INVALID_SOCKET)
|
cerr << "SRV ERR #" << se.getErrorCode() << ": " << se.getErrorMsg () << endl;
|
||||||
{
|
goto doSrv;
|
||||||
continue;
|
}
|
||||||
}
|
return 0;
|
||||||
cout << "A" << endl;
|
}
|
||||||
|
|
||||||
Request req = Request (conn, &addr);
|
void HTTPServer::handleConnections (HTTPServer *server)
|
||||||
Response resp = Response (conn);
|
{
|
||||||
|
int r;
|
||||||
HTTPServer::handleConnection(srv, &req, &resp);
|
#ifdef WIN32
|
||||||
closesocket(conn);
|
int addrSz;
|
||||||
}
|
#else
|
||||||
|
socklen_t addrSz;
|
||||||
#ifdef WIN32
|
#endif
|
||||||
return 0;
|
SOCKADDR_IN addr;
|
||||||
#else
|
SOCKET cli;
|
||||||
return NULL;
|
|
||||||
#endif
|
while (server->isRunning)
|
||||||
}
|
{
|
||||||
|
r = listen (server->srv, 50);
|
||||||
void HTTPServer::handleConnection (HTTPServer *srv, Request *req, Response *resp)
|
if (r == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
// follow path...
|
#ifdef WIN32
|
||||||
serveNode *cNode = &srv->rootNode;
|
Sleep (500);
|
||||||
list<string>::iterator it;
|
#else
|
||||||
for (it = req->path.begin();(it != req->path.end() && cNode != NULL);it++)
|
sleep (1);
|
||||||
{
|
#endif
|
||||||
if ((*it).length() == 0)
|
continue;
|
||||||
continue; // same node.
|
}
|
||||||
|
addrSz = sizeof addr;
|
||||||
map<string, serveNode>::iterator np;
|
cli = accept (server->srv, (SOCKADDR*)&addr, &addrSz);
|
||||||
np = cNode->children.find((*it));
|
if (cli == INVALID_SOCKET)
|
||||||
if (np == srv->rootNode.children.end())
|
continue;
|
||||||
{
|
|
||||||
cNode = NULL;
|
Response resp (cli); // doesn't throw exceptions.
|
||||||
break;
|
|
||||||
}
|
try {
|
||||||
else
|
Request req (cli, &addr); // may throw exceptions.
|
||||||
cNode = &np->second;
|
reqCallback *cb = getRequestHandler (&server->rootNode, req.getPath());
|
||||||
}
|
if (cb == NULL)
|
||||||
|
{
|
||||||
if (cNode->callback != NULL)
|
// error 404
|
||||||
cNode->callback (req, resp);
|
resp.setStatus (404, "Not Found");
|
||||||
else
|
resp.addHeader ("Content-Type", "text/html; charset=US-ASCII");
|
||||||
{
|
stringstream stream;
|
||||||
// TODO: add HTTP error handler (404 NOT FOUND...)
|
stream << "<html>";
|
||||||
cout << "Page Not Found" << endl;
|
stream << "<head><title>Not Found</title></head>";
|
||||||
}
|
stream << "<body><h1>Not Found</h1><div>The server couldn't find the request resource.</div><br /><hr /><div style=\"font-size:small;text-align:center;\">© 2013 Naim A. | <a href=\"http://udpt.googlecode.com/\">The UDPT Project</a></div></body>";
|
||||||
}
|
stream << "</html>";
|
||||||
|
string str = stream.str();
|
||||||
list<string> HTTPServer::split (const string str, const string del)
|
resp.write (str.c_str(), str.length());
|
||||||
{
|
}
|
||||||
list<string> lst;
|
else
|
||||||
|
{
|
||||||
unsigned s, e;
|
try {
|
||||||
s = e = 0;
|
cb (server, &req, &resp);
|
||||||
|
} catch (...)
|
||||||
while (true)
|
{
|
||||||
{
|
resp.setStatus(500, "Internal Server Error");
|
||||||
e = str.find(del, s);
|
resp.addHeader ("Content-Type", "text/html; charset=US-ASCII");
|
||||||
|
stringstream stream;
|
||||||
if (e == string::npos)
|
stream << "<html>";
|
||||||
e = str.length();
|
stream << "<head><title>Internal Server Error</title></head>";
|
||||||
|
stream << "<body><h1>Internal Server Error</h1><div>An Error Occurred while trying to process your request.</div><br /><hr /><div style=\"font-size:small;text-align:center;\">© 2013 Naim A. | <a href=\"http://udpt.googlecode.com/\">The UDPT Project</a></div></body>";
|
||||||
if (e == str.length())
|
stream << "</html>";
|
||||||
break;
|
string str = stream.str();
|
||||||
s = e + del.length();
|
resp.write (str.c_str(), str.length());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return lst;
|
resp.finalize();
|
||||||
}
|
} catch (ServerException &e)
|
||||||
|
{
|
||||||
void HTTPServer::addApplication (const string path, srvCallback *callback)
|
// Error 400 Bad Request!
|
||||||
{
|
}
|
||||||
list<string> p = split (path, "/");
|
|
||||||
list<string>::iterator it;
|
closesocket (cli);
|
||||||
|
}
|
||||||
serveNode *node = &this->rootNode;
|
}
|
||||||
|
|
||||||
for (it = p.begin();it != p.end();it++)
|
void HTTPServer::addApp (list<string> *path, reqCallback *cb)
|
||||||
{
|
{
|
||||||
if ((*it).length() == 0)
|
list<string>::iterator it = path->begin();
|
||||||
continue; // same node...
|
appNode *node = &this->rootNode;
|
||||||
|
while (it != path->end())
|
||||||
node = &node->children[*it];
|
{
|
||||||
node->name = *it;
|
map<string, appNode>::iterator se;
|
||||||
}
|
se = node->nodes.find (*it);
|
||||||
node->callback = callback;
|
if (se == node->nodes.end())
|
||||||
}
|
{
|
||||||
|
node->nodes[*it].callback = NULL;
|
||||||
HTTPServer::~HTTPServer()
|
}
|
||||||
{
|
node = &node->nodes[*it];
|
||||||
this->isRunning = false;
|
it++;
|
||||||
closesocket(this->sock);
|
}
|
||||||
for (int i = 0;i < this->thread_count;i++)
|
node->callback = cb;
|
||||||
{
|
}
|
||||||
#ifdef WIN32
|
|
||||||
TerminateThread(this->threads[i], 0);
|
HTTPServer::reqCallback* HTTPServer::getRequestHandler (appNode *node, list<string> *path)
|
||||||
#else
|
{
|
||||||
pthread_detach (this->threads[i]);
|
appNode *cn = node;
|
||||||
pthread_cancel (this->threads[i]);
|
list<string>::iterator it = path->begin(),
|
||||||
#endif
|
end = path->end();
|
||||||
}
|
map<string, appNode>::iterator n;
|
||||||
delete[] this->threads;
|
while (true)
|
||||||
}
|
{
|
||||||
|
if (it == end)
|
||||||
|
{
|
||||||
HTTPServer::Request::Request(SOCKET sock, const SOCKADDR *sa)
|
return cn->callback;
|
||||||
{
|
}
|
||||||
this->sock = sock;
|
|
||||||
this->sock_addr = sa;
|
n = cn->nodes.find (*it);
|
||||||
}
|
if (n == cn->nodes.end())
|
||||||
|
return NULL; // node not found!
|
||||||
HTTPServer::Response::Response(SOCKET sock)
|
cn = &n->second;
|
||||||
{
|
|
||||||
|
it++;
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
void HTTPServer::setData(string k, void *d)
|
||||||
|
{
|
||||||
|
this->customData[k] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* HTTPServer::getData(string k)
|
||||||
|
{
|
||||||
|
map<string, void*>::iterator it = this->customData.find(k);
|
||||||
|
if (it == this->customData.end())
|
||||||
|
return NULL;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPServer::~HTTPServer ()
|
||||||
|
{
|
||||||
|
if (this->srv != INVALID_SOCKET)
|
||||||
|
closesocket (this->srv);
|
||||||
|
|
||||||
|
if (this->isRunning)
|
||||||
|
{
|
||||||
|
for (int i = 0;i < this->thread_count;i++)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
TerminateThread (this->threads[i], 0x00);
|
||||||
|
#else
|
||||||
|
pthread_detach (this->threads[i]);
|
||||||
|
pthread_cancel (this->threads[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] this->threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTTPServer::Request */
|
||||||
|
HTTPServer::Request::Request (SOCKET cli, const SOCKADDR_IN *addr)
|
||||||
|
{
|
||||||
|
this->conn = cli;
|
||||||
|
this->addr = addr;
|
||||||
|
|
||||||
|
this->parseRequest ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static char* nextReqLine (int &cPos, char *buff, int len)
|
||||||
|
{
|
||||||
|
for (int i = cPos;i < len - 1;i++)
|
||||||
|
{
|
||||||
|
if (buff[i] == '\r' && buff[i + 1] == '\n')
|
||||||
|
{
|
||||||
|
buff[i] = '\0';
|
||||||
|
|
||||||
|
int r = cPos;
|
||||||
|
cPos = i + 2;
|
||||||
|
return (buff + r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (buff + len); // end
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void parseURL (string request, list<string> *path, map<string, string> *params)
|
||||||
|
{
|
||||||
|
string::size_type p;
|
||||||
|
string query, url;
|
||||||
|
p = request.find ('?');
|
||||||
|
if (p == string::npos)
|
||||||
|
{
|
||||||
|
p = request.length();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
query = request.substr (p + 1);
|
||||||
|
}
|
||||||
|
url = request.substr (0, p);
|
||||||
|
|
||||||
|
path->clear ();
|
||||||
|
string::size_type s, e;
|
||||||
|
s = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
e = url.find ('/', s);
|
||||||
|
if (e == string::npos)
|
||||||
|
e = url.length();
|
||||||
|
|
||||||
|
string x = url.substr (s, e - s);
|
||||||
|
if (!(x.length() == 0 || x == "."))
|
||||||
|
{
|
||||||
|
if (x == "..")
|
||||||
|
{
|
||||||
|
if (path->empty())
|
||||||
|
throw ServerException (1, "Hack attempt");
|
||||||
|
else
|
||||||
|
path->pop_back ();
|
||||||
|
}
|
||||||
|
path->push_back (x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e == url.length())
|
||||||
|
break;
|
||||||
|
s = e + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string::size_type vS, vE, kS, kE;
|
||||||
|
vS = vE = kS = kE = 0;
|
||||||
|
while (kS < query.length())
|
||||||
|
{
|
||||||
|
kE = query.find ('=', kS);
|
||||||
|
if (kE == string::npos) break;
|
||||||
|
vS = kE + 1;
|
||||||
|
vE = query.find ('&', vS);
|
||||||
|
if (vE == string::npos) vE = query.length();
|
||||||
|
|
||||||
|
params->insert (pair<string, string>( query.substr (kS, kE - kS), query.substr (vS, vE - vS) ));
|
||||||
|
|
||||||
|
kS = vE + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setCookies (string &data, map<string, string> *cookies)
|
||||||
|
{
|
||||||
|
string::size_type kS, kE, vS, vE;
|
||||||
|
kS = 0;
|
||||||
|
while (kS < data.length ())
|
||||||
|
{
|
||||||
|
kE = data.find ('=', kS);
|
||||||
|
if (kE == string::npos)
|
||||||
|
break;
|
||||||
|
vS = kE + 1;
|
||||||
|
vE = data.find ("; ", vS);
|
||||||
|
if (vE == string::npos)
|
||||||
|
vE = data.length();
|
||||||
|
|
||||||
|
(*cookies) [data.substr (kS, kE-kS)] = data.substr (vS, vE-vS);
|
||||||
|
|
||||||
|
kS = vE + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPServer::Request::parseRequest ()
|
||||||
|
{
|
||||||
|
char buffer [REQUEST_BUFFER_SIZE];
|
||||||
|
int r;
|
||||||
|
r = recv (this->conn, buffer, REQUEST_BUFFER_SIZE, 0);
|
||||||
|
if (r == REQUEST_BUFFER_SIZE)
|
||||||
|
throw ServerException (1, "Request Size too big.");
|
||||||
|
if (r <= 0)
|
||||||
|
throw ServerException (2, "Socket Error");
|
||||||
|
|
||||||
|
char *cLine;
|
||||||
|
int n = 0;
|
||||||
|
int pos = 0;
|
||||||
|
string::size_type p;
|
||||||
|
while ( (cLine = nextReqLine (pos, buffer, r)) < (buffer + r))
|
||||||
|
{
|
||||||
|
string line = string (cLine);
|
||||||
|
if (line.length() == 0) break; // CRLF CRLF = end of headers.
|
||||||
|
n++;
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
{
|
||||||
|
string::size_type uS, uE;
|
||||||
|
p = line.find (' ');
|
||||||
|
if (p == string::npos)
|
||||||
|
throw ServerException (5, "Malformed request method");
|
||||||
|
uS = p + 1;
|
||||||
|
this->requestMethod.str = line.substr (0, p);
|
||||||
|
|
||||||
|
if (this->requestMethod.str == "GET")
|
||||||
|
this->requestMethod.rm = RM_GET;
|
||||||
|
else if (this->requestMethod.str == "POST")
|
||||||
|
this->requestMethod.rm = RM_POST;
|
||||||
|
else
|
||||||
|
this->requestMethod.rm = RM_UNKNOWN;
|
||||||
|
|
||||||
|
uE = uS;
|
||||||
|
while (p < line.length())
|
||||||
|
{
|
||||||
|
if (p == string::npos)
|
||||||
|
break;
|
||||||
|
p = line.find (' ', p + 1);
|
||||||
|
if (p == string::npos)
|
||||||
|
break;
|
||||||
|
uE = p;
|
||||||
|
}
|
||||||
|
if (uE + 1 >= line.length())
|
||||||
|
throw ServerException (6, "Malformed request");
|
||||||
|
string httpVersion = line.substr (uE + 1);
|
||||||
|
|
||||||
|
|
||||||
|
parseURL (line.substr (uS, uE - uS), &this->path, &this->params);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = line.find (": ");
|
||||||
|
if (p == string::npos)
|
||||||
|
throw ServerException (4, "Malformed headers");
|
||||||
|
string key = line.substr (0, p);
|
||||||
|
string value = line.substr (p + 2);
|
||||||
|
if (key != "Cookie")
|
||||||
|
this->headers.insert(pair<string, string>( key, value));
|
||||||
|
else
|
||||||
|
setCookies (value, &this->cookies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n == 0)
|
||||||
|
throw ServerException (3, "No Request header.");
|
||||||
|
}
|
||||||
|
|
||||||
|
list<string>* HTTPServer::Request::getPath ()
|
||||||
|
{
|
||||||
|
return &this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
string HTTPServer::Request::getParam (const string key)
|
||||||
|
{
|
||||||
|
map<string, string>::iterator it = this->params.find (key);
|
||||||
|
if (it == this->params.end())
|
||||||
|
return "";
|
||||||
|
else
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
multimap<string, string>::iterator HTTPServer::Request::getHeader (const string name)
|
||||||
|
{
|
||||||
|
multimap<string, string>::iterator it = this->headers.find (name);
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPServer::Request::RequestMethod HTTPServer::Request::getRequestMethod ()
|
||||||
|
{
|
||||||
|
return this->requestMethod.rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
string HTTPServer::Request::getRequestMethodStr ()
|
||||||
|
{
|
||||||
|
return this->requestMethod.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
string HTTPServer::Request::getCookie (const string name)
|
||||||
|
{
|
||||||
|
map<string, string>::iterator it = this->cookies.find (name);
|
||||||
|
if (it == this->cookies.end())
|
||||||
|
return "";
|
||||||
|
else
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SOCKADDR_IN* HTTPServer::Request::getAddress ()
|
||||||
|
{
|
||||||
|
return this->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTTPServer::Response */
|
||||||
|
HTTPServer::Response::Response (SOCKET cli)
|
||||||
|
{
|
||||||
|
this->conn = cli;
|
||||||
|
|
||||||
|
setStatus (200, "OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPServer::Response::setStatus (int c, const string m)
|
||||||
|
{
|
||||||
|
this->status_code = c;
|
||||||
|
this->status_msg = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPServer::Response::addHeader (string key, string value)
|
||||||
|
{
|
||||||
|
this->headers.insert (pair<string, string>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPServer::Response::write (const char *data, int len)
|
||||||
|
{
|
||||||
|
if (len < 0)
|
||||||
|
len = strlen (data);
|
||||||
|
msg.write(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPServer::Response::finalize ()
|
||||||
|
{
|
||||||
|
stringstream x;
|
||||||
|
x << "HTTP/1.1 " << this->status_code << " " << this->status_msg << "\r\n";
|
||||||
|
multimap<string, string>::iterator it, end;
|
||||||
|
end = this->headers.end();
|
||||||
|
for (it = this->headers.begin(); it != end;it++)
|
||||||
|
{
|
||||||
|
x << it->first << ": " << it->second << "\r\n";
|
||||||
|
}
|
||||||
|
x << "Connection: Close\r\n";
|
||||||
|
x << "Content-Length: " << this->msg.tellp() << "\r\n";
|
||||||
|
x << "Server: udpt\r\n";
|
||||||
|
x << "\r\n";
|
||||||
|
x << this->msg.str();
|
||||||
|
|
||||||
|
// write to socket
|
||||||
|
send (this->conn, x.str().c_str(), x.str().length(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -1,110 +1,166 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2012,2013 Naim A.
|
* Copyright © 2013 Naim A.
|
||||||
*
|
*
|
||||||
* This file is part of UDPT.
|
* This file is part of UDPT.
|
||||||
*
|
*
|
||||||
* UDPT is free software: you can redistribute it and/or modify
|
* UDPT is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* UDPT is distributed in the hope that it will be useful,
|
* UDPT is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
|
* along with UDPT. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HTTPSERVER_HPP_
|
#pragma once
|
||||||
#define HTTPSERVER_HPP_
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdint.h>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <sstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include "../multiplatform.h"
|
||||||
#include "../multiplatform.h"
|
using namespace std;
|
||||||
|
|
||||||
using namespace std;
|
#define REQUEST_BUFFER_SIZE 2048
|
||||||
|
|
||||||
namespace UDPT
|
namespace UDPT
|
||||||
{
|
{
|
||||||
namespace API
|
namespace Server
|
||||||
{
|
{
|
||||||
class APIException
|
class ServerException
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline
|
inline ServerException (int ec)
|
||||||
APIException (const string msg)
|
{
|
||||||
{
|
this->ec = ec;
|
||||||
this->msg = msg;
|
this->em = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
inline ServerException (int ec, const char *em)
|
||||||
string msg;
|
{
|
||||||
};
|
this->ec = ec;
|
||||||
|
this->em = em;
|
||||||
class HTTPServer
|
}
|
||||||
{
|
|
||||||
public:
|
inline const char *getErrorMsg () const
|
||||||
class Request
|
{
|
||||||
{
|
return this->em;
|
||||||
public:
|
}
|
||||||
Request (SOCKET sock, const SOCKADDR *sock_addr);
|
|
||||||
private:
|
inline int getErrorCode () const
|
||||||
friend class HTTPServer;
|
{
|
||||||
|
return this->ec;
|
||||||
SOCKET sock;
|
}
|
||||||
multimap<string, string> headers;
|
private:
|
||||||
list<string> path; // /some/path
|
int ec;
|
||||||
map<string, string> query; // a=b&c=d
|
const char *em;
|
||||||
const SOCKADDR *sock_addr; // IP address+family
|
};
|
||||||
|
|
||||||
void loadAndParse ();
|
class HTTPServer
|
||||||
};
|
{
|
||||||
class Response
|
public:
|
||||||
{
|
class Request
|
||||||
public:
|
{
|
||||||
Response (SOCKET sock);
|
public:
|
||||||
|
enum RequestMethod
|
||||||
private:
|
{
|
||||||
friend class HTTPServer;
|
RM_UNKNOWN = 0,
|
||||||
};
|
RM_GET = 1,
|
||||||
|
RM_POST = 2
|
||||||
typedef int (srvCallback) (Request *, Response *);
|
};
|
||||||
|
|
||||||
HTTPServer (uint16_t port, int threads);
|
Request (SOCKET, const SOCKADDR_IN *);
|
||||||
|
list<string>* getPath ();
|
||||||
void addApplication (const string path, srvCallback *callback);
|
|
||||||
|
string getParam (const string key);
|
||||||
virtual ~HTTPServer ();
|
multimap<string, string>::iterator getHeader (const string name);
|
||||||
|
RequestMethod getRequestMethod ();
|
||||||
|
string getRequestMethodStr ();
|
||||||
static list<string> split (const string str, const string del);
|
string getCookie (const string name);
|
||||||
private:
|
const SOCKADDR_IN* getAddress ();
|
||||||
typedef struct _serve_node {
|
|
||||||
string name; // part of path name
|
private:
|
||||||
map<string, struct _serve_node> children;
|
const SOCKADDR_IN *addr;
|
||||||
srvCallback *callback;
|
SOCKET conn;
|
||||||
} serveNode;
|
struct {
|
||||||
|
int major;
|
||||||
bool isRunning;
|
int minor;
|
||||||
serveNode rootNode;
|
} httpVer;
|
||||||
SOCKET sock;
|
struct {
|
||||||
int thread_count;
|
string str;
|
||||||
HANDLE *threads;
|
RequestMethod rm;
|
||||||
|
} requestMethod;
|
||||||
#ifdef WIN32
|
list<string> path;
|
||||||
static DWORD doServe (LPVOID arg);
|
map<string, string> params;
|
||||||
#else
|
map<string, string> cookies;
|
||||||
static void* doServe (void* arg);
|
multimap<string, string> headers;
|
||||||
#endif
|
|
||||||
|
void parseRequest ();
|
||||||
static void handleConnection (HTTPServer *, Request *, Response *);
|
};
|
||||||
};
|
|
||||||
};
|
class Response
|
||||||
};
|
{
|
||||||
|
public:
|
||||||
#endif /* HTTPSERVER_HPP_ */
|
Response (SOCKET conn);
|
||||||
|
|
||||||
|
void setStatus (int, const string);
|
||||||
|
void addHeader (string key, string value);
|
||||||
|
|
||||||
|
int writeRaw (const char *data, int len);
|
||||||
|
void write (const char *data, int len = -1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class HTTPServer;
|
||||||
|
|
||||||
|
SOCKET conn;
|
||||||
|
int status_code;
|
||||||
|
string status_msg;
|
||||||
|
multimap<string, string> headers;
|
||||||
|
stringstream msg;
|
||||||
|
|
||||||
|
void finalize ();
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (reqCallback)(HTTPServer*,Request*,Response*);
|
||||||
|
|
||||||
|
HTTPServer (uint16_t port, int threads);
|
||||||
|
|
||||||
|
void addApp (list<string> *path, reqCallback *);
|
||||||
|
|
||||||
|
void setData (string, void *);
|
||||||
|
void* getData (string);
|
||||||
|
|
||||||
|
virtual ~HTTPServer ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef struct appNode
|
||||||
|
{
|
||||||
|
reqCallback *callback;
|
||||||
|
map<string, appNode> nodes;
|
||||||
|
} appNode;
|
||||||
|
|
||||||
|
SOCKET srv;
|
||||||
|
int thread_count;
|
||||||
|
HANDLE *threads;
|
||||||
|
bool isRunning;
|
||||||
|
appNode rootNode;
|
||||||
|
map<string, void*> customData;
|
||||||
|
|
||||||
|
static void handleConnections (HTTPServer *);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
static DWORD _thread_start (LPVOID);
|
||||||
|
#else
|
||||||
|
static void* _thread_start (void*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static reqCallback* getRequestHandler (appNode *, list<string> *);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
266
src/http/webapp.cpp
Normal file
266
src/http/webapp.cpp
Normal file
|
@ -0,0 +1,266 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "webapp.hpp"
|
||||||
|
#include "../tools.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdio>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace UDPT
|
||||||
|
{
|
||||||
|
namespace Server
|
||||||
|
{
|
||||||
|
|
||||||
|
static uint32_t _getNextIPv4 (string::size_type &i, string &line)
|
||||||
|
{
|
||||||
|
string::size_type len = line.length();
|
||||||
|
char c;
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
c = line.at(i);
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ip = 0;
|
||||||
|
for (int n = 0;n < 4;n++)
|
||||||
|
{
|
||||||
|
int cn = 0;
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
c = line.at (i++);
|
||||||
|
if (c == '.' || ((c == ' ' || c == ',' || c == ';') && n == 3))
|
||||||
|
break;
|
||||||
|
else if (!(c >= '0' && c <= '9'))
|
||||||
|
return 0;
|
||||||
|
cn *= 10;
|
||||||
|
cn += (c - '0');
|
||||||
|
}
|
||||||
|
ip *= 256;
|
||||||
|
ip += cn;
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _hex2bin (uint8_t *data, const string str)
|
||||||
|
{
|
||||||
|
int len = str.length();
|
||||||
|
|
||||||
|
if (len % 2 != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char a, b;
|
||||||
|
uint8_t c;
|
||||||
|
for (int i = 0;i < len;i+=2)
|
||||||
|
{
|
||||||
|
a = str.at (i);
|
||||||
|
b = str.at (i + 1);
|
||||||
|
c = 0;
|
||||||
|
|
||||||
|
if (a >= 'a' && a <= 'f')
|
||||||
|
a = (a - 'a') + 10;
|
||||||
|
else if (a >= '0' && a <= '9')
|
||||||
|
a = (a - '0');
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (b >= 'a' && b <= 'f')
|
||||||
|
b = (b - 'a') + 10;
|
||||||
|
else if (b >= '0' && b <= '9')
|
||||||
|
b = (b - '0');
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
c = (a * 16) + b;
|
||||||
|
|
||||||
|
data [i / 2] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebApp::WebApp(HTTPServer *srv, DatabaseDriver *db, Settings *settings)
|
||||||
|
{
|
||||||
|
this->instance = srv;
|
||||||
|
this->db = db;
|
||||||
|
this->sc_api = settings->getClass("api");
|
||||||
|
|
||||||
|
Settings::SettingClass *apiKeys = settings->getClass("api.keys");
|
||||||
|
if (apiKeys != NULL)
|
||||||
|
{
|
||||||
|
map<string, string>* aK = apiKeys->getMap();
|
||||||
|
map<string, string>::iterator it, end;
|
||||||
|
end = aK->end();
|
||||||
|
for (it = aK->begin();it != end;it++)
|
||||||
|
{
|
||||||
|
string key = it->first;
|
||||||
|
list<uint32_t> ips;
|
||||||
|
|
||||||
|
string::size_type strp = 0;
|
||||||
|
uint32_t ip;
|
||||||
|
while ((ip = _getNextIPv4(strp, it->second)) != 0)
|
||||||
|
{
|
||||||
|
ips.push_back( m_hton32(ip) );
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ip_whitelist.insert(pair<string, list<uint32_t> >(key, ips));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
srv->setData("webapp", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebApp::~WebApp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApp::deploy()
|
||||||
|
{
|
||||||
|
list<string> path;
|
||||||
|
this->instance->addApp(&path, &WebApp::handleRoot);
|
||||||
|
|
||||||
|
path.push_back("api");
|
||||||
|
this->instance->addApp(&path, &WebApp::handleAPI); // "/api"
|
||||||
|
|
||||||
|
path.pop_back();
|
||||||
|
path.push_back("announce");
|
||||||
|
this->instance->addApp(&path, &WebApp::handleAnnounce);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApp::handleRoot (HTTPServer *srv, HTTPServer::Request *req, HTTPServer::Response *resp)
|
||||||
|
{
|
||||||
|
// It would be very appreciated to keep this in the code.
|
||||||
|
resp->write("<html>"
|
||||||
|
"<head><title>Powered by UDPT</title></head>"
|
||||||
|
"<body>"
|
||||||
|
"<h2>The UDPT Project</h2>"
|
||||||
|
"<div style=\"vertical-align:top;\">This tracker is running on UDPT Software.<br />"
|
||||||
|
"UDPT is a open-source project, freely available for anyone to use. If you would like to obtain a copy of the software, you can get it here: <a href=\"http://code.google.com/p/udpt\">http://code.googe.com/p/udpt</a>."
|
||||||
|
"<br /><br />If you would like to help the project grow, please donate for our hard work, effort & time: <a class=\"dbtn\" href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6735UFXPUM7BG\">"
|
||||||
|
"<img src=\"data:image/gif;base64,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\" alt=\"Donate via PayPal\" />"
|
||||||
|
"</a></div>"
|
||||||
|
"<br /><hr /><div style=\"text-align:center;font-size:small;\">© 2013 Naim A. | Powered by <a href=\"http://code.google.com/p/udpt\">UDPT</a></div>"
|
||||||
|
"</body>"
|
||||||
|
"</html>");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebApp::isAllowedIP (WebApp *app, string key, uint32_t ip)
|
||||||
|
{
|
||||||
|
std::map<std::string, list<uint32_t> >::iterator it, end;
|
||||||
|
end = app->ip_whitelist.end ();
|
||||||
|
it = app->ip_whitelist.find (key);
|
||||||
|
if (it == app->ip_whitelist.end())
|
||||||
|
return false; // no such key
|
||||||
|
|
||||||
|
list<uint32_t> *lst = &it->second;
|
||||||
|
list<uint32_t>::iterator ipit;
|
||||||
|
for (ipit = lst->begin();ipit != lst->end();ipit++)
|
||||||
|
{
|
||||||
|
if (*ipit == ip)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApp::doRemoveTorrent (HTTPServer::Request *req, HTTPServer::Response *resp)
|
||||||
|
{
|
||||||
|
string strHash = req->getParam("hash");
|
||||||
|
if (strHash.length() != 40)
|
||||||
|
{
|
||||||
|
resp->write("{\"error\":\"Hash length must be 40 characters.\"}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t hash [20];
|
||||||
|
if (!_hex2bin(hash, strHash))
|
||||||
|
{
|
||||||
|
resp->write("{\"error\":\"invalid info_hash.\"}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (this->db->removeTorrent(hash))
|
||||||
|
resp->write("{\"success\":true}");
|
||||||
|
else
|
||||||
|
resp->write("{\"error\":\"failed to remove torrent from DB\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApp::doAddTorrent (HTTPServer::Request *req, HTTPServer::Response *resp)
|
||||||
|
{
|
||||||
|
string strHash = req->getParam("hash");
|
||||||
|
if (strHash.length() != 40)
|
||||||
|
{
|
||||||
|
resp->write("{\"error\":\"Hash length must be 40 characters.\"}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t hash [20];
|
||||||
|
if (!_hex2bin(hash, strHash))
|
||||||
|
{
|
||||||
|
resp->write("{\"error\":\"invalid info_hash.\"}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->db->addTorrent(hash))
|
||||||
|
resp->write("{\"success\":true}");
|
||||||
|
else
|
||||||
|
resp->write("{\"error\":\"failed to add torrent to DB\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApp::handleAnnounce (HTTPServer *srv, HTTPServer::Request *req, HTTPServer::Response *resp)
|
||||||
|
{
|
||||||
|
resp->write("d14:failure reason42:this is a UDP tracker, not a HTTP tracker.e");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApp::handleAPI(HTTPServer *srv, HTTPServer::Request *req, HTTPServer::Response *resp)
|
||||||
|
{
|
||||||
|
if (req->getAddress()->sin_family != AF_INET)
|
||||||
|
{
|
||||||
|
throw ServerException (0, "IPv4 supported Only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string key = req->getParam("auth");
|
||||||
|
if (key.length() <= 0)
|
||||||
|
throw ServerException (0, "Bad Authentication Key");
|
||||||
|
|
||||||
|
WebApp *app = (WebApp*)srv->getData("webapp");
|
||||||
|
if (app == NULL)
|
||||||
|
throw ServerException(0, "WebApp object wasn't found");
|
||||||
|
|
||||||
|
if (!isAllowedIP(app, key, req->getAddress()->sin_addr.s_addr))
|
||||||
|
{
|
||||||
|
resp->setStatus(403, "Forbidden");
|
||||||
|
resp->write("IP not whitelisted. Access Denied.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string action = req->getParam("action");
|
||||||
|
if (action == "add")
|
||||||
|
app->doAddTorrent(req, resp);
|
||||||
|
else if (action == "remove")
|
||||||
|
app->doRemoveTorrent(req, resp);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resp->write("{\"error\":\"unknown action\"}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
60
src/http/webapp.hpp
Normal file
60
src/http/webapp.hpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "httpserver.hpp"
|
||||||
|
#include "../db/database.hpp"
|
||||||
|
#include "../settings.hpp"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using namespace UDPT;
|
||||||
|
using namespace UDPT::Data;
|
||||||
|
|
||||||
|
namespace UDPT
|
||||||
|
{
|
||||||
|
namespace Server
|
||||||
|
{
|
||||||
|
class WebApp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebApp (HTTPServer *, DatabaseDriver *, Settings *);
|
||||||
|
~WebApp ();
|
||||||
|
void deploy ();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
HTTPServer *instance;
|
||||||
|
UDPT::Data::DatabaseDriver *db;
|
||||||
|
Settings::SettingClass *sc_api;
|
||||||
|
std::map<std::string, list<uint32_t> > ip_whitelist;
|
||||||
|
|
||||||
|
static void handleRoot (HTTPServer*,HTTPServer::Request*, HTTPServer::Response*);
|
||||||
|
static void handleAnnounce (HTTPServer*,HTTPServer::Request*, HTTPServer::Response*);
|
||||||
|
static void handleAPI (HTTPServer*,HTTPServer::Request*, HTTPServer::Response*);
|
||||||
|
static bool isAllowedIP (WebApp *, string, uint32_t);
|
||||||
|
|
||||||
|
void doAddTorrent (HTTPServer::Request*, HTTPServer::Response*);
|
||||||
|
void doRemoveTorrent (HTTPServer::Request*, HTTPServer::Response*);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
61
src/main.cpp
61
src/main.cpp
|
@ -22,15 +22,52 @@
|
||||||
#include "multiplatform.h"
|
#include "multiplatform.h"
|
||||||
#include "udpTracker.hpp"
|
#include "udpTracker.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "http/httpserver.hpp"
|
||||||
|
#include "http/webapp.hpp"
|
||||||
|
#include <cstdlib> // atoi
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace UDPT;
|
using namespace UDPT;
|
||||||
|
using namespace UDPT::Server;
|
||||||
|
|
||||||
static void _print_usage ()
|
static void _print_usage ()
|
||||||
{
|
{
|
||||||
cout << "Usage: udpt [<configuration file>]" << endl;
|
cout << "Usage: udpt [<configuration file>]" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _doAPIStart (Settings *settings, WebApp **wa, HTTPServer **srv, DatabaseDriver *drvr)
|
||||||
|
{
|
||||||
|
if (settings == NULL)
|
||||||
|
return;
|
||||||
|
Settings::SettingClass *sc = settings->getClass("apiserver");
|
||||||
|
if (sc == NULL)
|
||||||
|
return; // no settings set!
|
||||||
|
|
||||||
|
if (sc->get("enable") != "1")
|
||||||
|
{
|
||||||
|
cerr << "API Server not enabled." << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string s_port = sc->get("port");
|
||||||
|
string s_threads = sc->get("threads");
|
||||||
|
|
||||||
|
uint16_t port = (s_port == "" ? 6969 : atoi (s_port.c_str()));
|
||||||
|
uint16_t threads = (s_threads == "" ? 1 : atoi (s_threads.c_str()));
|
||||||
|
|
||||||
|
if (threads <= 0)
|
||||||
|
threads = 1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
*srv = new HTTPServer (port, threads);
|
||||||
|
*wa = new WebApp (*srv, drvr, settings);
|
||||||
|
(*wa)->deploy();
|
||||||
|
} catch (ServerException &e)
|
||||||
|
{
|
||||||
|
cerr << "ServerException #" << e.getErrorCode() << ": " << e.getErrorMsg() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Settings *settings = NULL;
|
Settings *settings = NULL;
|
||||||
|
@ -60,43 +97,53 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const char strDATABASE[] = "database";
|
const char strDATABASE[] = "database";
|
||||||
const char strTRACKER[] = "tracker";
|
const char strTRACKER[] = "tracker";
|
||||||
|
const char strAPISRV [] = "apiserver";
|
||||||
// set default settings:
|
// set default settings:
|
||||||
|
|
||||||
settings->set (strDATABASE, "driver", "sqlite3");
|
settings->set (strDATABASE, "driver", "sqlite3");
|
||||||
settings->set (strDATABASE, "file", "tracker.db");
|
settings->set (strDATABASE, "file", "tracker.db");
|
||||||
|
|
||||||
settings->set (strTRACKER, "port", "6969");
|
settings->set (strTRACKER, "port", "6969"); // UDP PORT
|
||||||
settings->set (strTRACKER, "threads", "5");
|
settings->set (strTRACKER, "threads", "5");
|
||||||
settings->set (strTRACKER, "allow_remotes", "yes");
|
settings->set (strTRACKER, "allow_remotes", "yes");
|
||||||
settings->set (strTRACKER, "allow_iana_ips", "yes");
|
settings->set (strTRACKER, "allow_iana_ips", "yes");
|
||||||
settings->set (strTRACKER, "announce_interval", "1800");
|
settings->set (strTRACKER, "announce_interval", "1800");
|
||||||
settings->set (strTRACKER, "cleanup_interval", "120");
|
settings->set (strTRACKER, "cleanup_interval", "120");
|
||||||
|
|
||||||
|
settings->set (strAPISRV, "enable", "1");
|
||||||
|
settings->set (strAPISRV, "threads", "1");
|
||||||
|
settings->set (strAPISRV, "port", "6969"); // TCP PORT
|
||||||
|
|
||||||
settings->save();
|
settings->save();
|
||||||
cout << "Failed to read from '" << config_file.c_str() << "'. Using default settings." << endl;
|
cerr << "Failed to read from '" << config_file.c_str() << "'. Using default settings." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
usi = new UDPTracker (settings);
|
usi = new UDPTracker (settings);
|
||||||
|
|
||||||
|
HTTPServer *apiSrv = NULL;
|
||||||
|
WebApp *wa = NULL;
|
||||||
|
|
||||||
r = usi->start();
|
r = usi->start();
|
||||||
if (r != UDPTracker::START_OK)
|
if (r != UDPTracker::START_OK)
|
||||||
{
|
{
|
||||||
cout << "Error While trying to start server." << endl;
|
cerr << "Error While trying to start server." << endl;
|
||||||
switch (r)
|
switch (r)
|
||||||
{
|
{
|
||||||
case UDPTracker::START_ESOCKET_FAILED:
|
case UDPTracker::START_ESOCKET_FAILED:
|
||||||
cout << "Failed to create socket." << endl;
|
cerr << "Failed to create socket." << endl;
|
||||||
break;
|
break;
|
||||||
case UDPTracker::START_EBIND_FAILED:
|
case UDPTracker::START_EBIND_FAILED:
|
||||||
cout << "Failed to bind socket." << endl;
|
cerr << "Failed to bind socket." << endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cout << "Unknown Error" << endl;
|
cerr << "Unknown Error" << endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_doAPIStart(settings, &wa, &apiSrv, usi->conn);
|
||||||
|
|
||||||
cout << "Press Any key to exit." << endl;
|
cout << "Press Any key to exit." << endl;
|
||||||
|
|
||||||
cin.get();
|
cin.get();
|
||||||
|
@ -106,6 +153,8 @@ cleanup:
|
||||||
|
|
||||||
delete usi;
|
delete usi;
|
||||||
delete settings;
|
delete settings;
|
||||||
|
delete apiSrv;
|
||||||
|
delete wa;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#define VERSION "1.0.0 (Windows)"
|
#define VERSION "1.0.0-beta (Windows)"
|
||||||
#elif defined (linux)
|
#elif defined (linux)
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -52,9 +52,6 @@ typedef void* LPVOID;
|
||||||
typedef void (LPTHREAD_START_ROUTINE)(LPVOID);
|
typedef void (LPTHREAD_START_ROUTINE)(LPVOID);
|
||||||
typedef pthread_t HANDLE;
|
typedef pthread_t HANDLE;
|
||||||
|
|
||||||
#ifndef min
|
#define VERSION "1.0.0-beta (Linux)"
|
||||||
#define min(a,b) (a > b ? b : a)
|
|
||||||
#endif
|
|
||||||
#define VERSION "1.0.0-alpha (Linux)"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,8 @@ void _settings_clean_string (char **str)
|
||||||
SettingClass *c;
|
SettingClass *c;
|
||||||
|
|
||||||
c = this->getClass(classN);
|
c = this->getClass(classN);
|
||||||
|
if (c == NULL)
|
||||||
|
return "";
|
||||||
return c->get(name);
|
return c->get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,9 +279,16 @@ void _settings_clean_string (char **str)
|
||||||
|
|
||||||
string Settings::SettingClass::get (const string name)
|
string Settings::SettingClass::get (const string name)
|
||||||
{
|
{
|
||||||
|
if (this->entries.find(name) == this->entries.end())
|
||||||
|
return "";
|
||||||
return this->entries[name];
|
return this->entries[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map<string, string>* Settings::SettingClass::getMap()
|
||||||
|
{
|
||||||
|
return &this->entries;
|
||||||
|
}
|
||||||
|
|
||||||
bool Settings::SettingClass::set (const string name, const string value)
|
bool Settings::SettingClass::set (const string name, const string value)
|
||||||
{
|
{
|
||||||
pair<map<string, string>::iterator, bool> r;
|
pair<map<string, string>::iterator, bool> r;
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace UDPT
|
||||||
SettingClass (const string className);
|
SettingClass (const string className);
|
||||||
bool set (const string key, const string value);
|
bool set (const string key, const string value);
|
||||||
string get (const string key);
|
string get (const string key);
|
||||||
|
map<string, string>* getMap ();
|
||||||
private:
|
private:
|
||||||
friend class Settings;
|
friend class Settings;
|
||||||
string className;
|
string className;
|
||||||
|
|
|
@ -455,7 +455,7 @@ static int _isIANA_IP (uint32_t ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << ":: " << (void*)m_hton32(remote->sin_addr.s_addr) << ": " << m_hton16(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)
|
if (action == 0 && r >= 16)
|
||||||
return UDPTracker::handleConnection (usi, remote, data);
|
return UDPTracker::handleConnection (usi, remote, data);
|
||||||
|
@ -465,7 +465,7 @@ static int _isIANA_IP (uint32_t ip)
|
||||||
return UDPTracker::handleScrape (usi, remote, data, r);
|
return UDPTracker::handleScrape (usi, remote, data, r);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cout << "E: action=" << action << ", r=" << r << endl;
|
// cout << "E: action=" << action << ", r=" << r << endl;
|
||||||
UDPTracker::sendError (usi, remote, cR->transaction_id, "Tracker couldn't understand Client's request.");
|
UDPTracker::sendError (usi, remote, cR->transaction_id, "Tracker couldn't understand Client's request.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,7 @@ namespace UDPT
|
||||||
*/
|
*/
|
||||||
virtual ~UDPTracker ();
|
virtual ~UDPTracker ();
|
||||||
|
|
||||||
|
Data::DatabaseDriver *conn;
|
||||||
private:
|
private:
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
|
@ -142,7 +143,6 @@ namespace UDPT
|
||||||
|
|
||||||
uint8_t settings;
|
uint8_t settings;
|
||||||
Settings *o_settings;
|
Settings *o_settings;
|
||||||
Data::DatabaseDriver *conn;
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
static DWORD _thread_start (LPVOID arg);
|
static DWORD _thread_start (LPVOID arg);
|
||||||
|
|
Loading…
Reference in a new issue