Skip to content
Snippets Groups Projects
Commit e2c534df authored by Sébastien Blin's avatar Sébastien Blin
Browse files

add std::bind, fix put, avoid overflow on base64

parent 2ca2835c
No related branches found
No related tags found
No related merge requests found
...@@ -62,7 +62,7 @@ private: ...@@ -62,7 +62,7 @@ private:
/** /**
* Return the PublicKey id, the node id and node stats * Return the PublicKey id, the node id and node stats
* Method: GET "/" * Method: GET "/"
* Result: HTTP 200, body: Value in JSON format (one part = one value) * Result: HTTP 200, body: Node infos in JSON format
* On error: HTTP 503, body: {"err":"xxxx"} * On error: HTTP 503, body: {"err":"xxxx"}
* @param session * @param session
*/ */
...@@ -98,7 +98,7 @@ private: ...@@ -98,7 +98,7 @@ private:
* body = Value to put in JSON * body = Value to put in JSON
* Return: HTTP 200 if success and the value put in JSON * Return: HTTP 200 if success and the value put in JSON
* On error: HTTP 503, body: {"err":"xxxx"} if no dht * On error: HTTP 503, body: {"err":"xxxx"} if no dht
* HTTP 400, body: {"err":"xxxx"} if bad json * HTTP 400, body: {"err":"xxxx"} if bad json or HTTP 502 if put fails
* @param session * @param session
*/ */
void put(const std::shared_ptr<restbed::Session>& session) const; void put(const std::shared_ptr<restbed::Session>& session) const;
...@@ -157,7 +157,7 @@ private: ...@@ -157,7 +157,7 @@ private:
struct SessionToHashToken { struct SessionToHashToken {
std::shared_ptr<restbed::Session> session; std::shared_ptr<restbed::Session> session;
InfoHash hash; InfoHash hash;
size_t token; std::future<size_t> token;
}; };
mutable std::vector<SessionToHashToken> currentListeners_; mutable std::vector<SessionToHashToken> currentListeners_;
std::atomic_bool stopListeners {false}; std::atomic_bool stopListeners {false};
......
...@@ -72,7 +72,7 @@ uint8_t *base64_decode(const char *input, size_t input_length, ...@@ -72,7 +72,7 @@ uint8_t *base64_decode(const char *input, size_t input_length,
for (c = 0; c < 64; c++) for (c = 0; c < 64; c++)
decoding_table[static_cast<int>(encoding_table[c])] = c; decoding_table[static_cast<int>(encoding_table[c])] = c;
if (input_length % 4 != 0) if (input_length % 4 != 0 || input_length < 2)
return nullptr; return nullptr;
size_t out_sz = *output_length; size_t out_sz = *output_length;
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <json/json.h> #include <json/json.h>
#include <limits> #include <limits>
using namespace std::placeholders;
namespace dht { namespace dht {
DhtProxyServer::DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port) DhtProxyServer::DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port)
...@@ -40,62 +42,22 @@ DhtProxyServer::DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port) ...@@ -40,62 +42,22 @@ DhtProxyServer::DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port)
// Create endpoints // Create endpoints
auto resource = std::make_shared<restbed::Resource>(); auto resource = std::make_shared<restbed::Resource>();
resource->set_path("/"); resource->set_path("/");
resource->set_method_handler("GET", resource->set_method_handler("GET", std::bind(&DhtProxyServer::getNodeInfo, this, _1));
[this](const std::shared_ptr<restbed::Session> session)
{
this->getNodeInfo(session);
}
);
service_->publish(resource); service_->publish(resource);
resource = std::make_shared<restbed::Resource>(); resource = std::make_shared<restbed::Resource>();
resource->set_path("/{hash: .*}"); resource->set_path("/{hash: .*}");
resource->set_method_handler("GET", resource->set_method_handler("GET", std::bind(&DhtProxyServer::get, this, _1));
[this](const std::shared_ptr<restbed::Session> session) resource->set_method_handler("LISTEN", std::bind(&DhtProxyServer::listen, this, _1));
{ resource->set_method_handler("POST", std::bind(&DhtProxyServer::put, this, _1));
this->get(session);
}
);
resource->set_method_handler("LISTEN",
[this](const std::shared_ptr<restbed::Session> session)
{
this->listen(session);
}
);
resource->set_method_handler("POST",
[this](const std::shared_ptr<restbed::Session> session)
{
this->put(session);
}
);
#if OPENDHT_PROXY_SERVER_IDENTITY #if OPENDHT_PROXY_SERVER_IDENTITY
resource->set_method_handler("SIGN", resource->set_method_handler("SIGN", std::bind(&DhtProxyServer::putSigned, this, _1));
[this](const std::shared_ptr<restbed::Session> session) resource->set_method_handler("ENCRYPT", std::bind(&DhtProxyServer::putEncrypted, this, _1));
{
this->putSigned(session);
}
);
resource->set_method_handler("ENCRYPT",
[this](const std::shared_ptr<restbed::Session> session)
{
this->putEncrypted(session);
}
);
#endif // OPENDHT_PROXY_SERVER_IDENTITY #endif // OPENDHT_PROXY_SERVER_IDENTITY
resource->set_method_handler("OPTIONS", resource->set_method_handler("OPTIONS", std::bind(&DhtProxyServer::handleOptionsMethod, this, _1));
[this](const std::shared_ptr<restbed::Session> session)
{
this->handleOptionsMethod(session);
}
);
service_->publish(resource); service_->publish(resource);
resource = std::make_shared<restbed::Resource>(); resource = std::make_shared<restbed::Resource>();
resource->set_path("/{hash: .*}/{value: .*}"); resource->set_path("/{hash: .*}/{value: .*}");
resource->set_method_handler("GET", resource->set_method_handler("GET", std::bind(&DhtProxyServer::getFiltered, this, _1));
[this](const std::shared_ptr<restbed::Session> session)
{
this->getFiltered(session);
}
);
service_->publish(resource); service_->publish(resource);
// Start server // Start server
...@@ -118,7 +80,7 @@ DhtProxyServer::DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port) ...@@ -118,7 +80,7 @@ DhtProxyServer::DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port)
auto listener = currentListeners_.begin(); auto listener = currentListeners_.begin();
while (listener != currentListeners_.end()) { while (listener != currentListeners_.end()) {
if (listener->session->is_closed() && dht_) { if (listener->session->is_closed() && dht_) {
dht_->cancelListen(listener->hash, listener->token); dht_->cancelListen(listener->hash, std::move(listener->token));
// Remove listener if unused // Remove listener if unused
listener = currentListeners_.erase(listener); listener = currentListeners_.erase(listener);
} else { } else {
...@@ -226,36 +188,32 @@ DhtProxyServer::listen(const std::shared_ptr<restbed::Session>& session) const ...@@ -226,36 +188,32 @@ DhtProxyServer::listen(const std::shared_ptr<restbed::Session>& session) const
if (!infoHash) { if (!infoHash) {
infoHash = InfoHash::get(hash); infoHash = InfoHash::get(hash);
} }
s->yield(restbed::OK, "", [=]( const std::shared_ptr< restbed::Session > s) { s->yield(restbed::OK);
size_t token = dht_->listen(infoHash, [s](std::shared_ptr<Value> value) { // Handle client deconnection
// NOTE: for now, there is no handler, so we test the session in a thread
// will be the case in restbed 5.0
SessionToHashToken listener;
listener.session = session;
listener.hash = infoHash;
listener.token = dht_->listen(infoHash, [s](std::shared_ptr<Value> value) {
// Send values as soon as we get them // Send values as soon as we get them
if (!s->is_closed()) { if (!s->is_closed()) {
Json::FastWriter writer; Json::FastWriter writer;
s->yield(writer.write(value->toJson()), [](const std::shared_ptr<restbed::Session> /*session*/){ }); s->yield(writer.write(value->toJson()), [](const std::shared_ptr<restbed::Session> /*session*/){ });
} }
return !s->is_closed(); return !s->is_closed();
}).get();
// Handle client deconnection
// NOTE: for now, there is no handler, so we test the session in a thread
// will be the case in restbed 5.0
SessionToHashToken listener;
listener.session = s;
listener.hash = infoHash;
listener.token = token;
currentListeners_.emplace_back(listener);
}); });
currentListeners_.emplace_back(std::move(listener));
} else { } else {
s->close(restbed::SERVICE_UNAVAILABLE, "{\"err\":\"Incorrect DhtRunner\"}"); session->close(restbed::SERVICE_UNAVAILABLE, "{\"err\":\"Incorrect DhtRunner\"}");
} }
} }
); );
} }
void void
DhtProxyServer::put(const std::shared_ptr<restbed::Session>& session) const DhtProxyServer::put(const std::shared_ptr<restbed::Session>& session) const
{ {
// TODO test with the proxy client
const auto request = session->get_request(); const auto request = session->get_request();
int content_length = std::stoi(request->get_header("Content-Length", "0")); int content_length = std::stoi(request->get_header("Content-Length", "0"));
auto hash = request->get_path_parameter("hash"); auto hash = request->get_path_parameter("hash");
...@@ -268,7 +226,7 @@ DhtProxyServer::put(const std::shared_ptr<restbed::Session>& session) const ...@@ -268,7 +226,7 @@ DhtProxyServer::put(const std::shared_ptr<restbed::Session>& session) const
{ {
if (dht_) { if (dht_) {
if(b.empty()) { if(b.empty()) {
std::string response("Missing parameters"); std::string response("{\"err\":\"Missing parameters\"}");
s->close(restbed::BAD_REQUEST, response); s->close(restbed::BAD_REQUEST, response);
} else { } else {
restbed::Bytes buf(b); restbed::Bytes buf(b);
...@@ -280,11 +238,16 @@ DhtProxyServer::put(const std::shared_ptr<restbed::Session>& session) const ...@@ -280,11 +238,16 @@ DhtProxyServer::put(const std::shared_ptr<restbed::Session>& session) const
// Build the Value from json // Build the Value from json
auto value = std::make_shared<Value>(root); auto value = std::make_shared<Value>(root);
dht_->put(infoHash, value, [s, value](bool ok) {
if (ok) {
Json::FastWriter writer; Json::FastWriter writer;
dht_->put(infoHash, value);
s->close(restbed::OK, writer.write(value->toJson())); s->close(restbed::OK, writer.write(value->toJson()));
} else { } else {
s->close(restbed::BAD_REQUEST, "Incorrect JSON"); s->close(restbed::BAD_GATEWAY, "{\"err\":\"put failed\"}");
}
});
} else {
s->close(restbed::BAD_REQUEST, "{\"err\":\"Incorrect JSON\"}");
} }
} }
} else { } else {
...@@ -310,7 +273,7 @@ DhtProxyServer::putSigned(const std::shared_ptr<restbed::Session>& session) cons ...@@ -310,7 +273,7 @@ DhtProxyServer::putSigned(const std::shared_ptr<restbed::Session>& session) cons
{ {
if (dht_) { if (dht_) {
if(b.empty()) { if(b.empty()) {
std::string response("Missing parameters"); std::string response("{\"err\":\"Missing parameters\"}");
s->close(restbed::BAD_REQUEST, response); s->close(restbed::BAD_REQUEST, response);
} else { } else {
restbed::Bytes buf(b); restbed::Bytes buf(b);
...@@ -325,7 +288,7 @@ DhtProxyServer::putSigned(const std::shared_ptr<restbed::Session>& session) cons ...@@ -325,7 +288,7 @@ DhtProxyServer::putSigned(const std::shared_ptr<restbed::Session>& session) cons
dht_->putSigned(infoHash, value); dht_->putSigned(infoHash, value);
s->close(restbed::OK, writer.write(value->toJson())); s->close(restbed::OK, writer.write(value->toJson()));
} else { } else {
s->close(restbed::BAD_REQUEST, "Incorrect JSON" + strJson); s->close(restbed::BAD_REQUEST, "{\"err\":\"Incorrect JSON\"}");
} }
} }
} else { } else {
...@@ -341,16 +304,16 @@ DhtProxyServer::putEncrypted(const std::shared_ptr<restbed::Session>& session) c ...@@ -341,16 +304,16 @@ DhtProxyServer::putEncrypted(const std::shared_ptr<restbed::Session>& session) c
const auto request = session->get_request(); const auto request = session->get_request();
int content_length = std::stoi(request->get_header("Content-Length", "0")); int content_length = std::stoi(request->get_header("Content-Length", "0"));
auto hash = request->get_path_parameter("hash"); auto hash = request->get_path_parameter("hash");
InfoHash infoHash(hash); InfoHash key(hash);
if (!infoHash) if (!key)
infoHash = InfoHash::get(hash); key = InfoHash::get(hash);
session->fetch(content_length, session->fetch(content_length,
[=](const std::shared_ptr<restbed::Session> s, const restbed::Bytes& b) [=](const std::shared_ptr<restbed::Session> s, const restbed::Bytes& b)
{ {
if (dht_) { if (dht_) {
if(b.empty()) { if(b.empty()) {
std::string response("Missing parameters"); std::string response("{\"err\":\"Missing parameters\"}");
s->close(restbed::BAD_REQUEST, response); s->close(restbed::BAD_REQUEST, response);
} else { } else {
restbed::Bytes buf(b); restbed::Bytes buf(b);
...@@ -358,22 +321,17 @@ DhtProxyServer::putEncrypted(const std::shared_ptr<restbed::Session>& session) c ...@@ -358,22 +321,17 @@ DhtProxyServer::putEncrypted(const std::shared_ptr<restbed::Session>& session) c
Json::Reader reader; Json::Reader reader;
std::string strJson(buf.begin(), buf.end()); std::string strJson(buf.begin(), buf.end());
bool parsingSuccessful = reader.parse(strJson.c_str(), root); bool parsingSuccessful = reader.parse(strJson.c_str(), root);
auto toHash = root["to"].asString(); InfoHash to(root["to"].asString());
if (parsingSuccessful && !toHash.empty()) { if (parsingSuccessful && toInfoHash) {
auto value = std::make_shared<Value>(root); auto value = std::make_shared<Value>(root);
auto toHash = request->get_path_parameter("to");
InfoHash toInfoHash(toHash);
if (toInfoHash)
toInfoHash = InfoHash::get(toHash);
Json::FastWriter writer; Json::FastWriter writer;
dht_->putEncrypted(infoHash, toInfoHash, value); dht_->putEncrypted(key, to, value);
s->close(restbed::OK, writer.write(value->toJson())); s->close(restbed::OK, writer.write(value->toJson()));
} else { } else {
if(!parsingSuccessful) if(!parsingSuccessful)
s->close(restbed::BAD_REQUEST, "Incorrect JSON"); s->close(restbed::BAD_REQUEST, "{\"err\":\"Incorrect JSON\"}");
else else
s->close(restbed::BAD_REQUEST, "No destination found"); s->close(restbed::BAD_REQUEST, "{\"err\":\"No destination found\"}");
} }
} }
} else { } else {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment