diff options
author | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2016-08-11 08:54:06 +0300 |
---|---|---|
committer | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2016-08-11 08:54:06 +0300 |
commit | 028ddc8e576e78d500f1cba443d7e21401130bb6 (patch) | |
tree | 8c3a3b1ae9899eaafb490e776d6407bb16f6213d | |
parent | d9ffc27c8b563d76a493ec9eafad56ec5dda13b9 (diff) |
server:
event_system:
draft implementation of repeated events (we still have none defined by protcol)
more appropriate names for some enums and structs
messaging:
a bit of refactoring in server_session (cut message handler to separate functions for each message type)
more appropriate names for some functions
curl_downloader:
updating downloaded size variable during download process (thread safety required)
-rw-r--r-- | client-qt/udm-client-qt/udm_main.cpp | 3 | ||||
-rw-r--r-- | server/include/client.h | 4 | ||||
-rw-r--r-- | server/include/event_subscription_base.h | 10 | ||||
-rw-r--r-- | server/include/event_subscription_repeated.h | 8 | ||||
-rw-r--r-- | server/include/server_session.h | 19 | ||||
-rw-r--r-- | server/modules/downloaders/curl/src/curl_download.cpp | 5 | ||||
-rw-r--r-- | server/src/client.cpp | 26 | ||||
-rw-r--r-- | server/src/event_subscription_event.cpp | 2 | ||||
-rw-r--r-- | server/src/event_subscription_repeated.cpp | 25 | ||||
-rw-r--r-- | server/src/server_session.cpp | 600 |
10 files changed, 426 insertions, 276 deletions
diff --git a/client-qt/udm-client-qt/udm_main.cpp b/client-qt/udm-client-qt/udm_main.cpp index 830adfe..72d73d8 100644 --- a/client-qt/udm-client-qt/udm_main.cpp +++ b/client-qt/udm-client-qt/udm_main.cpp @@ -259,7 +259,6 @@ void udm_main::server_message_received(server_msg msg) if(msg.auth_reply().status()) { auth_token = msg.auth_reply().auth_token(); - lbl_state->setText(tr("State") + ": " + tr("Connected") + ", " + tr("Authenticated")); //TODO: subscript to events //request modules and settings here @@ -305,7 +304,7 @@ void udm_main::server_message_received(server_msg msg) s->mutable_download_state_change()->add_states(SDS_STARTED); //subscript to download started event s->mutable_download_state_change()->add_states(SDS_STOPPED); //subscript to download stopped event s->mutable_download_state_change()->add_states(SDS_DELETED); //subscript to download deleted event - s->mutable_download_state_change()->add_states(SDS_COMPLETED); //subscript to download deleted event + s->mutable_download_state_change()->add_states(SDS_COMPLETED); //subscript to download completed event session->send_message(msg); } diff --git a/server/include/client.h b/server/include/client.h index e755fac..5aa4fb4 100644 --- a/server/include/client.h +++ b/server/include/client.h @@ -23,9 +23,10 @@ #include <string> #include <list> -#include "event_subscription_base.h" class server_session; +class event_subscription_base; +class client_event_subscription_request; class client { @@ -33,6 +34,7 @@ class client client(std::string &client_auth_token, server_session *sess = nullptr); void add_event_subscription(event_subscription_base* e); const std::list<event_subscription_base*>& get_subscriptions(); + void fire_event(client_event_subscription_request* e); virtual ~client(); protected: private: diff --git a/server/include/event_subscription_base.h b/server/include/event_subscription_base.h index b181dfd..635abba 100644 --- a/server/include/event_subscription_base.h +++ b/server/include/event_subscription_base.h @@ -25,9 +25,9 @@ //TODO: rework (events and polls separated ?) -enum EVENT_SUBTYPE { - EVENT_SUBTYPE_REPEATED = 0, //periodic firing based on timer - EVENT_SUBTYPE_EVENT = 1, //fired on event occurs (only can be used for data which support this event type) +enum EVENT_MODE { + EVENT_MODE_REPEATED = 0, //periodic firing based on timer + EVENT_MODE_EVENT = 1, //fired on event occurs (only can be used for data which support this event type) }; class event_subscription_base @@ -37,7 +37,7 @@ public: { subscription_request = *req; } - const EVENT_SUBTYPE get_subtype() + const EVENT_MODE get_subtype() { return subtype; } @@ -48,7 +48,7 @@ public: virtual ~event_subscription_base(){} protected: - EVENT_SUBTYPE subtype = EVENT_SUBTYPE::EVENT_SUBTYPE_EVENT; + EVENT_MODE subtype = EVENT_MODE::EVENT_MODE_EVENT; client_event_subscription_request subscription_request; }; diff --git a/server/include/event_subscription_repeated.h b/server/include/event_subscription_repeated.h index fc0d857..309c9ab 100644 --- a/server/include/event_subscription_repeated.h +++ b/server/include/event_subscription_repeated.h @@ -25,6 +25,8 @@ #include "event_subscription_base.h" #include <boost/asio.hpp> +class client; + typedef boost::asio::basic_deadline_timer<boost::posix_time::ptime> deadline_timer; class event_subscription_repeated : public event_subscription_base @@ -34,8 +36,14 @@ public: ~event_subscription_repeated(); void timer_handler(const boost::system::error_code &e); + + void start(); + const client* get_owner(); + void set_owner(client* c); + private: deadline_timer *timer; + client *owner = nullptr; }; #endif // EVENT_SUBSCRIPTION_PERIODIC_H diff --git a/server/include/server_session.h b/server/include/server_session.h index c0220f0..13f60fd 100644 --- a/server/include/server_session.h +++ b/server/include/server_session.h @@ -49,15 +49,26 @@ public: protected: private: server_session(const server_session&) = delete; - // net + // lowlevel net void handle_read(const boost::system::error_code& error, size_t bytes_transferred); void handle_write(const boost::system::error_code& error); void handle_write_no_read(const boost::system::error_code& error); void handle_handshake(const boost::system::error_code& error); - bool handle_command(client_msg* msg); //TODO: thread safety ? - void send_download_list(); - + //message handlers + //TODO: thread safety ? + bool handle_message(client_msg* msg); + bool handle_auth_request(client_msg *msg); + bool handle_modules_request(client_msg *msg); + bool handle_core_info_request(client_msg *msg); + bool handle_downloads_list_request(); + bool handle_download_info_request(client_msg *msg); + bool handle_download_add_request(client_msg *msg); + bool handle_download_start_request(client_msg *msg); + bool handle_download_stop_request(client_msg *msg); + bool handle_download_delete_request(client_msg *msg); + bool handle_subscription_request(client_msg *msg); + char* recv_data_ = nullptr; socket_wraper* socket_ = nullptr; boost::asio::io_service& io_service_; diff --git a/server/modules/downloaders/curl/src/curl_download.cpp b/server/modules/downloaders/curl/src/curl_download.cpp index cb85239..a190f63 100644 --- a/server/modules/downloaders/curl/src/curl_download.cpp +++ b/server/modules/downloaders/curl/src/curl_download.cpp @@ -42,7 +42,6 @@ size_t curl_w_callback(char *ptr, size_t size, size_t nmemb, void *userdata) } } size_t size_ = size * nmemb; - //TODO: update download state with new size if(size_) { if(of.is_open()) @@ -59,7 +58,9 @@ size_t curl_w_callback(char *ptr, size_t size, size_t nmemb, void *userdata) return -1; //TODO: handle error } - + //updated downloaded size on success write + //TODO: thread safety (without proper locking size will be inacurate) + d->downloaded += size_; } return size_; } diff --git a/server/src/client.cpp b/server/src/client.cpp index 67acdb0..4dd412b 100644 --- a/server/src/client.cpp +++ b/server/src/client.cpp @@ -20,6 +20,8 @@ #include "client.h" #include "server_session.h" +#include "event_subscription_repeated.h" +#include "../../protocol/udm.pb.h" client::client(std::string &client_auth_token, server_session *sess) : auth_token(client_auth_token), session(sess) { @@ -28,12 +30,36 @@ client::client(std::string &client_auth_token, server_session *sess) : auth_toke void client::add_event_subscription(event_subscription_base* e) { + subscriptions.push_back(e); + switch(e->get_subtype()) + { + case EVENT_MODE_REPEATED: + { + event_subscription_repeated *re = static_cast<event_subscription_repeated*>(e); + re->set_owner(this); + re->start(); + } + break; + default: + break; + } } const std::list<event_subscription_base*>& client::get_subscriptions() { return subscriptions; } + +void client::fire_event(client_event_subscription_request* e) +{ + switch(e->type()) + { + //TODO: design protocol for repeated events + default: + break; + } +} + client::~client() { //dtor diff --git a/server/src/event_subscription_event.cpp b/server/src/event_subscription_event.cpp index a702d60..29076ba 100644 --- a/server/src/event_subscription_event.cpp +++ b/server/src/event_subscription_event.cpp @@ -23,7 +23,7 @@ event_subscription_event::event_subscription_event(client_event_subscription_request *req) : event_subscription_base(req) { - subtype = EVENT_SUBTYPE_EVENT; + subtype = EVENT_MODE_EVENT; } event_subscription_event::~event_subscription_event() diff --git a/server/src/event_subscription_repeated.cpp b/server/src/event_subscription_repeated.cpp index 4291dfa..04c0944 100644 --- a/server/src/event_subscription_repeated.cpp +++ b/server/src/event_subscription_repeated.cpp @@ -22,14 +22,16 @@ #include "event_subscription_repeated.h" #include <boost/bind.hpp> +#include "client.h" + extern boost::asio::io_service io_service_server; event_subscription_repeated::event_subscription_repeated(client_event_subscription_request *req) : event_subscription_base(req) { - subtype = EVENT_SUBTYPE_REPEATED; + subtype = EVENT_MODE_REPEATED; timer = new deadline_timer(io_service_server, boost::posix_time::milliseconds(req->interval())); - timer->async_wait(boost::bind(&event_subscription_repeated::timer_handler, this, _1)); + } event_subscription_repeated::~event_subscription_repeated() @@ -40,8 +42,9 @@ event_subscription_repeated::~event_subscription_repeated() void event_subscription_repeated::timer_handler(const boost::system::error_code &e) { - if(!e) + if(!e && this->owner) { + this->owner->fire_event(&subscription_request); //TODO: fire event if(!subscription_request.one_time()) { @@ -61,3 +64,19 @@ void event_subscription_repeated::timer_handler(const boost::system::error_code delete this; } } + +void event_subscription_repeated::start() +{ + timer->async_wait(boost::bind(&event_subscription_repeated::timer_handler, this, _1)); +} + +const client* event_subscription_repeated::get_owner() +{ + return owner; +} + +void event_subscription_repeated::set_owner(client* c) +{ + owner = c; +} + diff --git a/server/src/server_session.cpp b/server/src/server_session.cpp index bfab451..4436391 100644 --- a/server/src/server_session.cpp +++ b/server/src/server_session.cpp @@ -102,7 +102,7 @@ void server_session::handle_read(const boost::system::error_code& error, size_t { //parsed = true; BOOST_LOG_TRIVIAL(trace)<<"received message:\n"<<msg.DebugString(); - if(!handle_command(&msg)) + if(!handle_message(&msg)) { //cannot handle command, delete session delete this; @@ -269,7 +269,7 @@ void add_download_content_menu_element(module_download_menu_element_info_s &elem } -bool server_session::handle_command(client_msg *msg) +bool server_session::handle_message(client_msg *msg) { //TODO: thread safety ? if(msg->type() != CLIENT_MSG_TYPE::CLIENT_AUTH_REQUEST && clients.find(msg->auth_token()) == clients.end()) @@ -281,309 +281,81 @@ bool server_session::handle_command(client_msg *msg) { case CLIENT_MSG_TYPE::CLIENT_AUTH_REQUEST: { - server_msg m; - m.set_type(SERVER_MSG_TYPE::SERVER_AUTH_REPLY); - std::string server_password = runtime_config.config_file.get<std::string>("server.password", ""); - if(server_password.empty()) - m.mutable_auth_reply()->set_status(true); - else - { - switch(msg->auth_request().hash_type()) - { - case PASSWD_HASH_TYPE::HASH_NONE: - { - if(msg->auth_request().password() != server_password) - { - m.mutable_auth_reply()->set_status(false); - m.mutable_auth_reply()->set_error_description("wrong password"); - } - else - m.mutable_auth_reply()->set_status(true); - } - break; - case PASSWD_HASH_TYPE::HASH_MD5: - { - //TODO: - } - break; - case PASSWD_HASH_TYPE::HASH_SHA2: - { - //TODO: - } - break; - case PASSWD_HASH_TYPE::HASH_SHA512: - { - unsigned char hash[64]; - SHA512((unsigned char*)server_password.c_str(), server_password.length(), hash); - if(msg->auth_request().password() != std::string((const char*)hash)) - { - m.mutable_auth_reply()->set_status(false); - m.mutable_auth_reply()->set_error_description("wrong password"); - } - else - m.mutable_auth_reply()->set_status(true); - } - break; - default: - break; - } - } - if(m.auth_reply().status() == true) + if(!handle_auth_request(msg)) { - client_auth_token = generate_auth_token(); - m.mutable_auth_reply()->set_auth_token(client_auth_token); - auto i = clients.find(client_auth_token); - if(i == clients.end()) - { - auto a = new client(client_auth_token); - clients[client_auth_token] = a; - client_ = a; - } - else - client_ = i->second; - //set auth token + //TODO: handle auth failure } - send_message(&m); } break; case CLIENT_MSG_TYPE::CLIENT_MODULES_REQUEST: { - server_msg m; - m.set_type(SERVER_MSG_TYPE::SERVER_MODULES_REPLY); - for(auto i : modules->get_downloader_modules()) + if(!handle_modules_request(msg)) { - module_info *mi = m.add_server_modules_reply(); - mi->set_type(SERVER_MODULE_TYPE::SERVER_MODULE_DOWNLOADER); - mi->set_name(i->get_module_info().name); - mi->set_description(i->get_module_info().description); - mi->set_version(i->get_module_info().version); - for(auto ms : i->get_runtime_module_settings()) - add_runtime_module_setting(ms, mi); - const downloader_module_info &dmi = static_cast<const downloader_module_info&>(i->get_module_info()); - for(auto ui_element : dmi.download_info_ui) - add_download_info_ui_element(ui_element, mi); - for(auto ui_element : dmi.download_creation_ui) - add_download_create_ui_element(ui_element, mi); - for(auto menu_entry : dmi.download_root_menu) - add_download_menu_element(menu_entry, mi); - for(auto menu_entry : dmi.download_content_menu) - add_download_content_menu_element(menu_entry, mi); - for(auto si : dmi.get_downloads_parameters_info) - { - string_pair *p = mi->add_get_downloads_parameters_info(); - p->set_name(si.first); - p->set_value(si.second); - } - for(auto si : dmi.download_state_names) - { - int_string_pair *p = mi->add_download_state_name(); - p->set_id(si.first); - p->set_value(si.second); - } - - - - } - for(auto i : modules->get_metadata_modules()) - { - module_info *mi = m.add_server_modules_reply(); - mi->set_type(SERVER_MODULE_TYPE::SERVER_MODULE_METADATA_STORAGE); - mi->set_name(i->get_module_info().name); - mi->set_description(i->get_module_info().description); - mi->set_version(i->get_module_info().version); - for(auto ms : i->get_runtime_module_settings()) - add_runtime_module_setting(ms, mi); + //TODO: handle modules request failure } - send_message(&m); } break; case CLIENT_MSG_TYPE::CLIENT_CORE_INFO_REQUEST: { - server_msg m; - m.set_type(SERVER_MSG_TYPE::SERVER_CORE_INFO_REPLY); - m.mutable_server_core_info_reply()->set_version(1); - try{ - for(auto it : runtime_config.config_file.get_child("server")) //load server node + if(!handle_core_info_request(msg)) { - std::string val = it.second.get_value<std::string>("empty_value"); //TODO: something better here. we need to avoid subtrees and empty vars - if(/*val == "" ||*/ val == "empty_value") - continue; - setting *i = m.mutable_server_core_info_reply()->add_settings(); - i->set_name(it.first); - i->set_value(val); - //TODO: is it possible to set something better than just list of core setting ? + //TODO: handle core info request failure } - } - catch(...) - { - //TODO: - } - send_message(&m); - } break; case CLIENT_MSG_TYPE::CLIENT_DOWNLOADS_LIST_REQUEST: - send_download_list(); + { + if(!handle_downloads_list_request()) + { + //TODO: handle dowbload list request failure + } + } break; case CLIENT_MSG_TYPE::CLIENT_DOWNLOAD_INFO_REQUEST: { - for(auto i : modules->get_downloader_modules()) + if(!handle_download_info_request(msg)) { - if(i->get_module_info().name == downloads[msg->download_info_request().download_id()].module_name) - { - auto dm = static_cast<module_downloader *>(i); - server_msg m; - m.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_INFO_REPLY); - download *d = m.mutable_download()->mutable_download(); - d->set_id(msg->download_info_request().download_id()); - auto dl = dm->get_download(downloads[msg->download_info_request().download_id()].module_id); - d->set_name(dl.name); - d->set_size(dl.size); - d->set_state(dl.state); - d->set_module_name(msg->download_add_request().module_name()); - d->set_downloaded(dl.downloaded); - send_message(&m); - } + //TODO: handle download info request failure } } break; case CLIENT_MSG_TYPE::CLIENT_DOWNLOAD_ADD: { - for(auto i : modules->get_downloader_modules()) - { - if(i->get_module_info().name == msg->download_add_request().module_name()) - { - std::map<int, std::string> params; - for(auto p : msg->download_add_request().params()) - params[p.id()] = p.value(); - auto dm = static_cast<module_downloader *>(i); - int download_id = dm->add_download(params); - int core_id = downloads.size(); - downloads[core_id].module_id = download_id; - downloads[core_id].module_name = msg->download_add_request().module_name(); - server_msg m; - m.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_INFO_REPLY); - download *d = m.mutable_download()->mutable_download(); - d->set_id(core_id); - auto dl = dm->get_download(download_id); - d->set_name(dl.name); - d->set_size(dl.size); - d->set_state(dl.state); - d->set_module_name(msg->download_add_request().module_name()); - d->set_downloaded(dl.downloaded); - fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_ADDED, m); - break; - } + if(!handle_download_add_request(msg)) + { + //TODO: handle download add request failure } } break; case CLIENT_MSG_TYPE::CLIENT_DOWNLOAD_START: { - server_msg s_msg; - s_msg.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_STATE_CHANGE); - for(auto i : msg->download_start_request()) + if(!handle_download_start_request(msg)) { - for(auto m : modules->get_downloader_modules()) - { - if(m->get_module_info().name == downloads[i.download_id()].module_name) - { - auto dm = static_cast<module_downloader *>(m); - if(!dm->start_download(i.download_id())) - { - - //TODO: handle error - } - else - { - auto dsc = s_msg.add_download_state_changes(); - dsc->set_download_id(i.download_id()); - dsc->set_state(SUBSCRIPTION_DOWNLOAD_STATE::SDS_STARTED); - } - break; - } - } + //TODO: handle download start request failure } - fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_STATE_CHANGE, s_msg); } break; case CLIENT_MSG_TYPE::CLIENT_DOWNLOAD_STOP: { - server_msg s_msg; - s_msg.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_STATE_CHANGE); - for(auto i : msg->download_stop_request()) + if(!handle_download_stop_request(msg)) { - for(auto m : modules->get_downloader_modules()) - { - if(m->get_module_info().name == downloads[i.download_id()].module_name) - { - auto dm = static_cast<module_downloader *>(m); - if(!dm->stop_download(i.download_id())) - { - //TODO: handle error - } - else - { - auto dsc = s_msg.add_download_state_changes(); - dsc->set_download_id(i.download_id()); - dsc->set_state(SUBSCRIPTION_DOWNLOAD_STATE::SDS_STOPPED); - } - break; - } - } + //TODO: handle download stop request failure } - fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_STATE_CHANGE, s_msg); } break; case CLIENT_MSG_TYPE::CLIENT_DOWNLOAD_DELETE: { - server_msg s_msg; - s_msg.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_STATE_CHANGE); - for(auto i : msg->download_delete_request()) + if(!handle_download_delete_request(msg)) { - for(auto m : modules->get_downloader_modules()) - { - if(m->get_module_info().name == downloads[i.download_id()].module_name) - { - auto dm = static_cast<module_downloader *>(m); - if(!dm->delete_download(i.download_id(), i.with_data())) - { - //TODO: handle error - } - else - { - downloads.erase(i.download_id()); - auto dsc = s_msg.add_download_state_changes(); - dsc->set_download_id(i.download_id()); - dsc->set_state(SUBSCRIPTION_DOWNLOAD_STATE::SDS_DELETED); - } - break; - } - } + //TODO: handle download delete request failure } - fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_STATE_CHANGE, s_msg); } break; case CLIENT_MSG_TYPE::CLIENT_SUBSCRIPTION_REQUEST: { - for(auto i : msg->subscription_request()) + if(!handle_subscription_request(msg)) { - switch(i.mode()) - { - case SUBSCRIPTION_MODE::SM_EVENT: - { - event_subscription_event *e = new event_subscription_event(&i); - client_->add_event_subscription(e); - } - break; - case SUBSCRIPTION_MODE::SM_REPEATED: - { - event_subscription_repeated *e = new event_subscription_repeated(&i); - client_->add_event_subscription(e); - } - break; - default: - break; - } + //TODO: handle subscription request failure } } break; @@ -594,7 +366,149 @@ bool server_session::handle_command(client_msg *msg) return true; } -void server_session::send_download_list() +bool server_session::handle_auth_request(client_msg *msg) +{ + server_msg m; + m.set_type(SERVER_MSG_TYPE::SERVER_AUTH_REPLY); + std::string server_password = runtime_config.config_file.get<std::string>("server.password", ""); + if(server_password.empty()) + m.mutable_auth_reply()->set_status(true); + else + { + switch(msg->auth_request().hash_type()) + { + case PASSWD_HASH_TYPE::HASH_NONE: + { + if(msg->auth_request().password() != server_password) + { + m.mutable_auth_reply()->set_status(false); + m.mutable_auth_reply()->set_error_description("wrong password"); + } + else + m.mutable_auth_reply()->set_status(true); + } + break; + case PASSWD_HASH_TYPE::HASH_MD5: + { + //TODO: + } + break; + case PASSWD_HASH_TYPE::HASH_SHA2: + { + //TODO: + } + break; + case PASSWD_HASH_TYPE::HASH_SHA512: + { + unsigned char hash[64]; + SHA512((unsigned char*)server_password.c_str(), server_password.length(), hash); + if(msg->auth_request().password() != std::string((const char*)hash)) + { + m.mutable_auth_reply()->set_status(false); + m.mutable_auth_reply()->set_error_description("wrong password"); + } + else + m.mutable_auth_reply()->set_status(true); + } + break; + default: + break; + } + } + if(m.auth_reply().status() == true) + { + client_auth_token = generate_auth_token(); + m.mutable_auth_reply()->set_auth_token(client_auth_token); + auto i = clients.find(client_auth_token); + if(i == clients.end()) + { + auto a = new client(client_auth_token); + clients[client_auth_token] = a; + client_ = a; + } + else + client_ = i->second; + //set auth token + } + send_message(&m); + return true; +} + +bool server_session::handle_modules_request(client_msg *msg) +{ + server_msg m; + m.set_type(SERVER_MSG_TYPE::SERVER_MODULES_REPLY); + for(auto i : modules->get_downloader_modules()) + { + module_info *mi = m.add_server_modules_reply(); + mi->set_type(SERVER_MODULE_TYPE::SERVER_MODULE_DOWNLOADER); + mi->set_name(i->get_module_info().name); + mi->set_description(i->get_module_info().description); + mi->set_version(i->get_module_info().version); + for(auto ms : i->get_runtime_module_settings()) + add_runtime_module_setting(ms, mi); + const downloader_module_info &dmi = static_cast<const downloader_module_info&>(i->get_module_info()); + for(auto ui_element : dmi.download_info_ui) + add_download_info_ui_element(ui_element, mi); + for(auto ui_element : dmi.download_creation_ui) + add_download_create_ui_element(ui_element, mi); + for(auto menu_entry : dmi.download_root_menu) + add_download_menu_element(menu_entry, mi); + for(auto menu_entry : dmi.download_content_menu) + add_download_content_menu_element(menu_entry, mi); + for(auto si : dmi.get_downloads_parameters_info) + { + string_pair *p = mi->add_get_downloads_parameters_info(); + p->set_name(si.first); + p->set_value(si.second); + } + for(auto si : dmi.download_state_names) + { + int_string_pair *p = mi->add_download_state_name(); + p->set_id(si.first); + p->set_value(si.second); + } + } + for(auto i : modules->get_metadata_modules()) + { + module_info *mi = m.add_server_modules_reply(); + mi->set_type(SERVER_MODULE_TYPE::SERVER_MODULE_METADATA_STORAGE); + mi->set_name(i->get_module_info().name); + mi->set_description(i->get_module_info().description); + mi->set_version(i->get_module_info().version); + for(auto ms : i->get_runtime_module_settings()) + add_runtime_module_setting(ms, mi); + } + send_message(&m); + return true; +} + +bool server_session::handle_core_info_request(client_msg *msg) +{ + server_msg m; + m.set_type(SERVER_MSG_TYPE::SERVER_CORE_INFO_REPLY); + m.mutable_server_core_info_reply()->set_version(1); + try{ + for(auto it : runtime_config.config_file.get_child("server")) //load server node + { + std::string val = it.second.get_value<std::string>("empty_value"); //TODO: something better here. we need to avoid subtrees and empty vars + if(/*val == "" ||*/ val == "empty_value") + continue; + setting *i = m.mutable_server_core_info_reply()->add_settings(); + i->set_name(it.first); + i->set_value(val); + //TODO: is it possible to set something better than just list of core setting ? + } + } + catch(...) + { + //TODO: + } + send_message(&m); + return true; +} + +bool server_session::handle_downloads_list_request() { //TODO: thread safety //draft implementation, need a lot of optimizations @@ -628,8 +542,178 @@ void server_session::send_download_list() d->set_state(ds.state); } send_message(&m); + return true; } +bool server_session::handle_download_info_request(client_msg *msg) +{ + for(auto i : modules->get_downloader_modules()) + { + if(i->get_module_info().name == downloads[msg->download_info_request().download_id()].module_name) + { + auto dm = static_cast<module_downloader *>(i); + server_msg m; + m.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_INFO_REPLY); + download *d = m.mutable_download()->mutable_download(); + d->set_id(msg->download_info_request().download_id()); + auto dl = dm->get_download(downloads[msg->download_info_request().download_id()].module_id); + d->set_name(dl.name); + d->set_size(dl.size); + d->set_state(dl.state); + d->set_module_name(msg->download_add_request().module_name()); + d->set_downloaded(dl.downloaded); + send_message(&m); + } + } + return true; +} + +bool server_session::handle_download_add_request(client_msg *msg) +{ + for(auto i : modules->get_downloader_modules()) + { + if(i->get_module_info().name == msg->download_add_request().module_name()) + { + std::map<int, std::string> params; + for(auto p : msg->download_add_request().params()) + params[p.id()] = p.value(); + auto dm = static_cast<module_downloader *>(i); + int download_id = dm->add_download(params); + int core_id = downloads.size(); + downloads[core_id].module_id = download_id; + downloads[core_id].module_name = msg->download_add_request().module_name(); + server_msg m; + m.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_INFO_REPLY); + download *d = m.mutable_download()->mutable_download(); + d->set_id(core_id); + auto dl = dm->get_download(download_id); + d->set_name(dl.name); + d->set_size(dl.size); + d->set_state(dl.state); + d->set_module_name(msg->download_add_request().module_name()); + d->set_downloaded(dl.downloaded); + fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_ADDED, m); + break; + } + } + return true; +} + +bool server_session::handle_download_start_request(client_msg *msg) +{ + server_msg s_msg; + s_msg.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_STATE_CHANGE); + for(auto i : msg->download_start_request()) + { + for(auto m : modules->get_downloader_modules()) + { + if(m->get_module_info().name == downloads[i.download_id()].module_name) + { + auto dm = static_cast<module_downloader *>(m); + if(!dm->start_download(i.download_id())) + { + + //TODO: handle error + } + else + { + auto dsc = s_msg.add_download_state_changes(); + dsc->set_download_id(i.download_id()); + dsc->set_state(SUBSCRIPTION_DOWNLOAD_STATE::SDS_STARTED); + } + break; + } + } + } + fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_STATE_CHANGE, s_msg); + return true; +} + +bool server_session::handle_download_stop_request(client_msg *msg) +{ + server_msg s_msg; + s_msg.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_STATE_CHANGE); + for(auto i : msg->download_stop_request()) + { + for(auto m : modules->get_downloader_modules()) + { + if(m->get_module_info().name == downloads[i.download_id()].module_name) + { + auto dm = static_cast<module_downloader *>(m); + if(!dm->stop_download(i.download_id())) + { + //TODO: handle error + } + else + { + auto dsc = s_msg.add_download_state_changes(); + dsc->set_download_id(i.download_id()); + dsc->set_state(SUBSCRIPTION_DOWNLOAD_STATE::SDS_STOPPED); + } + break; + } + } + } + fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_STATE_CHANGE, s_msg); + return true; +} + +bool server_session::handle_download_delete_request(client_msg *msg) +{ + server_msg s_msg; + s_msg.set_type(SERVER_MSG_TYPE::SERVER_DOWNLOAD_STATE_CHANGE); + for(auto i : msg->download_delete_request()) + { + for(auto m : modules->get_downloader_modules()) + { + if(m->get_module_info().name == downloads[i.download_id()].module_name) + { + auto dm = static_cast<module_downloader *>(m); + if(!dm->delete_download(i.download_id(), i.with_data())) + { + //TODO: handle error + } + else + { + downloads.erase(i.download_id()); + auto dsc = s_msg.add_download_state_changes(); + dsc->set_download_id(i.download_id()); + dsc->set_state(SUBSCRIPTION_DOWNLOAD_STATE::SDS_DELETED); + } + break; + } + } + } + fire_event(SUBSCRIPTION_TYPE::ST_DOWNLOAD_STATE_CHANGE, s_msg); + return true; +} + +bool server_session::handle_subscription_request(client_msg *msg) +{ + for(auto i : msg->subscription_request()) + { + switch(i.mode()) + { + case SUBSCRIPTION_MODE::SM_EVENT: + { + event_subscription_event *e = new event_subscription_event(&i); + client_->add_event_subscription(e); + } + break; + case SUBSCRIPTION_MODE::SM_REPEATED: + { + event_subscription_repeated *e = new event_subscription_repeated(&i); + client_->add_event_subscription(e); + } + break; + default: + break; + } + } + return true; +} + + void server_session::send_message(server_msg *msg) { //TODO: thread safety @@ -662,8 +746,8 @@ void server_session::fire_event(SUBSCRIPTION_TYPE type, server_msg &msg) { if(s->get_subscription_request().type() != type) continue; - if(s->get_subtype() != EVENT_SUBTYPE::EVENT_SUBTYPE_EVENT) - continue; + if(s->get_subtype() != EVENT_MODE::EVENT_MODE_EVENT) + continue; //this is handled in client class via event internal timer switch(type) { case SUBSCRIPTION_TYPE::ST_DOWNLOAD_ADDED: |