diff --git a/spectrum_manager/src/APIServer.cpp b/spectrum_manager/src/APIServer.cpp new file mode 100644 index 00000000..359f6d48 --- /dev/null +++ b/spectrum_manager/src/APIServer.cpp @@ -0,0 +1,92 @@ +#include "APIServer.h" +#include "methods.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static std::string get_http_var(const struct http_message *hm, const char *name) { + char data[4096]; + data[0] = '\0'; + + mg_get_http_var(&hm->body, name, data, sizeof(data)); + if (data[0] != '\0') { + return data; + } + + mg_get_http_var(&hm->query_string, name, data, sizeof(data)); + if (data[0] != '\0') { + return data; + } + + return ""; +} + +APIServer::APIServer(ManagerConfig *config, StorageBackend *storage) { + m_config = config; + m_storage = storage; +} + +APIServer::~APIServer() { +} + +void APIServer::send_json(struct mg_connection *conn, const std::string &json) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/json\r\n" + "Content-Length: %d\r\n" + "\r\n" + "%s", + (int) json.size(), json.c_str()); +} + +void APIServer::serve_instances(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) { +// std::string jid = get_http_var(hm, "jid"); +// if (!jid.empty()) { +// serve_instance(conn, hm, jid); +// return; +// } + + std::vector list = show_list(m_config, false); + + std::string json = "{\"error\":0, \"instances\": ["; + + BOOST_FOREACH(std::string &instance, list) { + json += "{"; + json += "\"id\":\"" + instance + "\","; + json += "\"name\":\"" + instance + "\","; + + std::string status = server->send_command(instance, "status"); + if (status.empty()) { + status = "Cannot get the instance status."; + } + else if (*(status.end() - 1) == '\n') { + status.erase(status.end() - 1); + } + json += "\"status\":\"" + status + "\""; + json += "},"; + } + json.erase(json.end() - 1); + + json += "]}"; + send_json(conn, json); +} + +void APIServer::handleRequest(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm) { + if (mg_vcmp(&hm->uri, "/api/v1/instances") == 0) { + serve_instances(server, sess, conn, hm); + } +} + + + + + + diff --git a/spectrum_manager/src/APIServer.h b/spectrum_manager/src/APIServer.h new file mode 100644 index 00000000..fdc71045 --- /dev/null +++ b/spectrum_manager/src/APIServer.h @@ -0,0 +1,58 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2016, Jan Kaluza + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "mongoose.h" +#include "managerconfig.h" +#include "server.h" + +#include "transport/Config.h" +#include "transport/SQLite3Backend.h" +#include "transport/MySQLBackend.h" +#include "transport/PQXXBackend.h" +#include "transport/StorageBackend.h" + +using namespace Transport; + +class APIServer { + public: + APIServer(ManagerConfig *config, StorageBackend *storage); + + virtual ~APIServer(); + + void handleRequest(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm); + + private: + void serve_instances(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm); + void send_json(struct mg_connection *conn, const std::string &json); + + private: + ManagerConfig *m_config; + StorageBackend *m_storage; +}; diff --git a/spectrum_manager/src/server.cpp b/spectrum_manager/src/server.cpp index 88ffc726..4d156e18 100644 --- a/spectrum_manager/src/server.cpp +++ b/spectrum_manager/src/server.cpp @@ -1,3 +1,4 @@ +#include "APIServer.h" #include "server.h" #include "methods.h" @@ -99,9 +100,13 @@ Server::Server(ManagerConfig *config, const std::string &config_file) { m_storage = NULL; std::cerr << "Can't connect to database!\n"; } + + m_apiServer = new APIServer(config, m_storage); } Server::~Server() { + delete m_apiServer; + mg_mgr_free(&m_mgr); if (m_storage) { delete m_storage; @@ -173,9 +178,10 @@ void Server::authorize(struct mg_connection *conn, struct http_message *hm) { mg_printf(conn, "HTTP/1.1 302 Found\r\n" "Set-Cookie: session=%s; max-age=3600; http-only\r\n" // Session ID "Set-Cookie: user=%s\r\n" // Set user, needed by Javascript code + "Set-Cookie: admin=%s\r\n" // Set user, needed by Javascript code "Set-Cookie: original_url=/; max-age=0\r\n" // Delete original_url "Location: /\r\n\r\n", - session->session_id, session->user); + session->session_id, session->user, session->admin ? "1" : "0"); } else { // Authentication failure, redirect to login. redirect_to(conn, hm, "/login"); @@ -312,9 +318,10 @@ void Server::serve_cmd(struct mg_connection *conn, struct http_message *hm) { void Server::serve_logout(struct mg_connection *conn, struct http_message *hm) { Server:session *session = get_session(hm); mg_printf(conn, "HTTP/1.1 302 Found\r\n" - "Set-Cookie: session=%s; max-age=0\r\n" // Session ID + "Set-Cookie: session=%s; max-age=0\r\n" + "Set-Cookie: admin=%s; max-age=0\r\n" "Location: /\r\n\r\n", - session->session_id); + session->session_id, session->admin ? "1" : "0"); sessions.erase(session->session_id); delete session; @@ -675,32 +682,34 @@ void Server::event_handler(struct mg_connection *conn, int ev, void *p) { redirect_to(conn, hm, "/login"); } else if (mg_vcmp(&hm->uri, "/authorize") == 0) { authorize(conn, hm); - } else if (mg_vcmp(&hm->uri, "/") == 0) { - serve_instances(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/") == 0) { +// serve_instances(conn, hm); } else if (mg_vcmp(&hm->uri, "/logout") == 0) { serve_logout(conn, hm); - } else if (mg_vcmp(&hm->uri, "/instances") == 0) { - serve_instances(conn, hm); - } else if (mg_vcmp(&hm->uri, "/onlineusers") == 0) { - serve_onlineusers(conn, hm); - } else if (mg_vcmp(&hm->uri, "/cmd") == 0) { - serve_cmd(conn, hm); - } else if (mg_vcmp(&hm->uri, "/instances/start") == 0) { - serve_instances_start(conn, hm); - } else if (mg_vcmp(&hm->uri, "/instances/stop") == 0) { - serve_instances_stop(conn, hm); - } else if (mg_vcmp(&hm->uri, "/instances/register") == 0) { - serve_instances_register(conn, hm); - } else if (mg_vcmp(&hm->uri, "/instances/unregister") == 0) { - serve_instances_unregister(conn, hm); - } else if (mg_vcmp(&hm->uri, "/users") == 0) { - serve_users(conn, hm); - } else if (mg_vcmp(&hm->uri, "/users/add") == 0) { - serve_users_add(conn, hm); - } else if (mg_vcmp(&hm->uri, "/users/remove") == 0) { - serve_users_remove(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/instances") == 0) { +// serve_instances(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/onlineusers") == 0) { +// serve_onlineusers(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/cmd") == 0) { +// serve_cmd(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/instances/start") == 0) { +// serve_instances_start(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/instances/stop") == 0) { +// serve_instances_stop(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/instances/register") == 0) { +// serve_instances_register(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/instances/unregister") == 0) { +// serve_instances_unregister(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/users") == 0) { +// serve_users(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/users/add") == 0) { +// serve_users_add(conn, hm); +// } else if (mg_vcmp(&hm->uri, "/users/remove") == 0) { +// serve_users_remove(conn, hm); } else if (has_prefix(&hm->uri, "/oauth2")) { serve_oauth2(conn, hm); + } else if (has_prefix(&hm->uri, "/api/v1/")) { + m_apiServer->handleRequest(this, get_session(hm), conn, hm); } else { mg_serve_http(conn, hm, s_http_server_opts); } diff --git a/spectrum_manager/src/server.h b/spectrum_manager/src/server.h index f4fa17f9..e42bcc0f 100644 --- a/spectrum_manager/src/server.h +++ b/spectrum_manager/src/server.h @@ -39,6 +39,8 @@ using namespace Transport; +class APIServer; + class Server { public: struct session { @@ -59,6 +61,10 @@ class Server { void event_handler(struct mg_connection *nc, int ev, void *p); + void redirect_to(struct mg_connection *conn, struct http_message *hm, const char *where); + + std::string send_command(const std::string &jid, const std::string &cmd); + private: void serve_instance(struct mg_connection *conn, struct http_message *hm, const std::string &jid); void serve_instances(struct mg_connection *conn, struct http_message *hm); @@ -74,7 +80,6 @@ class Server { void serve_cmd(struct mg_connection *conn, struct http_message *hm); void serve_oauth2(struct mg_connection *conn, struct http_message *hm); void print_html(struct mg_connection *conn, struct http_message *hm, const std::string &html); - std::string send_command(const std::string &jid, const std::string &cmd); private: bool check_password(const std::string &user, const std::string &password); @@ -85,8 +90,6 @@ class Server { bool is_authorized(const struct mg_connection *conn, struct http_message *hm); - void redirect_to(struct mg_connection *conn, struct http_message *hm, const char *where); - private: struct mg_mgr m_mgr; struct mg_connection *m_nc; @@ -99,4 +102,5 @@ class Server { std::string m_footer; Config *m_storageCfg; StorageBackend *m_storage; + APIServer *m_apiServer; };