From b21f1d1da09466c10851a9cc395fdca0b00f5836 Mon Sep 17 00:00:00 2001 From: Jürgen Knödlseder Date: Mon, 18 May 2015 09:52:12 +0200 Subject: [PATCH] Use new internal structure to store information. --- include/GVOHub.hpp | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------- src/vo/GVOClient.cpp | 5 +---- src/vo/GVOHub.cpp | 993 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 3 files changed, 576 insertions(+), 556 deletions(-) diff --git a/include/GVOHub.hpp b/include/GVOHub.hpp index 8f01492..b40c598 100644 --- a/include/GVOHub.hpp +++ b/include/GVOHub.hpp @@ -28,15 +28,11 @@ #define GVOHUB_HPP /* __ Definitions ________________________________________________________ */ -#define GVOHUB_NB_CLIENTS 5 -#define GVOHUB_NB_METHODS 128 -#define GVO_HUB_testing 1 /* __ Includes ___________________________________________________________ */ #include -#include +#include #include -#include #include "GBase.hpp" #include "GXml.hpp" #include "GXmlNode.hpp" @@ -71,82 +67,78 @@ public: protected: // Protected methods - void init_members(void); - void copy_members(const GVOHub& client); - void free_members(void); - void start_hub(void); - void handle_request(const socklen_t& sock); - void request_ping(const socklen_t& sock); - void request_register(const GXml& xml, - const socklen_t& sock); - void request_unregister(const GXml& xml, + void init_members(void); + void copy_members(const GVOHub& client); + void free_members(void); + void start_hub(void); + void handle_request(const socklen_t& sock); + void request_ping(const socklen_t& sock); + void request_register(const GXml& xml, const socklen_t& sock); - void request_declare_metadata(const GXml& xml, - const socklen_t& sock); - void request_declare_subscriptions(const GXml& xml, - const socklen_t& sock); - void request_set_xml_rpc_callback(const GXml& xml, - const socklen_t& sock); - void request_get_subscriptions(const GXml& xml, - const socklen_t& sock); - void request_get_registered_clients(const GXml& xml, - const socklen_t& sock); - void request_get_subscribed_clients(const GXml& xml, - const socklen_t& sock); - void request_get_metadata(const GXml& xml, + void request_unregister(const GXml& xml, const socklen_t& sock); - void request_shutdown(const socklen_t& sock); - std::string get_client_key(const GXml& xml) const; - int get_client_index(const GXml& xml) const; - std::string get_response_value(const GXml& xml, - const std::string& name) const; - void get_name_value_pair(const GXmlNode* node, - std::string& name, - std::string& value) const; - std::list get_registrations(const GXml& xml) const; - std::string get_callback_port(const GXml& xml) const; - std::string get_hub_lockfile(void) const; - void activate_callbacks(std::string method, char cl_id[31]); + void request_declare_metadata(const GXml& xml, + const socklen_t& sock); + void request_declare_subscriptions(const GXml& xml, + const socklen_t& sock); + void request_set_xml_rpc_callback(const GXml& xml, + const socklen_t& sock); + void request_get_subscriptions(const GXml& xml, + const socklen_t& sock); + void request_get_registered_clients(const GXml& xml, + const socklen_t& sock); + void request_get_subscribed_clients(const GXml& xml, + const socklen_t& sock); + void request_get_metadata(const GXml& xml, + const socklen_t& sock); + void request_shutdown(const socklen_t& sock); + std::string get_client_key(const GXml& xml) const; + int get_client_index(const GXml& xml) const; + std::string get_response_value(const GXml& xml, + const std::string& name) const; + void get_name_value_pair(const GXmlNode* node, + std::string& name, + std::string& value) const; + std::vector get_subscriptions(const GXml& xml) const; + std::string get_callback_url(const GXml& xml) const; + std::string get_hub_lockfile(void) const; + void send_notifications(const std::string& method, + const std::string& client); // Low-level methods void create_samp_file(void) const; + void post_samp_ok(const socklen_t& sock) const; void post_string(const std::string& content, const socklen_t& sock) const; - void post_string_callback(const std::string& content) const; + void notify(const std::string& url, const std::string& notification) const; std::string random_string(const size_t& length) const; - // Protected structures - typedef struct { - char private_key[16]; - char name[32]; - char reference[32]; - char description[256]; - char icon[32]; - char documentation[32]; - char affiliation[32]; - char author_name[32]; - char email[32]; - char homepage[32]; - char port[32]; - char registered_methods[GVOHUB_NB_METHODS][GVOHUB_NB_METHODS]; //128 methods of 128 cars max. - } connected_shm; - typedef struct { - int registered; - sem_t lock; - connected_shm metadata[GVOHUB_NB_CLIENTS]; - } clients; + // Protected structure + struct client { + std::string name; + std::string private_key; + std::string reference; + std::string description; + std::string icon; + std::string documentation; + std::string affiliation; + std::string author_name; + std::string email; + std::string homepage; + std::string url; + std::vector subscriptions; + }; // Protected members - std::string m_secret; //!< Secret Hub key - std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub - std::string m_hub_host; //!< Hub host (extracted from XML-RPC endpoint) - std::string m_hub_port; //!< Hub port (extracted from XML-RPC endpoint) - std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub - std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others - socklen_t m_socket; //!< Hub socket - int m_cback_socket; //!< Hub socket to callback clients - clients* m_clients; //!< Structure of registered clients - void* m_shmem; //!< Pointer to shared memory address - int m_shmem_handler; //!< Handler to shared memory + std::string m_secret; //!< Secret Hub key + std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub + std::string m_hub_host; //!< Hub host + std::string m_hub_port; //!< Hub port + std::string m_hub_path; //!< Hub path + std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub + std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others + socklen_t m_socket; //!< Hub socket + bool m_shutdown; //!< Shutdown request + std::vector m_clients; //!< Clients }; diff --git a/src/vo/GVOClient.cpp b/src/vo/GVOClient.cpp index 0e91644..66a9327 100644 --- a/src/vo/GVOClient.cpp +++ b/src/vo/GVOClient.cpp @@ -867,9 +867,6 @@ void GVOClient::connect_to_hub(void) const break; } } - else { - break; - } } // endfor: looped through all results @@ -917,7 +914,7 @@ void GVOClient::post_string(const std::string& content) const bool done = false; do { int length = post.length() + 1; // +1 for terminating 0 - int sent_length = send(m_socket, post.c_str(), length+1, 0); + int sent_length = send(m_socket, post.c_str(), length, 0); if (sent_length < length) { post = post.substr(sent_length, std::string::npos); } diff --git a/src/vo/GVOHub.cpp b/src/vo/GVOHub.cpp index 89a6131..96e1e4b 100644 --- a/src/vo/GVOHub.cpp +++ b/src/vo/GVOHub.cpp @@ -57,10 +57,9 @@ /* __ Coding definitions _________________________________________________ */ #define G_KEY 12345 //#define G_USE_FORK -//#define G_USE_SHMEM /* __ Debug definitions __________________________________________________ */ -//#define G_CONSOLE_DUMP +#define G_CONSOLE_DUMP /*========================================================================== @@ -217,8 +216,9 @@ std::string GVOHub::print(const GChatter& chatter) const result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id); result.append("\n"+gammalib::parformat("Hub key")+m_secret); result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url); - result.append("\n"+gammalib::parformat("Hub host (port)")); - result.append(m_hub_host+" ("+m_hub_port+")"); + result.append("\n"+gammalib::parformat("Hub host")+m_hub_host); + result.append("\n"+gammalib::parformat("Hub port")+m_hub_port); + result.append("\n"+gammalib::parformat("Hub path")+m_hub_path); result.append("\n"+gammalib::parformat("SAMP protocol version")); result.append(m_version); @@ -243,50 +243,14 @@ void GVOHub::init_members(void) // Initialise members m_secret = random_string(15); m_hub_host = "127.0.0.1"; - m_hub_port = "2525"; - m_hub_url = "http://"+m_hub_host+":"+m_hub_port+"/xmlrpc"; + m_hub_port = "2526"; + m_hub_path = "xmlrpc"; + m_hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path; m_version = "1.3"; m_hub_id = "gammalib_hub"; m_socket = -1; // Signals no socket - m_cback_socket = -1; // Signals no socket - m_clients = NULL; - m_shmem = NULL; - m_shmem_handler = 0; - - #if defined(G_USE_SHMEM) - // Get shared memory for handling of clients - if ((m_shmem_handler = shmget(G_KEY, sizeof(clients), 0666 | IPC_CREAT)) < 0) { - std::string msg = "Could not open shared memory."; - throw GException::invalid_value(G_INIT_MEMBERS, msg); - } - - // Get pointer on shared memory - if ((m_shmem = shmat(m_shmem_handler, NULL, 0)) == (void*) -1) { - std::string msg = "Could not attach shared memory."; - throw GException::invalid_value(G_INIT_MEMBERS, msg); - } - - // Get pointer - m_clients = static_cast(m_shmem); - #else - m_clients = new clients; - #endif - - // Initialise shared memory - m_clients->registered = 0; - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) { - strcpy(m_clients->metadata[i].reference, "NoRef"); - strcpy(m_clients->metadata[i].private_key, "Unknown"); - strcpy(m_clients->metadata[i].name, "Unknown"); - strcpy(m_clients->metadata[i].icon, "Unknown"); - strcpy(m_clients->metadata[i].documentation,"Unknown"); - strcpy(m_clients->metadata[i].affiliation, "Unknown"); - strcpy(m_clients->metadata[i].author_name, "Unknown"); - strcpy(m_clients->metadata[i].email, "Unknown"); - strcpy(m_clients->metadata[i].homepage, "Unknown"); - strcpy(m_clients->metadata[i].port, "Unknown"); - strcpy(m_clients->metadata[i].description, "Unknown"); - } + m_clients.clear(); + m_shutdown = false; // Return return; @@ -301,16 +265,16 @@ void GVOHub::init_members(void) void GVOHub::copy_members(const GVOHub& hub) { // Copy members - m_secret = hub.m_secret; - m_hub_url = hub.m_hub_url; - m_hub_host = hub.m_hub_host; - m_hub_port = hub.m_hub_port; - m_version = hub.m_version; - m_hub_id = hub.m_hub_id; - m_socket = hub.m_socket; - m_cback_socket = hub.m_cback_socket; - - //TODO: What to do with shared memory? Copy over all data? + m_secret = hub.m_secret; + m_hub_url = hub.m_hub_url; + m_hub_host = hub.m_hub_host; + m_hub_port = hub.m_hub_port; + m_hub_path = hub.m_hub_path; + m_version = hub.m_version; + m_hub_id = hub.m_hub_id; + m_socket = hub.m_socket; + m_clients = hub.m_clients; + m_shutdown = hub.m_shutdown; // Return return; @@ -327,22 +291,11 @@ void GVOHub::free_members(void) close(m_socket); m_socket = -1; } - if (m_cback_socket != -1) { - close(m_cback_socket); - m_cback_socket = -1; - } // Remove lockfile std::string lockurl = get_hub_lockfile(); std::remove(lockurl.c_str()); - // Release shared memory - #if defined(G_USE_SHMEM) - struct shmid_ds *buf; - shmdt(m_shmem); - shmctl(m_shmem_handler, IPC_RMID, buf); - #endif - // Return return; } @@ -358,9 +311,6 @@ void GVOHub::free_members(void) ***************************************************************************/ void GVOHub::start_hub(void) { - // Set maximum number of clients - int max_clients = 10; - // Prepare TCP/IP structure struct sockaddr_in serv_addr; std::memset(&serv_addr, 0, sizeof(serv_addr)); @@ -368,12 +318,6 @@ void GVOHub::start_hub(void) serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str()); serv_addr.sin_port = htons(gammalib::toint(m_hub_port)); - // Initialise all client_socket[] to 0 so not checked - socklen_t client_socket[max_clients]; - for (int i = 0; i < max_clients; ++i) { - client_socket[i] = 0; - } - // Create Hub socket m_socket = socket(AF_INET, SOCK_STREAM, 0); @@ -463,7 +407,7 @@ void GVOHub::start_hub(void) // If we have received a shutdown request then exit the event // loop - if (m_clients->registered == -1) { + if (o_clients->registered == -1) { break; } @@ -477,7 +421,7 @@ void GVOHub::start_hub(void) // If we have received a shutdown request then exit the event // loop - if (m_clients->registered == -1) { + if (m_shutdown) { break; } #endif @@ -559,16 +503,16 @@ void GVOHub::handle_request(const socklen_t& sock) request_register(xml, sock); } else if (method_called.compare("samp.hub.unregister") == 0) { - request_unregister(xml,sock); + request_unregister(xml, sock); } else if (method_called.compare("samp.hub.declareMetadata") == 0) { - request_declare_metadata(xml,sock); + request_declare_metadata(xml, sock); } else if (method_called.compare("samp.hub.declareSubscriptions") == 0) { - request_declare_subscriptions(xml,sock); + request_declare_subscriptions(xml, sock); } else if (method_called.compare("samp.hub.setXmlrpcCallback") == 0) { - request_set_xml_rpc_callback(xml,sock); + request_set_xml_rpc_callback(xml, sock); } else if (method_called.compare("samp.hub.getSubscriptions") == 0) { request_get_subscriptions(xml, sock); @@ -623,21 +567,23 @@ void GVOHub::request_ping(const socklen_t& sock) std::cout << "GVOHub::request_ping" << std::endl; #endif - // Declare message - std::string msg = ""; + // Declare response + std::string response = ""; // Set response - msg.append("\n"); - msg.append("\n"); - msg.append("\n"); - msg.append(" \n"); - msg.append("\n"); - msg.append("\n"); + response.append("\n"); + response.append("\n"); + response.append(" \n"); + response.append(" \n"); + response.append(" \n"); + response.append(" \n"); + response.append(" \n"); + response.append("\n"); // Post response - post_string(msg,sock); + post_string(response, sock); - //Return + // Return return; } @@ -657,58 +603,56 @@ void GVOHub::request_register(const GXml& xml, const socklen_t& sock) std::cout << "GVOHub::request_register" << std::endl; #endif - // Initialize values - char cl_id[31]; - char selfid[124]; - char privatekey[124]; - std::string secret = random_string(15); - std::string translator = m_hub_url; + // Create a new client + struct client voclient; + voclient.reference = "c"+gammalib::str(m_clients.size()); + voclient.private_key = random_string(15); - // Search for a new free slot - bool found = false; - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) { - if (strcmp(m_clients->metadata[i].reference, "NoRef") == 0) { - sprintf(cl_id, "c%d",i); - strcpy(m_clients->metadata[i].reference, cl_id); - sprintf(m_clients->metadata[i].private_key, "%s", secret.c_str()); - found = true; - break; - } + // Attached client + m_clients.push_back(voclient); + /* + for (int i = 0; i < m_clients.size(); ++i) { + std::cout << "Client i " << m_clients[i].reference << " key=" << m_clients[i].private_key << std::endl; } - - // Throw an exception if no free slot is available - if (!found) { - std::string msg = "No free slot found for client."; - throw GException::invalid_value(G_REGISTER_SERVICE, msg); - } - - // Set self ID and private key - sprintf(selfid, " samp.self-id%s\n",cl_id); - sprintf(privatekey, " samp.private-key%s\n",secret.c_str()); + */ // Declare response std::string msg = ""; - msg.append("\n"); + + // Set response + msg.append("\n"); msg.append("\n"); msg.append("\n"); msg.append(" \n"); - msg.append(" samp.hub-id" + m_hub_id + "\n"); - msg.append(selfid); - msg.append(privatekey); - msg.append(" samp.statussamp.ok\n"); - msg.append(" samp.url-translator" + translator + "\n"); + msg.append(" \n"); + msg.append(" samp.private-key\n"); + msg.append(" "+voclient.private_key+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.hub-id\n"); + msg.append(" "+m_hub_id+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.self-id\n"); + msg.append(" "+voclient.reference+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.status\n"); + msg.append(" samp.ok\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.url-translator\n"); + msg.append(" "+m_hub_url+"\n"); + msg.append(" \n"); msg.append(" \n"); msg.append("\n"); msg.append("\n"); // Post response - post_string(msg,sock); - - // Activate callbacks - activate_callbacks("samp.hub.event.register", cl_id); + post_string(msg, sock); - // Increment number of registered clients - //m_clients->registered++; + // Send notifications + send_notifications("samp.hub.event.register", voclient.reference); //Return return; @@ -750,22 +694,21 @@ void GVOHub::request_unregister(const GXml& xml, const socklen_t& sock) // Post response post_string(msg, sock); - // Activate callbacks - activate_callbacks("samp.hub.event.unregister", - m_clients->metadata[i].reference); - - // Reset client entry - strcpy(m_clients->metadata[i].reference, "NoRef"); - sprintf(m_clients->metadata[i].name, "Unknown"); - sprintf(m_clients->metadata[i].description, "Unknown"); - sprintf(m_clients->metadata[i].icon, "Unknown"); - sprintf(m_clients->metadata[i].documentation, "Unknown"); - sprintf(m_clients->metadata[i].affiliation, "Unknown"); - sprintf(m_clients->metadata[i].email, "Unknown"); - sprintf(m_clients->metadata[i].author_name, "Unknown"); - sprintf(m_clients->metadata[i].homepage, "Unknown"); + // Send notifications + send_notifications("samp.hub.event.unregister", + m_clients[i].reference); + + // Remove client + m_clients.erase(m_clients.begin()+i); } // endif: valid client found + + // Signal if the client was unknown + #if defined(G_CONSOLE_DUMP) + else { + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl; + } + #endif // Return return; @@ -793,25 +736,15 @@ void GVOHub::request_declare_metadata(const GXml& xml, const socklen_t& sock) // Continue only if index is valid if (i != -1) { - // Get metadata - std::string client_name = get_response_value(xml, "samp.name"); - std::string client_description = get_response_value(xml, "samp.description.text"); - std::string client_icon = get_response_value(xml, "samp.icon.url"); - std::string client_doc = get_response_value(xml, "samp.documentation.url"); - std::string client_affi = get_response_value(xml, "author.affiliation"); - std::string client_mail = get_response_value(xml, "author.email"); - std::string client_authname = get_response_value(xml, "author.name"); - std::string client_page = get_response_value(xml, "home.page"); - // Store metadata - sprintf(m_clients->metadata[i].name, "%s", client_name.c_str()); - sprintf(m_clients->metadata[i].description, "%s", client_description.c_str()); - sprintf(m_clients->metadata[i].icon, "%s", client_icon.c_str()); - sprintf(m_clients->metadata[i].documentation, "%s", client_doc.c_str()); - sprintf(m_clients->metadata[i].affiliation, "%s", client_affi.c_str()); - sprintf(m_clients->metadata[i].email, "%s", client_mail.c_str()); - sprintf(m_clients->metadata[i].author_name, "%s", client_authname.c_str()); - sprintf(m_clients->metadata[i].homepage, "%s", client_page.c_str()); + m_clients[i].name = get_response_value(xml, "samp.name");; + m_clients[i].description = get_response_value(xml, "samp.description.text"); + m_clients[i].icon = get_response_value(xml, "samp.icon.url"); + m_clients[i].documentation = get_response_value(xml, "samp.documentation.url"); + m_clients[i].affiliation = get_response_value(xml, "author.affiliation"); + m_clients[i].email = get_response_value(xml, "author.email"); + m_clients[i].author_name = get_response_value(xml, "author.name"); + m_clients[i].homepage = get_response_value(xml, "home.page"); // Declare message std::string msg = ""; @@ -826,8 +759,8 @@ void GVOHub::request_declare_metadata(const GXml& xml, const socklen_t& sock) // Post response post_string(msg,sock); - // Activate callbacks - activate_callbacks("samp.hub.event.metadata", m_clients->metadata[i].reference); + // Send notifications + send_notifications("samp.hub.event.metadata", m_clients[i].reference); } // endif: client found @@ -864,32 +797,25 @@ void GVOHub::request_declare_subscriptions(const GXml& xml,const socklen_t& sock // Continue only if index is valid if (i != -1) { - // Do stuff - int j; - std::list::iterator p; - std::ofstream myfile; - std::string tempo; - std::list client_subscriptions = get_registrations(xml); - for (j = 0, p=client_subscriptions.begin(); jmetadata[i].registered_methods[j], "%s", tempo.c_str()); - } + // Get subscriptions + std::vector subscriptions = get_subscriptions(xml); - // Declare response - std::string msg = ""; - msg.append("\n"); - msg.append("\n"); - msg.append("\n"); - msg.append(" \n"); - msg.append(" samp.statussamp.ok\n"); - msg.append(" \n"); - msg.append("\n"); - msg.append("\n"); + // Store subscriptions + for (int k = 0; k < subscriptions.size(); ++k) { + m_clients[i].subscriptions.push_back(subscriptions[k]); + } - // Post string - post_string(msg,sock); + // Post SAMP ok + post_samp_ok(sock); } // endif: valid client found + + // Signal if the client was unknown + #if defined(G_CONSOLE_DUMP) + else { + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl; + } + #endif //Return return; @@ -904,11 +830,12 @@ void GVOHub::request_declare_subscriptions(const GXml& xml,const socklen_t& sock * * Handles all incoming XML-RPC callback setting requests. ***************************************************************************/ -void GVOHub::request_set_xml_rpc_callback(const GXml& xml,const socklen_t& sock) +void GVOHub::request_set_xml_rpc_callback(const GXml& xml, + const socklen_t& sock) { // Header #if defined(G_CONSOLE_DUMP) - std::cout << "GVOHub::request_declare_subscriptions" << std::endl; + std::cout << "GVOHub::request_set_xml_rpc_callback" << std::endl; #endif // Get client index @@ -917,31 +844,24 @@ void GVOHub::request_set_xml_rpc_callback(const GXml& xml,const socklen_t& sock) // Continue only if index is valid if (i != -1) { - // Get callback port - std::string client_port = get_callback_port(xml); + // Get callback URL + std::string client_url = get_callback_url(xml); - // Set callback port value - sprintf(m_clients->metadata[i].port, "%s", client_port.c_str()); + // Set callback URL + m_clients[i].url = get_callback_url(xml); - // Declare message - std::string msg = ""; - - // The hub response to rpc callback declaration has no useful - // content and can be discarded by the client. - msg.append("\n"); - msg.append("\n"); - msg.append("\n"); - msg.append(" \n"); - msg.append(" samp.statussamp.ok\n"); - msg.append(" \n"); - msg.append("\n"); - msg.append("\n"); - - // Post message - post_string(msg, sock); + // Post SAMP ok + post_samp_ok(sock); } // endif: client found + // Signal if the client was unknown + #if defined(G_CONSOLE_DUMP) + else { + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl; + } + #endif + // Return return; } @@ -955,7 +875,7 @@ void GVOHub::request_set_xml_rpc_callback(const GXml& xml,const socklen_t& sock) * * Handles all incoming subscriptions getting requests. ***************************************************************************/ -void GVOHub::request_get_subscriptions(const GXml& xml,const socklen_t& sock) +void GVOHub::request_get_subscriptions(const GXml& xml, const socklen_t& sock) { // Header #if defined(G_CONSOLE_DUMP) @@ -978,18 +898,14 @@ void GVOHub::request_get_subscriptions(const GXml& xml,const socklen_t& sock) msg.append(" \n"); // Append all subscriptions - char tempo[128]; - for (int j = 0; j < GVOHUB_NB_METHODS; ++j) { - strcpy(tempo, m_clients->metadata[i].registered_methods[j]); - if (strcmp("", tempo) != 0) { - msg.append(" \n"); - msg.append(" "); - msg.append(tempo); - msg.append("\n"); - msg.append(" \n)"); - msg.append(" \n"); - } - } + for (int k = 0; k < m_clients[i].subscriptions.size(); ++k) { + msg.append(" \n"); + msg.append(" "); + msg.append(m_clients[i].subscriptions[k]); + msg.append("\n"); + msg.append(" \n)"); + msg.append(" \n"); + } // Finish response msg.append(" \n"); @@ -997,9 +913,16 @@ void GVOHub::request_get_subscriptions(const GXml& xml,const socklen_t& sock) msg.append("\n"); // Post response - post_string(msg,sock); + post_string(msg, sock); } // endif: client index was valid + + // Signal if the client was unknown + #if defined(G_CONSOLE_DUMP) + else { + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl; + } + #endif // Return return; @@ -1035,13 +958,11 @@ void GVOHub::request_get_registered_clients(const GXml& xml, const socklen_t& so msg.append(" gammalib_hub\n"); // Loop over all clients. Do not send back current client's registration - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) { - if (strcmp(m_clients->metadata[i].reference,"NoRef") != 0) { - if (strcmp(m_clients->metadata[i].private_key, key.c_str()) != 0) { - msg.append(" "); - msg.append(m_clients->metadata[i].reference); - msg.append("\n"); - } + for (int i = 0; i < m_clients.size(); ++i) { + if (m_clients[i].private_key != key) { + msg.append(" "); + msg.append(m_clients[i].reference); + msg.append("\n"); } } @@ -1053,7 +974,7 @@ void GVOHub::request_get_registered_clients(const GXml& xml, const socklen_t& so // Post response post_string(msg, sock); - //Return + // Return return; } @@ -1107,7 +1028,7 @@ void GVOHub::request_get_subscribed_clients(const GXml& xml, const socklen_t& so msg.append("\n"); // Post message - post_string(msg,sock); + post_string(msg, sock); // Return return; @@ -1168,28 +1089,28 @@ void GVOHub::request_get_metadata(const GXml& xml,const socklen_t& sock) // Append response msg.append(" samp.name"); - msg.append(m_clients->metadata[i].name); + msg.append(m_clients[i].name); msg.append("\n"); msg.append(" samp.description.text"); - msg.append(m_clients->metadata[i].description); + msg.append(m_clients[i].description); msg.append("\n"); msg.append(" samp.icon.url"); - msg.append(m_clients->metadata[i].icon); + msg.append(m_clients[i].icon); msg.append("\n"); msg.append(" samp.documentation.url"); - msg.append(m_clients->metadata[i].documentation); + msg.append(m_clients[i].documentation); msg.append("\n"); msg.append(" author.affiliation"); - msg.append(m_clients->metadata[i].affiliation); + msg.append(m_clients[i].affiliation); msg.append("\n"); msg.append(" author.email"); - msg.append(m_clients->metadata[i].email); + msg.append(m_clients[i].email); msg.append("\n"); msg.append(" author.name"); - msg.append(m_clients->metadata[i].author_name); + msg.append(m_clients[i].author_name); msg.append("\n"); msg.append(" home.page"); - msg.append(m_clients->metadata[i].homepage); + msg.append(m_clients[i].homepage); msg.append("\n"); } // endif: index was valid @@ -1224,21 +1145,10 @@ void GVOHub::request_shutdown(const socklen_t& sock) #endif // Set shutdown flag - m_clients->registered = -1; + m_shutdown = true; - // Declare message - std::string msg = ""; - - // Set response - msg.append("\n"); - msg.append("\n"); - msg.append("\n"); - msg.append(" \n"); - msg.append("\n"); - msg.append("\n"); - - // Post response - post_string(msg,sock); + // Post SAMP ok + post_samp_ok(sock); // Return return; @@ -1300,9 +1210,9 @@ int GVOHub::get_client_index(const GXml& xml) const // Continue only if string is not empty if (!key.empty()) { - // Searches for key in metadata - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) { - if (strcmp(m_clients->metadata[i].private_key, key.c_str()) == 0) { + // Searches for key in clients + for (int i = 0; i < m_clients.size(); ++i) { + if (m_clients[i].private_key == key) { index = i; break; } @@ -1400,18 +1310,18 @@ void GVOHub::get_name_value_pair(const GXmlNode* node, /***********************************************************************//** - * @brief Returns registrations from XML document + * @brief Returns subscriptions from XML document * * @param[in] xml client query XML document. - * @return List of registrations. + * @return List of subscriptions. ***************************************************************************/ -std::list GVOHub::get_registrations(const GXml& xml) const +std::vector GVOHub::get_subscriptions(const GXml& xml) const { - // Declare value - std::list value; + // Declare subscriptions + std::vector subscriptions; // Get the client's private key - const GXmlNode* node = xml.element("methodCall > params > param > value > struct"); + const GXmlNode* node = xml.element("methodCall > params > param[1] > value > struct"); if (node != NULL) { int num = node->elements("member"); for (int i = 0; i < num; ++i) { @@ -1421,40 +1331,40 @@ std::list GVOHub::get_registrations(const GXml& xml) const if (name != NULL) { const GXmlText* text = static_cast((*name)[0]); if (text != NULL) { - value.push_front(text->text()); + subscriptions.push_back(text->text()); } } } } } - // Return value - return value; + // Return subscriptions + return subscriptions; } /***********************************************************************//** - * @brief Returns callback port + * @brief Returns callback URL of client * * @param[in] xml client query XML document. - * @return Callback port value. + * @return Callback URL of client. ***************************************************************************/ -std::string GVOHub::get_callback_port(const GXml& xml) const +std::string GVOHub::get_callback_url(const GXml& xml) const { - // Declare value - std::string value; + // Declare URL + std::string url; // Get the client's private key const GXmlNode* node = xml.element("methodCall > params > param[1] > value"); if (node != NULL) { const GXmlText* text = static_cast((*node)[0]); if (text != NULL) { - value.append(text->text()); + url.append(text->text()); } } - // Return value - return value; + // Return URL + return url; } @@ -1510,186 +1420,188 @@ std::string GVOHub::get_hub_lockfile(void) const /***********************************************************************//** - * @brief Test if any registered client needs to know that the method - * has been called + * @brief Send notifications * - * @param[in] method: name of the method - * @param[in] cl_id id of calling client + * @param[in] method Name of the method + * @param[in] client Reference of the client + * + * The method send notifications to all registered clients that request so. ***************************************************************************/ -void GVOHub::activate_callbacks(std::string method,char cl_id[31]) +void GVOHub::send_notifications(const std::string& method, + const std::string& client) { - int k; - char port[16]; - char pkey[16]; - std::string spkey; - // Loop over all clients - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) { + for (int i = 0; i < m_clients.size(); ++i) { // Loop over all methods - for (int j = 0; j < GVOHUB_NB_METHODS; ++j) { + for (int j = 0; j < m_clients[i].subscriptions.size(); ++j) { + + // Continue only if method matches + if (method == m_clients[i].subscriptions[j]) { - // Continue only if method is valid - if (strcmp("",m_clients->metadata[i].registered_methods[j]) != 0) { - - // - if (strcmp(method.c_str(), m_clients->metadata[i].registered_methods[j]) == 0) { - strcpy(port,m_clients->metadata[i].port); - std::string port_string = std::string(port); - //Eliminate http://127.0.0.1/ from port string -----> improve this code is necessary - port_string.replace(0,17,""); - std::size_t pos = port_string.find("/"); - std::string port_only = port_string.substr(0,pos); - - // Set hints - struct addrinfo hints; - std::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - // Get server information - struct addrinfo* servinfo; - if (getaddrinfo("127.0.0.1", port_only.c_str(), - &hints, &servinfo) == 0) { - - // Loop through all the results and connect to the first - // we can - for (struct addrinfo* ptr = servinfo; ptr != NULL; ptr = ptr->ai_next) { - - // Create socket - m_cback_socket = socket(ptr->ai_family, - ptr->ai_socktype, - ptr->ai_protocol); - - // Connect to socket if socket is valid - if (m_cback_socket != -1) { - if (::connect(m_cback_socket, - ptr->ai_addr, - ptr->ai_addrlen) == -1) { - close(m_cback_socket); - m_cback_socket = -1; - } - } - - } // endfor: looped through all results - - } // endif: server information was valid - - // - std::string msg = ""; - - // - if (strcmp(method.c_str(),"samp.hub.event.register") == 0) { - - // Set methodResponse elts for samp.hub.event.register - msg.append("\n"); - msg.append("samp.client.receiveNotification\n"); - msg.append("\t\n"); - msg.append("\t\t"); - msg.append(m_clients->metadata[i].private_key); - msg.append("\n"); - msg.append("\t\t"+m_hub_id+"\n"); - msg.append("\t\t\n\t\t\t\n\t\t\t\t\n"); - msg.append("\t\t\t\t\tsamp.mtypesamp.hub.event.register\n"); - msg.append("\t\t\t\t\tsamp.params\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t"); - msg.append("id"); - msg.append(cl_id); - msg.append("\n\t\t\t\t\t\t\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\n\t\t\t\n\t\t\n"); - msg.append("\t\n"); - msg.append("\n"); + // Declare notification + std::string msg = ""; + + // Register + if (method == "samp.hub.event.register") { + + // Set response for samp.hub.event.register + msg.append("\n"); + msg.append("\n"); + msg.append("samp.client.receiveNotification\n"); + msg.append("\n"); + msg.append(" "); + msg.append(m_clients[i].private_key); + msg.append("\n"); + msg.append(" "+m_hub_id+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.mtype\n"); + msg.append(" samp.hub.event.register\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.params\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" id\n"); + msg.append(" "+client+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append("\n"); + msg.append("\n"); - // Post response - post_string_callback(msg); + // Post notification + notify(m_clients[i].url, msg); - } + } - // - else if (strcmp(method.c_str(),"samp.hub.event.unregister") == 0) { - - // Set methodResponse elts for samp.hub.event.unregister - msg.append("\n"); - msg.append("samp.client.receiveNotification\n"); - msg.append("\t\n"); - msg.append("\t\t"); - msg.append(m_clients->metadata[i].private_key); - msg.append("\n"); - msg.append("\t\t"+m_hub_id+"\n"); - msg.append("\t\t\n\t\t\t\n\t\t\t\t\n"); - msg.append("\t\t\t\t\tsamp.mtypesamp.hub.event.unregister\n"); - msg.append("\t\t\t\t\tsamp.params\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t"); - msg.append("id"); - msg.append(cl_id); - msg.append("\n\t\t\t\t\t\t\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\n\t\t\t\n\t\t\n"); - msg.append("\t\n"); - msg.append("\n"); + // Unregister + else if (method == "samp.hub.event.unregister") { + + // Set response for samp.hub.event.unregister + msg.append("\n"); + msg.append("\n"); + msg.append("samp.client.receiveNotification\n"); + msg.append("\n"); + msg.append(" "); + msg.append(m_clients[i].private_key); + msg.append("\n"); + msg.append(" "); + msg.append(m_hub_id); + msg.append("\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.mtype\n"); + msg.append(" samp.hub.event.unregister\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.params\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" id\n"); + msg.append(" "+client+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append("\n"); + msg.append("\n"); - // Post response - post_string_callback(msg); + // Post notification + notify(m_clients[i].url, msg); - } + } - // - else if (strcmp(method.c_str(),"samp.hub.event.metadata") == 0) { - - // Set methodResponse elts for samp.hub.event.unregister - msg.append("\n"); - msg.append("samp.client.receiveNotification\n"); - msg.append("\t\n"); - msg.append("\t\t"); - msg.append(m_clients->metadata[i].private_key); - msg.append("\n"); - msg.append("\t\t"+m_hub_id+"\n"); - msg.append("\t\t\n\t\t\t\n\t\t\t\t\n"); - msg.append("\t\t\t\t\tsamp.mtypesamp.hub.event.metadata\n"); - msg.append("\t\t\t\t\tsamp.params\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t"); - msg.append("\t\t\t\t\tid"); - for (k = 0; k < GVOHUB_NB_CLIENTS; k++) { - if (strcmp(cl_id,m_clients->metadata[k].reference) == 0) { - break; - } + // Metadata + else if (method == "samp.hub.event.metadata") { + + // Get index of client + int k; + for (k = 0; k < m_clients.size(); ++k) { + if (m_clients[k].reference == client) { + break; } - msg.append(m_clients->metadata[k].reference); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\tmetadata\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\tsamp.name\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].name); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\tsamp.description.text\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].description); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\tsamp.icon.url\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].icon); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\tsamp.documentation.url\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].documentation); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\tauthor.affiliation\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].affiliation); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\tauthor.email\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].email); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\tauthor.name\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].author_name); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\t\n\t\t\t\t\t\thome.page\n\t\t\t\t\t\t"); - msg.append(m_clients->metadata[k].homepage); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\n"); - msg.append("\n\t\t\t\t\t\n"); - msg.append("\t\t\t\t\n\t\t\t\n\t\t\n"); - msg.append("\t\n"); - msg.append("\n"); + } + + // Fall through if client index is not valid + if (k >= m_clients.size()) { + continue; + } + + // Set response for samp.hub.event.metadata + msg.append("\n"); + msg.append("samp.client.receiveNotification\n"); + msg.append("\n"); + msg.append(" "); + msg.append(m_clients[i].private_key); + msg.append("\n"); + msg.append(" "+m_hub_id+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.mtype\n"); + msg.append(" samp.hub.event.metadata\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.params\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" id\n"); + msg.append(" "+m_clients[k].reference+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" metadata\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.name\n"); + msg.append(" "+m_clients[k].name+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.description.text\n"); + msg.append(" "+m_clients[k].description+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.icon.url\n"); + msg.append(" "+m_clients[k].icon+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" samp.documentation.url\n"); + msg.append(" "+m_clients[k].documentation+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" author.affiliation\n"); + msg.append(" "+m_clients[k].affiliation+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" author.name\n"); + msg.append(" "+m_clients[k].author_name+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" author.email\n"); + msg.append(" "+m_clients[k].email+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" home.page\n"); + msg.append(" "+m_clients[k].homepage+"\n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append(" \n"); + msg.append("\n"); + msg.append("\n"); - // Post response - post_string_callback(msg); + // Post notification + notify(m_clients[i].url, msg); - } - } - } // endif: method was valid + } // endelse: metadata + + } // endif: method was requested one + } // endfor: looped over all methods + } // endfor: looped over all clients // Return @@ -1709,37 +1621,61 @@ void GVOHub::create_samp_file(void) const // Open SAMP lockfile. Continue only if opening was successful FILE* fptr = fopen(lockurl.c_str(), "w"); + + // Successful? if (fptr != NULL) { - // If successful writes basic hub configuration to the lockfile - fputs("# SAMP lockfile \n# Required keys:\n",fptr); - char sampsecret[256] = "samp.secret="; - strcat(sampsecret,m_secret.c_str()); - strcat(sampsecret,"\n"); - fputs (sampsecret,fptr); - char sampurl[256] = "samp.hub.xmlrpc.url="; - strcat(sampurl,m_hub_url.c_str()); - strcat(sampurl,"\n"); - fputs(sampurl,fptr); - char samprofile[256] = "samp.profile.version="; - strcat(samprofile,m_version.c_str()); - strcat(samprofile,"\n"); - fputs(samprofile,fptr); - fputs("# Info stored by hub for some private reason:\n",fptr); - char sampid[256] = "gammalib.hubid="; - strcat(sampid,m_hub_id.c_str()); - strcat(sampid,"\n"); - fputs(sampid,fptr); + // Write lockfile + fprintf(fptr, "# SAMP lockfile\n"); + fprintf(fptr, "# Required keys:\n"); + fprintf(fptr, "samp.secret=%s\n", m_secret.c_str()); + fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", m_hub_url.c_str()); + fprintf(fptr, "samp.profile.version=%s\n", m_version.c_str()); + fprintf(fptr, "# Info stored by hub for some private reason:\n"); + fprintf(fptr, "gammalib.hubid=%s\n", m_hub_id.c_str()); + + // Close lockfile + fclose(fptr); + } - - // Close SAMP lockfile - fclose(fptr); // Return return; } +/***********************************************************************//** + * @brief Post SAMP ok massage to client + * + * @param[in] sock Socket. + * + * Posts a SAMP of massage to a client. + ***************************************************************************/ +void GVOHub::post_samp_ok(const socklen_t& sock) const +{ + // Declare response + std::string response = ""; + + // Compose response + response.append("\n"); + response.append("\n"); + response.append("\n"); + response.append(" \n"); + response.append(" \n"); + response.append(" samp.status\n"); + response.append(" samp.ok\n"); + response.append(" \n"); + response.append(" \n"); + response.append("\n"); + response.append("\n"); + + // Post string + post_string(response, sock); + + // Return + return; +} + /***********************************************************************//** * @brief Post string content to client @@ -1749,7 +1685,7 @@ void GVOHub::create_samp_file(void) const * * Posts the content of a string to a client. ***************************************************************************/ -void GVOHub::post_string(const std::string& content,const socklen_t& sock) const +void GVOHub::post_string(const std::string& content, const socklen_t& sock) const { // Continue only if socket is valid if (sock != -1) { @@ -1758,18 +1694,26 @@ void GVOHub::post_string(const std::string& content,const socklen_t& sock) const int length = content.length(); // Set prefix - std::string prefix = "HTTP/1.1 200 OK\n" - "Connection: close\n" + std::string prefix = "POST /"+m_hub_path+" HTTP/1.1\n" "Content-Type: text/xml\n" + "User-Agent: GammaLib\n" + "Host: "+m_hub_host+":"+m_hub_port+"\n" + "Connection: close\n" "Content-Length: "+gammalib::str(length)+"\n\n"; // Build post string std::string post = prefix + content; + // Dump message to post + #if defined(G_CONSOLE_DUMP) + std::cout << "\nGVOHub::post_string posts the following message" << std::endl; + std::cout << post << std::endl; + #endif + // Send content to socket bool done = false; do { - int length = post.length(); + int length = post.length() + 1; // +1 for terminating 0 int sent_length = send(sock, post.c_str(), length, 0); if (sent_length < length) { post = post.substr(sent_length, std::string::npos); @@ -1787,38 +1731,116 @@ void GVOHub::post_string(const std::string& content,const socklen_t& sock) const /***********************************************************************//** - * @brief Post string content to client for callback - * - * @param[in] content String content to post + * @brief Send notification to client * - * Posts the content of a string to the client for a callback. + * @param[in] url URL. + * @param[in] notification Notification. * - * The method does nothing if no callback socket is open. + * Send a @p notification to a @p url. ***************************************************************************/ -void GVOHub::post_string_callback(const std::string& content) const +void GVOHub::notify(const std::string& url, + const std::string& notification) const { - // Continue only if Hub connection has been established - if (m_cback_socket != -1) { + // Initalise socket + int socket = -1; + + // Extract host, port and path from URL + std::string host = "127.0.0.1"; + std::string port = "2525"; + std::string path = "xmlrpc"; + if (url.compare(0, 7, "http://") == 0) { + size_t length; + size_t start = 7; + size_t stop = url.find(":", start); + size_t end = std::string::npos; + if (stop != std::string::npos) { + length = stop - start; + } + else { + length = std::string::npos; + } + host = url.substr(start, length); + if (stop != std::string::npos) { + stop++; + end = url.find("/", stop); + if (end != std::string::npos) { + length = end - stop; + } + else { + length = std::string::npos; + } + port = url.substr(stop, length); + } + if (end != std::string::npos) { + end++; + length = url.length() - end; + path = url.substr(end, length); + } + } - // Determine content length - int length = content.length(); + // Set hints + struct addrinfo hints; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + // Get server information + struct addrinfo* servinfo; + if (getaddrinfo(host.c_str(), port.c_str(), &hints, &servinfo) == 0) { + + // Loop through all the results and connect to the first we can + for (struct addrinfo* ptr = servinfo; ptr != NULL; ptr = ptr->ai_next) { + + // Create socket + socket = ::socket(ptr->ai_family, + ptr->ai_socktype, + ptr->ai_protocol); + + // Connect to socket if socket is valid + if (socket != -1) { + if (::connect(socket, + ptr->ai_addr, + ptr->ai_addrlen) == -1) { + close(socket); + socket = -1; + } + else { + // Socket connection successful, break now + break; + } + } + + } // endfor: looped through all results + + } // endif: server information was valid + + // Continue only if socket is valid + if (socket != -1) { + + // Determine notification length + int length = notification.length(); // Set prefix - std::string prefix = "POST /xmlrpc HTTP/1.1\n" - "Connection: keep-alive\n" + std::string prefix = "POST /"+path+" HTTP/1.0\n" + "Connection: close\n" "User-Agent: GammaLib\n" - "Host: localhost:"+gammalib::str(m_cback_socket)+"\n" "Content-Type: text/xml\n" "Content-Length: "+gammalib::str(length)+"\n\n"; // Build post string - std::string post = prefix + content; + std::string post = prefix + notification; + + // Dump message to post + #if defined(G_CONSOLE_DUMP) + std::cout << "\nGVOHub::notify posts the following message" << std::endl; + std::cout << post << std::endl; + #endif // Send content to socket bool done = false; do { - int length = post.length(); - int sent_length = send(m_cback_socket, post.c_str(), length, 0); + int length = post.length() + 1; // +1 for terminating 0 + int sent_length = send(socket, post.c_str(), length, 0); if (sent_length < length) { post = post.substr(sent_length, std::string::npos); } @@ -1827,20 +1849,29 @@ void GVOHub::post_string_callback(const std::string& content) const } } while (!done); + /* + // Declare response + std::string response = ""; + // Read buffer until it is empty char buffer[1001]; - int timeout = 2000; // Initial timeout is 2 sec + int timeout = 1000; // Initial timeout is 1 sec int n = 0; do { - n = gammalib::recv(m_cback_socket, buffer, 1000, 0, timeout); + n = gammalib::recv(socket, buffer, 1000, 0, timeout); if (n > 0) { buffer[n+1] = '\0'; + response.append(std::string(buffer)); } timeout = 10; // The timeout now is 0.01 sec } while (n > 0); + */ + + // Close socket + close(socket); + + } - } // endif: Hub connection had been established - // Return return; } -- libgit2 0.21.4