Commit b21f1d1da09466c10851a9cc395fdca0b00f5836

Authored by Jürgen Knödlseder
1 parent 4f190b42

Use new internal structure to store information.

include/GVOHub.hpp
@@ -28,15 +28,11 @@ @@ -28,15 +28,11 @@
28 #define GVOHUB_HPP 28 #define GVOHUB_HPP
29 29
30 /* __ Definitions ________________________________________________________ */ 30 /* __ Definitions ________________________________________________________ */
31 -#define GVOHUB_NB_CLIENTS 5  
32 -#define GVOHUB_NB_METHODS 128  
33 -#define GVO_HUB_testing 1  
34 31
35 /* __ Includes ___________________________________________________________ */ 32 /* __ Includes ___________________________________________________________ */
36 #include <string> 33 #include <string>
37 -#include <list> 34 +#include <vector>
38 #include <sys/socket.h> 35 #include <sys/socket.h>
39 -#include <semaphore.h>  
40 #include "GBase.hpp" 36 #include "GBase.hpp"
41 #include "GXml.hpp" 37 #include "GXml.hpp"
42 #include "GXmlNode.hpp" 38 #include "GXmlNode.hpp"
@@ -71,82 +67,78 @@ public: @@ -71,82 +67,78 @@ public:
71 67
72 protected: 68 protected:
73 // Protected methods 69 // Protected methods
74 - void init_members(void);  
75 - void copy_members(const GVOHub& client);  
76 - void free_members(void);  
77 - void start_hub(void);  
78 - void handle_request(const socklen_t& sock);  
79 - void request_ping(const socklen_t& sock);  
80 - void request_register(const GXml& xml,  
81 - const socklen_t& sock);  
82 - void request_unregister(const GXml& xml, 70 + void init_members(void);
  71 + void copy_members(const GVOHub& client);
  72 + void free_members(void);
  73 + void start_hub(void);
  74 + void handle_request(const socklen_t& sock);
  75 + void request_ping(const socklen_t& sock);
  76 + void request_register(const GXml& xml,
83 const socklen_t& sock); 77 const socklen_t& sock);
84 - void request_declare_metadata(const GXml& xml,  
85 - const socklen_t& sock);  
86 - void request_declare_subscriptions(const GXml& xml,  
87 - const socklen_t& sock);  
88 - void request_set_xml_rpc_callback(const GXml& xml,  
89 - const socklen_t& sock);  
90 - void request_get_subscriptions(const GXml& xml,  
91 - const socklen_t& sock);  
92 - void request_get_registered_clients(const GXml& xml,  
93 - const socklen_t& sock);  
94 - void request_get_subscribed_clients(const GXml& xml,  
95 - const socklen_t& sock);  
96 - void request_get_metadata(const GXml& xml, 78 + void request_unregister(const GXml& xml,
97 const socklen_t& sock); 79 const socklen_t& sock);
98 - void request_shutdown(const socklen_t& sock);  
99 - std::string get_client_key(const GXml& xml) const;  
100 - int get_client_index(const GXml& xml) const;  
101 - std::string get_response_value(const GXml& xml,  
102 - const std::string& name) const;  
103 - void get_name_value_pair(const GXmlNode* node,  
104 - std::string& name,  
105 - std::string& value) const;  
106 - std::list<std::string> get_registrations(const GXml& xml) const;  
107 - std::string get_callback_port(const GXml& xml) const;  
108 - std::string get_hub_lockfile(void) const;  
109 - void activate_callbacks(std::string method, char cl_id[31]); 80 + void request_declare_metadata(const GXml& xml,
  81 + const socklen_t& sock);
  82 + void request_declare_subscriptions(const GXml& xml,
  83 + const socklen_t& sock);
  84 + void request_set_xml_rpc_callback(const GXml& xml,
  85 + const socklen_t& sock);
  86 + void request_get_subscriptions(const GXml& xml,
  87 + const socklen_t& sock);
  88 + void request_get_registered_clients(const GXml& xml,
  89 + const socklen_t& sock);
  90 + void request_get_subscribed_clients(const GXml& xml,
  91 + const socklen_t& sock);
  92 + void request_get_metadata(const GXml& xml,
  93 + const socklen_t& sock);
  94 + void request_shutdown(const socklen_t& sock);
  95 + std::string get_client_key(const GXml& xml) const;
  96 + int get_client_index(const GXml& xml) const;
  97 + std::string get_response_value(const GXml& xml,
  98 + const std::string& name) const;
  99 + void get_name_value_pair(const GXmlNode* node,
  100 + std::string& name,
  101 + std::string& value) const;
  102 + std::vector<std::string> get_subscriptions(const GXml& xml) const;
  103 + std::string get_callback_url(const GXml& xml) const;
  104 + std::string get_hub_lockfile(void) const;
  105 + void send_notifications(const std::string& method,
  106 + const std::string& client);
110 107
111 // Low-level methods 108 // Low-level methods
112 void create_samp_file(void) const; 109 void create_samp_file(void) const;
  110 + void post_samp_ok(const socklen_t& sock) const;
113 void post_string(const std::string& content, const socklen_t& sock) const; 111 void post_string(const std::string& content, const socklen_t& sock) const;
114 - void post_string_callback(const std::string& content) const; 112 + void notify(const std::string& url, const std::string& notification) const;
115 std::string random_string(const size_t& length) const; 113 std::string random_string(const size_t& length) const;
116 114
117 - // Protected structures  
118 - typedef struct {  
119 - char private_key[16];  
120 - char name[32];  
121 - char reference[32];  
122 - char description[256];  
123 - char icon[32];  
124 - char documentation[32];  
125 - char affiliation[32];  
126 - char author_name[32];  
127 - char email[32];  
128 - char homepage[32];  
129 - char port[32];  
130 - char registered_methods[GVOHUB_NB_METHODS][GVOHUB_NB_METHODS]; //128 methods of 128 cars max.  
131 - } connected_shm;  
132 - typedef struct {  
133 - int registered;  
134 - sem_t lock;  
135 - connected_shm metadata[GVOHUB_NB_CLIENTS];  
136 - } clients; 115 + // Protected structure
  116 + struct client {
  117 + std::string name;
  118 + std::string private_key;
  119 + std::string reference;
  120 + std::string description;
  121 + std::string icon;
  122 + std::string documentation;
  123 + std::string affiliation;
  124 + std::string author_name;
  125 + std::string email;
  126 + std::string homepage;
  127 + std::string url;
  128 + std::vector<std::string> subscriptions;
  129 + };
137 130
138 // Protected members 131 // Protected members
139 - std::string m_secret; //!< Secret Hub key  
140 - std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub  
141 - std::string m_hub_host; //!< Hub host (extracted from XML-RPC endpoint)  
142 - std::string m_hub_port; //!< Hub port (extracted from XML-RPC endpoint)  
143 - std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub  
144 - std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others  
145 - socklen_t m_socket; //!< Hub socket  
146 - int m_cback_socket; //!< Hub socket to callback clients  
147 - clients* m_clients; //!< Structure of registered clients  
148 - void* m_shmem; //!< Pointer to shared memory address  
149 - int m_shmem_handler; //!< Handler to shared memory 132 + std::string m_secret; //!< Secret Hub key
  133 + std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub
  134 + std::string m_hub_host; //!< Hub host
  135 + std::string m_hub_port; //!< Hub port
  136 + std::string m_hub_path; //!< Hub path
  137 + std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub
  138 + std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others
  139 + socklen_t m_socket; //!< Hub socket
  140 + bool m_shutdown; //!< Shutdown request
  141 + std::vector<client> m_clients; //!< Clients
150 }; 142 };
151 143
152 144
src/vo/GVOClient.cpp
@@ -867,9 +867,6 @@ void GVOClient::connect_to_hub(void) const @@ -867,9 +867,6 @@ void GVOClient::connect_to_hub(void) const
867 break; 867 break;
868 } 868 }
869 } 869 }
870 - else {  
871 - break;  
872 - }  
873 870
874 } // endfor: looped through all results 871 } // endfor: looped through all results
875 872
@@ -917,7 +914,7 @@ void GVOClient::post_string(const std::string&amp; content) const @@ -917,7 +914,7 @@ void GVOClient::post_string(const std::string&amp; content) const
917 bool done = false; 914 bool done = false;
918 do { 915 do {
919 int length = post.length() + 1; // +1 for terminating 0 916 int length = post.length() + 1; // +1 for terminating 0
920 - int sent_length = send(m_socket, post.c_str(), length+1, 0); 917 + int sent_length = send(m_socket, post.c_str(), length, 0);
921 if (sent_length < length) { 918 if (sent_length < length) {
922 post = post.substr(sent_length, std::string::npos); 919 post = post.substr(sent_length, std::string::npos);
923 } 920 }
src/vo/GVOHub.cpp
@@ -57,10 +57,9 @@ @@ -57,10 +57,9 @@
57 /* __ Coding definitions _________________________________________________ */ 57 /* __ Coding definitions _________________________________________________ */
58 #define G_KEY 12345 58 #define G_KEY 12345
59 //#define G_USE_FORK 59 //#define G_USE_FORK
60 -//#define G_USE_SHMEM  
61 60
62 /* __ Debug definitions __________________________________________________ */ 61 /* __ Debug definitions __________________________________________________ */
63 -//#define G_CONSOLE_DUMP 62 +#define G_CONSOLE_DUMP
64 63
65 64
66 /*========================================================================== 65 /*==========================================================================
@@ -217,8 +216,9 @@ std::string GVOHub::print(const GChatter&amp; chatter) const @@ -217,8 +216,9 @@ std::string GVOHub::print(const GChatter&amp; chatter) const
217 result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id); 216 result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id);
218 result.append("\n"+gammalib::parformat("Hub key")+m_secret); 217 result.append("\n"+gammalib::parformat("Hub key")+m_secret);
219 result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url); 218 result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url);
220 - result.append("\n"+gammalib::parformat("Hub host (port)"));  
221 - result.append(m_hub_host+" ("+m_hub_port+")"); 219 + result.append("\n"+gammalib::parformat("Hub host")+m_hub_host);
  220 + result.append("\n"+gammalib::parformat("Hub port")+m_hub_port);
  221 + result.append("\n"+gammalib::parformat("Hub path")+m_hub_path);
222 result.append("\n"+gammalib::parformat("SAMP protocol version")); 222 result.append("\n"+gammalib::parformat("SAMP protocol version"));
223 result.append(m_version); 223 result.append(m_version);
224 224
@@ -243,50 +243,14 @@ void GVOHub::init_members(void) @@ -243,50 +243,14 @@ void GVOHub::init_members(void)
243 // Initialise members 243 // Initialise members
244 m_secret = random_string(15); 244 m_secret = random_string(15);
245 m_hub_host = "127.0.0.1"; 245 m_hub_host = "127.0.0.1";
246 - m_hub_port = "2525";  
247 - m_hub_url = "http://"+m_hub_host+":"+m_hub_port+"/xmlrpc"; 246 + m_hub_port = "2526";
  247 + m_hub_path = "xmlrpc";
  248 + m_hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path;
248 m_version = "1.3"; 249 m_version = "1.3";
249 m_hub_id = "gammalib_hub"; 250 m_hub_id = "gammalib_hub";
250 m_socket = -1; // Signals no socket 251 m_socket = -1; // Signals no socket
251 - m_cback_socket = -1; // Signals no socket  
252 - m_clients = NULL;  
253 - m_shmem = NULL;  
254 - m_shmem_handler = 0;  
255 -  
256 - #if defined(G_USE_SHMEM)  
257 - // Get shared memory for handling of clients  
258 - if ((m_shmem_handler = shmget(G_KEY, sizeof(clients), 0666 | IPC_CREAT)) < 0) {  
259 - std::string msg = "Could not open shared memory.";  
260 - throw GException::invalid_value(G_INIT_MEMBERS, msg);  
261 - }  
262 -  
263 - // Get pointer on shared memory  
264 - if ((m_shmem = shmat(m_shmem_handler, NULL, 0)) == (void*) -1) {  
265 - std::string msg = "Could not attach shared memory.";  
266 - throw GException::invalid_value(G_INIT_MEMBERS, msg);  
267 - }  
268 -  
269 - // Get pointer  
270 - m_clients = static_cast<clients*>(m_shmem);  
271 - #else  
272 - m_clients = new clients;  
273 - #endif  
274 -  
275 - // Initialise shared memory  
276 - m_clients->registered = 0;  
277 - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) {  
278 - strcpy(m_clients->metadata[i].reference, "NoRef");  
279 - strcpy(m_clients->metadata[i].private_key, "Unknown");  
280 - strcpy(m_clients->metadata[i].name, "Unknown");  
281 - strcpy(m_clients->metadata[i].icon, "Unknown");  
282 - strcpy(m_clients->metadata[i].documentation,"Unknown");  
283 - strcpy(m_clients->metadata[i].affiliation, "Unknown");  
284 - strcpy(m_clients->metadata[i].author_name, "Unknown");  
285 - strcpy(m_clients->metadata[i].email, "Unknown");  
286 - strcpy(m_clients->metadata[i].homepage, "Unknown");  
287 - strcpy(m_clients->metadata[i].port, "Unknown");  
288 - strcpy(m_clients->metadata[i].description, "Unknown");  
289 - } 252 + m_clients.clear();
  253 + m_shutdown = false;
290 254
291 // Return 255 // Return
292 return; 256 return;
@@ -301,16 +265,16 @@ void GVOHub::init_members(void) @@ -301,16 +265,16 @@ void GVOHub::init_members(void)
301 void GVOHub::copy_members(const GVOHub& hub) 265 void GVOHub::copy_members(const GVOHub& hub)
302 { 266 {
303 // Copy members 267 // Copy members
304 - m_secret = hub.m_secret;  
305 - m_hub_url = hub.m_hub_url;  
306 - m_hub_host = hub.m_hub_host;  
307 - m_hub_port = hub.m_hub_port;  
308 - m_version = hub.m_version;  
309 - m_hub_id = hub.m_hub_id;  
310 - m_socket = hub.m_socket;  
311 - m_cback_socket = hub.m_cback_socket;  
312 -  
313 - //TODO: What to do with shared memory? Copy over all data? 268 + m_secret = hub.m_secret;
  269 + m_hub_url = hub.m_hub_url;
  270 + m_hub_host = hub.m_hub_host;
  271 + m_hub_port = hub.m_hub_port;
  272 + m_hub_path = hub.m_hub_path;
  273 + m_version = hub.m_version;
  274 + m_hub_id = hub.m_hub_id;
  275 + m_socket = hub.m_socket;
  276 + m_clients = hub.m_clients;
  277 + m_shutdown = hub.m_shutdown;
314 278
315 // Return 279 // Return
316 return; 280 return;
@@ -327,22 +291,11 @@ void GVOHub::free_members(void) @@ -327,22 +291,11 @@ void GVOHub::free_members(void)
327 close(m_socket); 291 close(m_socket);
328 m_socket = -1; 292 m_socket = -1;
329 } 293 }
330 - if (m_cback_socket != -1) {  
331 - close(m_cback_socket);  
332 - m_cback_socket = -1;  
333 - }  
334 294
335 // Remove lockfile 295 // Remove lockfile
336 std::string lockurl = get_hub_lockfile(); 296 std::string lockurl = get_hub_lockfile();
337 std::remove(lockurl.c_str()); 297 std::remove(lockurl.c_str());
338 298
339 - // Release shared memory  
340 - #if defined(G_USE_SHMEM)  
341 - struct shmid_ds *buf;  
342 - shmdt(m_shmem);  
343 - shmctl(m_shmem_handler, IPC_RMID, buf);  
344 - #endif  
345 -  
346 // Return 299 // Return
347 return; 300 return;
348 } 301 }
@@ -358,9 +311,6 @@ void GVOHub::free_members(void) @@ -358,9 +311,6 @@ void GVOHub::free_members(void)
358 ***************************************************************************/ 311 ***************************************************************************/
359 void GVOHub::start_hub(void) 312 void GVOHub::start_hub(void)
360 { 313 {
361 - // Set maximum number of clients  
362 - int max_clients = 10;  
363 -  
364 // Prepare TCP/IP structure 314 // Prepare TCP/IP structure
365 struct sockaddr_in serv_addr; 315 struct sockaddr_in serv_addr;
366 std::memset(&serv_addr, 0, sizeof(serv_addr)); 316 std::memset(&serv_addr, 0, sizeof(serv_addr));
@@ -368,12 +318,6 @@ void GVOHub::start_hub(void) @@ -368,12 +318,6 @@ void GVOHub::start_hub(void)
368 serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str()); 318 serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str());
369 serv_addr.sin_port = htons(gammalib::toint(m_hub_port)); 319 serv_addr.sin_port = htons(gammalib::toint(m_hub_port));
370 320
371 - // Initialise all client_socket[] to 0 so not checked  
372 - socklen_t client_socket[max_clients];  
373 - for (int i = 0; i < max_clients; ++i) {  
374 - client_socket[i] = 0;  
375 - }  
376 -  
377 // Create Hub socket 321 // Create Hub socket
378 m_socket = socket(AF_INET, SOCK_STREAM, 0); 322 m_socket = socket(AF_INET, SOCK_STREAM, 0);
379 323
@@ -463,7 +407,7 @@ void GVOHub::start_hub(void) @@ -463,7 +407,7 @@ void GVOHub::start_hub(void)
463 407
464 // If we have received a shutdown request then exit the event 408 // If we have received a shutdown request then exit the event
465 // loop 409 // loop
466 - if (m_clients->registered == -1) { 410 + if (o_clients->registered == -1) {
467 break; 411 break;
468 } 412 }
469 413
@@ -477,7 +421,7 @@ void GVOHub::start_hub(void) @@ -477,7 +421,7 @@ void GVOHub::start_hub(void)
477 421
478 // If we have received a shutdown request then exit the event 422 // If we have received a shutdown request then exit the event
479 // loop 423 // loop
480 - if (m_clients->registered == -1) { 424 + if (m_shutdown) {
481 break; 425 break;
482 } 426 }
483 #endif 427 #endif
@@ -559,16 +503,16 @@ void GVOHub::handle_request(const socklen_t&amp; sock) @@ -559,16 +503,16 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
559 request_register(xml, sock); 503 request_register(xml, sock);
560 } 504 }
561 else if (method_called.compare("samp.hub.unregister") == 0) { 505 else if (method_called.compare("samp.hub.unregister") == 0) {
562 - request_unregister(xml,sock); 506 + request_unregister(xml, sock);
563 } 507 }
564 else if (method_called.compare("samp.hub.declareMetadata") == 0) { 508 else if (method_called.compare("samp.hub.declareMetadata") == 0) {
565 - request_declare_metadata(xml,sock); 509 + request_declare_metadata(xml, sock);
566 } 510 }
567 else if (method_called.compare("samp.hub.declareSubscriptions") == 0) { 511 else if (method_called.compare("samp.hub.declareSubscriptions") == 0) {
568 - request_declare_subscriptions(xml,sock); 512 + request_declare_subscriptions(xml, sock);
569 } 513 }
570 else if (method_called.compare("samp.hub.setXmlrpcCallback") == 0) { 514 else if (method_called.compare("samp.hub.setXmlrpcCallback") == 0) {
571 - request_set_xml_rpc_callback(xml,sock); 515 + request_set_xml_rpc_callback(xml, sock);
572 } 516 }
573 else if (method_called.compare("samp.hub.getSubscriptions") == 0) { 517 else if (method_called.compare("samp.hub.getSubscriptions") == 0) {
574 request_get_subscriptions(xml, sock); 518 request_get_subscriptions(xml, sock);
@@ -623,21 +567,23 @@ void GVOHub::request_ping(const socklen_t&amp; sock) @@ -623,21 +567,23 @@ void GVOHub::request_ping(const socklen_t&amp; sock)
623 std::cout << "GVOHub::request_ping" << std::endl; 567 std::cout << "GVOHub::request_ping" << std::endl;
624 #endif 568 #endif
625 569
626 - // Declare message  
627 - std::string msg = ""; 570 + // Declare response
  571 + std::string response = "";
628 572
629 // Set response 573 // Set response
630 - msg.append("<?xml version=\"1.0\"?>\n");  
631 - msg.append("<methodResponse>\n");  
632 - msg.append("<params>\n");  
633 - msg.append(" <param><value/></param>\n");  
634 - msg.append("</params>\n");  
635 - msg.append("</methodResponse>\n"); 574 + response.append("<?xml version='1.0' encoding='UTF-8'?>\n");
  575 + response.append("<methodResponse>\n");
  576 + response.append(" <params>\n");
  577 + response.append(" <param>\n");
  578 + response.append(" <value/>\n");
  579 + response.append(" </param>\n");
  580 + response.append(" </params>\n");
  581 + response.append("</methodResponse>\n");
636 582
637 // Post response 583 // Post response
638 - post_string(msg,sock); 584 + post_string(response, sock);
639 585
640 - //Return 586 + // Return
641 return; 587 return;
642 } 588 }
643 589
@@ -657,58 +603,56 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock) @@ -657,58 +603,56 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock)
657 std::cout << "GVOHub::request_register" << std::endl; 603 std::cout << "GVOHub::request_register" << std::endl;
658 #endif 604 #endif
659 605
660 - // Initialize values  
661 - char cl_id[31];  
662 - char selfid[124];  
663 - char privatekey[124];  
664 - std::string secret = random_string(15);  
665 - std::string translator = m_hub_url; 606 + // Create a new client
  607 + struct client voclient;
  608 + voclient.reference = "c"+gammalib::str(m_clients.size());
  609 + voclient.private_key = random_string(15);
666 610
667 - // Search for a new free slot  
668 - bool found = false;  
669 - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) {  
670 - if (strcmp(m_clients->metadata[i].reference, "NoRef") == 0) {  
671 - sprintf(cl_id, "c%d",i);  
672 - strcpy(m_clients->metadata[i].reference, cl_id);  
673 - sprintf(m_clients->metadata[i].private_key, "%s", secret.c_str());  
674 - found = true;  
675 - break;  
676 - } 611 + // Attached client
  612 + m_clients.push_back(voclient);
  613 + /*
  614 + for (int i = 0; i < m_clients.size(); ++i) {
  615 + std::cout << "Client i " << m_clients[i].reference << " key=" << m_clients[i].private_key << std::endl;
677 } 616 }
678 -  
679 - // Throw an exception if no free slot is available  
680 - if (!found) {  
681 - std::string msg = "No free slot found for client.";  
682 - throw GException::invalid_value(G_REGISTER_SERVICE, msg);  
683 - }  
684 -  
685 - // Set self ID and private key  
686 - sprintf(selfid, " <member><name>samp.self-id</name><value>%s</value></member>\n",cl_id);  
687 - sprintf(privatekey, " <member><name>samp.private-key</name><value>%s</value></member>\n",secret.c_str()); 617 + */
688 618
689 // Declare response 619 // Declare response
690 std::string msg = ""; 620 std::string msg = "";
691 - msg.append("<?xml version=\"1.0\" ?>\n"); 621 +
  622 + // Set response
  623 + msg.append("<?xml version='1.0' encoding='UTF-8'?>\n");
692 msg.append("<methodResponse>\n"); 624 msg.append("<methodResponse>\n");
693 msg.append("<params>\n"); 625 msg.append("<params>\n");
694 msg.append(" <param><value><struct>\n"); 626 msg.append(" <param><value><struct>\n");
695 - msg.append(" <member><name>samp.hub-id</name><value>" + m_hub_id + "</value></member>\n");  
696 - msg.append(selfid);  
697 - msg.append(privatekey);  
698 - msg.append(" <member><name>samp.status</name><value>samp.ok</value></member>\n");  
699 - msg.append(" <member><name>samp.url-translator</name><value>" + translator + "</value></member>\n"); 627 + msg.append(" <member>\n");
  628 + msg.append(" <name>samp.private-key</name>\n");
  629 + msg.append(" <value>"+voclient.private_key+"</value>\n");
  630 + msg.append(" </member>\n");
  631 + msg.append(" <member>\n");
  632 + msg.append(" <name>samp.hub-id</name>\n");
  633 + msg.append(" <value>"+m_hub_id+"</value>\n");
  634 + msg.append(" </member>\n");
  635 + msg.append(" <member>\n");
  636 + msg.append(" <name>samp.self-id</name>\n");
  637 + msg.append(" <value>"+voclient.reference+"</value>\n");
  638 + msg.append(" </member>\n");
  639 + msg.append(" <member>\n");
  640 + msg.append(" <name>samp.status</name>\n");
  641 + msg.append(" <value>samp.ok</value>\n");
  642 + msg.append(" </member>\n");
  643 + msg.append(" <member>\n");
  644 + msg.append(" <name>samp.url-translator</name>\n");
  645 + msg.append(" <value>"+m_hub_url+"</value>\n");
  646 + msg.append(" </member>\n");
700 msg.append(" </struct></value></param>\n"); 647 msg.append(" </struct></value></param>\n");
701 msg.append("</params>\n"); 648 msg.append("</params>\n");
702 msg.append("</methodResponse>\n"); 649 msg.append("</methodResponse>\n");
703 650
704 // Post response 651 // Post response
705 - post_string(msg,sock);  
706 -  
707 - // Activate callbacks  
708 - activate_callbacks("samp.hub.event.register", cl_id); 652 + post_string(msg, sock);
709 653
710 - // Increment number of registered clients  
711 - //m_clients->registered++; 654 + // Send notifications
  655 + send_notifications("samp.hub.event.register", voclient.reference);
712 656
713 //Return 657 //Return
714 return; 658 return;
@@ -750,22 +694,21 @@ void GVOHub::request_unregister(const GXml&amp; xml, const socklen_t&amp; sock) @@ -750,22 +694,21 @@ void GVOHub::request_unregister(const GXml&amp; xml, const socklen_t&amp; sock)
750 // Post response 694 // Post response
751 post_string(msg, sock); 695 post_string(msg, sock);
752 696
753 - // Activate callbacks  
754 - activate_callbacks("samp.hub.event.unregister",  
755 - m_clients->metadata[i].reference);  
756 -  
757 - // Reset client entry  
758 - strcpy(m_clients->metadata[i].reference, "NoRef");  
759 - sprintf(m_clients->metadata[i].name, "Unknown");  
760 - sprintf(m_clients->metadata[i].description, "Unknown");  
761 - sprintf(m_clients->metadata[i].icon, "Unknown");  
762 - sprintf(m_clients->metadata[i].documentation, "Unknown");  
763 - sprintf(m_clients->metadata[i].affiliation, "Unknown");  
764 - sprintf(m_clients->metadata[i].email, "Unknown");  
765 - sprintf(m_clients->metadata[i].author_name, "Unknown");  
766 - sprintf(m_clients->metadata[i].homepage, "Unknown"); 697 + // Send notifications
  698 + send_notifications("samp.hub.event.unregister",
  699 + m_clients[i].reference);
  700 +
  701 + // Remove client
  702 + m_clients.erase(m_clients.begin()+i);
767 703
768 } // endif: valid client found 704 } // endif: valid client found
  705 +
  706 + // Signal if the client was unknown
  707 + #if defined(G_CONSOLE_DUMP)
  708 + else {
  709 + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  710 + }
  711 + #endif
769 712
770 // Return 713 // Return
771 return; 714 return;
@@ -793,25 +736,15 @@ void GVOHub::request_declare_metadata(const GXml&amp; xml, const socklen_t&amp; sock) @@ -793,25 +736,15 @@ void GVOHub::request_declare_metadata(const GXml&amp; xml, const socklen_t&amp; sock)
793 // Continue only if index is valid 736 // Continue only if index is valid
794 if (i != -1) { 737 if (i != -1) {
795 738
796 - // Get metadata  
797 - std::string client_name = get_response_value(xml, "samp.name");  
798 - std::string client_description = get_response_value(xml, "samp.description.text");  
799 - std::string client_icon = get_response_value(xml, "samp.icon.url");  
800 - std::string client_doc = get_response_value(xml, "samp.documentation.url");  
801 - std::string client_affi = get_response_value(xml, "author.affiliation");  
802 - std::string client_mail = get_response_value(xml, "author.email");  
803 - std::string client_authname = get_response_value(xml, "author.name");  
804 - std::string client_page = get_response_value(xml, "home.page");  
805 -  
806 // Store metadata 739 // Store metadata
807 - sprintf(m_clients->metadata[i].name, "%s", client_name.c_str());  
808 - sprintf(m_clients->metadata[i].description, "%s", client_description.c_str());  
809 - sprintf(m_clients->metadata[i].icon, "%s", client_icon.c_str());  
810 - sprintf(m_clients->metadata[i].documentation, "%s", client_doc.c_str());  
811 - sprintf(m_clients->metadata[i].affiliation, "%s", client_affi.c_str());  
812 - sprintf(m_clients->metadata[i].email, "%s", client_mail.c_str());  
813 - sprintf(m_clients->metadata[i].author_name, "%s", client_authname.c_str());  
814 - sprintf(m_clients->metadata[i].homepage, "%s", client_page.c_str()); 740 + m_clients[i].name = get_response_value(xml, "samp.name");;
  741 + m_clients[i].description = get_response_value(xml, "samp.description.text");
  742 + m_clients[i].icon = get_response_value(xml, "samp.icon.url");
  743 + m_clients[i].documentation = get_response_value(xml, "samp.documentation.url");
  744 + m_clients[i].affiliation = get_response_value(xml, "author.affiliation");
  745 + m_clients[i].email = get_response_value(xml, "author.email");
  746 + m_clients[i].author_name = get_response_value(xml, "author.name");
  747 + m_clients[i].homepage = get_response_value(xml, "home.page");
815 748
816 // Declare message 749 // Declare message
817 std::string msg = ""; 750 std::string msg = "";
@@ -826,8 +759,8 @@ void GVOHub::request_declare_metadata(const GXml&amp; xml, const socklen_t&amp; sock) @@ -826,8 +759,8 @@ void GVOHub::request_declare_metadata(const GXml&amp; xml, const socklen_t&amp; sock)
826 // Post response 759 // Post response
827 post_string(msg,sock); 760 post_string(msg,sock);
828 761
829 - // Activate callbacks  
830 - activate_callbacks("samp.hub.event.metadata", m_clients->metadata[i].reference); 762 + // Send notifications
  763 + send_notifications("samp.hub.event.metadata", m_clients[i].reference);
831 764
832 } // endif: client found 765 } // endif: client found
833 766
@@ -864,32 +797,25 @@ void GVOHub::request_declare_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock @@ -864,32 +797,25 @@ void GVOHub::request_declare_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock
864 // Continue only if index is valid 797 // Continue only if index is valid
865 if (i != -1) { 798 if (i != -1) {
866 799
867 - // Do stuff  
868 - int j;  
869 - std::list<std::string>::iterator p;  
870 - std::ofstream myfile;  
871 - std::string tempo;  
872 - std::list<std::string> client_subscriptions = get_registrations(xml);  
873 - for (j = 0, p=client_subscriptions.begin(); j<client_subscriptions.size()-1; j++,p++ ) {  
874 - tempo = *p;  
875 - sprintf(m_clients->metadata[i].registered_methods[j], "%s", tempo.c_str());  
876 - } 800 + // Get subscriptions
  801 + std::vector<std::string> subscriptions = get_subscriptions(xml);
877 802
878 - // Declare response  
879 - std::string msg = "";  
880 - msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");  
881 - msg.append("<methodResponse>\n");  
882 - msg.append("<params>\n");  
883 - msg.append(" <param><value><struct>\n");  
884 - msg.append(" <member><name>samp.status</name><value>samp.ok</value></member>\n");  
885 - msg.append(" </struct></value></param>\n");  
886 - msg.append("</params>\n");  
887 - msg.append("</methodResponse>\n"); 803 + // Store subscriptions
  804 + for (int k = 0; k < subscriptions.size(); ++k) {
  805 + m_clients[i].subscriptions.push_back(subscriptions[k]);
  806 + }
888 807
889 - // Post string  
890 - post_string(msg,sock); 808 + // Post SAMP ok
  809 + post_samp_ok(sock);
891 810
892 } // endif: valid client found 811 } // endif: valid client found
  812 +
  813 + // Signal if the client was unknown
  814 + #if defined(G_CONSOLE_DUMP)
  815 + else {
  816 + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  817 + }
  818 + #endif
893 819
894 //Return 820 //Return
895 return; 821 return;
@@ -904,11 +830,12 @@ void GVOHub::request_declare_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock @@ -904,11 +830,12 @@ void GVOHub::request_declare_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock
904 * 830 *
905 * Handles all incoming XML-RPC callback setting requests. 831 * Handles all incoming XML-RPC callback setting requests.
906 ***************************************************************************/ 832 ***************************************************************************/
907 -void GVOHub::request_set_xml_rpc_callback(const GXml& xml,const socklen_t& sock) 833 +void GVOHub::request_set_xml_rpc_callback(const GXml& xml,
  834 + const socklen_t& sock)
908 { 835 {
909 // Header 836 // Header
910 #if defined(G_CONSOLE_DUMP) 837 #if defined(G_CONSOLE_DUMP)
911 - std::cout << "GVOHub::request_declare_subscriptions" << std::endl; 838 + std::cout << "GVOHub::request_set_xml_rpc_callback" << std::endl;
912 #endif 839 #endif
913 840
914 // Get client index 841 // Get client index
@@ -917,31 +844,24 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml,const socklen_t&amp; sock) @@ -917,31 +844,24 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml,const socklen_t&amp; sock)
917 // Continue only if index is valid 844 // Continue only if index is valid
918 if (i != -1) { 845 if (i != -1) {
919 846
920 - // Get callback port  
921 - std::string client_port = get_callback_port(xml); 847 + // Get callback URL
  848 + std::string client_url = get_callback_url(xml);
922 849
923 - // Set callback port value  
924 - sprintf(m_clients->metadata[i].port, "%s", client_port.c_str()); 850 + // Set callback URL
  851 + m_clients[i].url = get_callback_url(xml);
925 852
926 - // Declare message  
927 - std::string msg = "";  
928 -  
929 - // The hub response to rpc callback declaration has no useful  
930 - // content and can be discarded by the client.  
931 - msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");  
932 - msg.append("<methodResponse>\n");  
933 - msg.append("<params>\n");  
934 - msg.append(" <param><value><struct>\n");  
935 - msg.append(" <member><name>samp.status</name><value>samp.ok</value></member>\n");  
936 - msg.append(" </struct></value></param>\n");  
937 - msg.append("</params>\n");  
938 - msg.append("</methodResponse>\n");  
939 -  
940 - // Post message  
941 - post_string(msg, sock); 853 + // Post SAMP ok
  854 + post_samp_ok(sock);
942 855
943 } // endif: client found 856 } // endif: client found
944 857
  858 + // Signal if the client was unknown
  859 + #if defined(G_CONSOLE_DUMP)
  860 + else {
  861 + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  862 + }
  863 + #endif
  864 +
945 // Return 865 // Return
946 return; 866 return;
947 } 867 }
@@ -955,7 +875,7 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml,const socklen_t&amp; sock) @@ -955,7 +875,7 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml,const socklen_t&amp; sock)
955 * 875 *
956 * Handles all incoming subscriptions getting requests. 876 * Handles all incoming subscriptions getting requests.
957 ***************************************************************************/ 877 ***************************************************************************/
958 -void GVOHub::request_get_subscriptions(const GXml& xml,const socklen_t& sock) 878 +void GVOHub::request_get_subscriptions(const GXml& xml, const socklen_t& sock)
959 { 879 {
960 // Header 880 // Header
961 #if defined(G_CONSOLE_DUMP) 881 #if defined(G_CONSOLE_DUMP)
@@ -978,18 +898,14 @@ void GVOHub::request_get_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock) @@ -978,18 +898,14 @@ void GVOHub::request_get_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock)
978 msg.append(" <param><value><struct>\n"); 898 msg.append(" <param><value><struct>\n");
979 899
980 // Append all subscriptions 900 // Append all subscriptions
981 - char tempo[128];  
982 - for (int j = 0; j < GVOHUB_NB_METHODS; ++j) {  
983 - strcpy(tempo, m_clients->metadata[i].registered_methods[j]);  
984 - if (strcmp("", tempo) != 0) {  
985 - msg.append(" <member>\n");  
986 - msg.append(" <name>");  
987 - msg.append(tempo);  
988 - msg.append("</name>\n");  
989 - msg.append(" <value></value>\n)");  
990 - msg.append(" </member>\n");  
991 - }  
992 - } 901 + for (int k = 0; k < m_clients[i].subscriptions.size(); ++k) {
  902 + msg.append(" <member>\n");
  903 + msg.append(" <name>");
  904 + msg.append(m_clients[i].subscriptions[k]);
  905 + msg.append("</name>\n");
  906 + msg.append(" <value></value>\n)");
  907 + msg.append(" </member>\n");
  908 + }
993 909
994 // Finish response 910 // Finish response
995 msg.append(" </struct></value></param>\n"); 911 msg.append(" </struct></value></param>\n");
@@ -997,9 +913,16 @@ void GVOHub::request_get_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock) @@ -997,9 +913,16 @@ void GVOHub::request_get_subscriptions(const GXml&amp; xml,const socklen_t&amp; sock)
997 msg.append("</methodResponse>\n"); 913 msg.append("</methodResponse>\n");
998 914
999 // Post response 915 // Post response
1000 - post_string(msg,sock); 916 + post_string(msg, sock);
1001 917
1002 } // endif: client index was valid 918 } // endif: client index was valid
  919 +
  920 + // Signal if the client was unknown
  921 + #if defined(G_CONSOLE_DUMP)
  922 + else {
  923 + std::cout << " *** ERROR: Unable to find client " << get_client_key(xml) << std::endl;
  924 + }
  925 + #endif
1003 926
1004 // Return 927 // Return
1005 return; 928 return;
@@ -1035,13 +958,11 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so @@ -1035,13 +958,11 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so
1035 msg.append(" <value>gammalib_hub</value>\n"); 958 msg.append(" <value>gammalib_hub</value>\n");
1036 959
1037 // Loop over all clients. Do not send back current client's registration 960 // Loop over all clients. Do not send back current client's registration
1038 - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) {  
1039 - if (strcmp(m_clients->metadata[i].reference,"NoRef") != 0) {  
1040 - if (strcmp(m_clients->metadata[i].private_key, key.c_str()) != 0) {  
1041 - msg.append(" <value>");  
1042 - msg.append(m_clients->metadata[i].reference);  
1043 - msg.append("</value>\n");  
1044 - } 961 + for (int i = 0; i < m_clients.size(); ++i) {
  962 + if (m_clients[i].private_key != key) {
  963 + msg.append(" <value>");
  964 + msg.append(m_clients[i].reference);
  965 + msg.append("</value>\n");
1045 } 966 }
1046 } 967 }
1047 968
@@ -1053,7 +974,7 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so @@ -1053,7 +974,7 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so
1053 // Post response 974 // Post response
1054 post_string(msg, sock); 975 post_string(msg, sock);
1055 976
1056 - //Return 977 + // Return
1057 return; 978 return;
1058 979
1059 } 980 }
@@ -1107,7 +1028,7 @@ void GVOHub::request_get_subscribed_clients(const GXml&amp; xml, const socklen_t&amp; so @@ -1107,7 +1028,7 @@ void GVOHub::request_get_subscribed_clients(const GXml&amp; xml, const socklen_t&amp; so
1107 msg.append("</methodResponse>\n"); 1028 msg.append("</methodResponse>\n");
1108 1029
1109 // Post message 1030 // Post message
1110 - post_string(msg,sock); 1031 + post_string(msg, sock);
1111 1032
1112 // Return 1033 // Return
1113 return; 1034 return;
@@ -1168,28 +1089,28 @@ void GVOHub::request_get_metadata(const GXml&amp; xml,const socklen_t&amp; sock) @@ -1168,28 +1089,28 @@ void GVOHub::request_get_metadata(const GXml&amp; xml,const socklen_t&amp; sock)
1168 1089
1169 // Append response 1090 // Append response
1170 msg.append(" <member><name>samp.name</name><value>"); 1091 msg.append(" <member><name>samp.name</name><value>");
1171 - msg.append(m_clients->metadata[i].name); 1092 + msg.append(m_clients[i].name);
1172 msg.append("</value></member>\n"); 1093 msg.append("</value></member>\n");
1173 msg.append(" <member><name>samp.description.text</name><value>"); 1094 msg.append(" <member><name>samp.description.text</name><value>");
1174 - msg.append(m_clients->metadata[i].description); 1095 + msg.append(m_clients[i].description);
1175 msg.append("</value></member>\n"); 1096 msg.append("</value></member>\n");
1176 msg.append(" <member><name>samp.icon.url</name><value>"); 1097 msg.append(" <member><name>samp.icon.url</name><value>");
1177 - msg.append(m_clients->metadata[i].icon); 1098 + msg.append(m_clients[i].icon);
1178 msg.append("</value></member>\n"); 1099 msg.append("</value></member>\n");
1179 msg.append(" <member><name>samp.documentation.url</name><value>"); 1100 msg.append(" <member><name>samp.documentation.url</name><value>");
1180 - msg.append(m_clients->metadata[i].documentation); 1101 + msg.append(m_clients[i].documentation);
1181 msg.append("</value></member>\n"); 1102 msg.append("</value></member>\n");
1182 msg.append(" <member><name>author.affiliation</name><value>"); 1103 msg.append(" <member><name>author.affiliation</name><value>");
1183 - msg.append(m_clients->metadata[i].affiliation); 1104 + msg.append(m_clients[i].affiliation);
1184 msg.append("</value></member>\n"); 1105 msg.append("</value></member>\n");
1185 msg.append(" <member><name>author.email</name><value>"); 1106 msg.append(" <member><name>author.email</name><value>");
1186 - msg.append(m_clients->metadata[i].email); 1107 + msg.append(m_clients[i].email);
1187 msg.append("</value></member>\n"); 1108 msg.append("</value></member>\n");
1188 msg.append(" <member><name>author.name</name><value>"); 1109 msg.append(" <member><name>author.name</name><value>");
1189 - msg.append(m_clients->metadata[i].author_name); 1110 + msg.append(m_clients[i].author_name);
1190 msg.append("</value></member>\n"); 1111 msg.append("</value></member>\n");
1191 msg.append(" <member><name>home.page</name><value>"); 1112 msg.append(" <member><name>home.page</name><value>");
1192 - msg.append(m_clients->metadata[i].homepage); 1113 + msg.append(m_clients[i].homepage);
1193 msg.append("</value></member>\n"); 1114 msg.append("</value></member>\n");
1194 1115
1195 } // endif: index was valid 1116 } // endif: index was valid
@@ -1224,21 +1145,10 @@ void GVOHub::request_shutdown(const socklen_t&amp; sock) @@ -1224,21 +1145,10 @@ void GVOHub::request_shutdown(const socklen_t&amp; sock)
1224 #endif 1145 #endif
1225 1146
1226 // Set shutdown flag 1147 // Set shutdown flag
1227 - m_clients->registered = -1; 1148 + m_shutdown = true;
1228 1149
1229 - // Declare message  
1230 - std::string msg = "";  
1231 -  
1232 - // Set response  
1233 - msg.append("<?xml version=\"1.0\"?>\n");  
1234 - msg.append("<methodResponse>\n");  
1235 - msg.append("<params>\n");  
1236 - msg.append(" <param><value/></param>\n");  
1237 - msg.append("</params>\n");  
1238 - msg.append("</methodResponse>\n");  
1239 -  
1240 - // Post response  
1241 - post_string(msg,sock); 1150 + // Post SAMP ok
  1151 + post_samp_ok(sock);
1242 1152
1243 // Return 1153 // Return
1244 return; 1154 return;
@@ -1300,9 +1210,9 @@ int GVOHub::get_client_index(const GXml&amp; xml) const @@ -1300,9 +1210,9 @@ int GVOHub::get_client_index(const GXml&amp; xml) const
1300 // Continue only if string is not empty 1210 // Continue only if string is not empty
1301 if (!key.empty()) { 1211 if (!key.empty()) {
1302 1212
1303 - // Searches for key in metadata  
1304 - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) {  
1305 - if (strcmp(m_clients->metadata[i].private_key, key.c_str()) == 0) { 1213 + // Searches for key in clients
  1214 + for (int i = 0; i < m_clients.size(); ++i) {
  1215 + if (m_clients[i].private_key == key) {
1306 index = i; 1216 index = i;
1307 break; 1217 break;
1308 } 1218 }
@@ -1400,18 +1310,18 @@ void GVOHub::get_name_value_pair(const GXmlNode* node, @@ -1400,18 +1310,18 @@ void GVOHub::get_name_value_pair(const GXmlNode* node,
1400 1310
1401 1311
1402 /***********************************************************************//** 1312 /***********************************************************************//**
1403 - * @brief Returns registrations from XML document 1313 + * @brief Returns subscriptions from XML document
1404 * 1314 *
1405 * @param[in] xml client query XML document. 1315 * @param[in] xml client query XML document.
1406 - * @return List of registrations. 1316 + * @return List of subscriptions.
1407 ***************************************************************************/ 1317 ***************************************************************************/
1408 -std::list<std::string> GVOHub::get_registrations(const GXml& xml) const 1318 +std::vector<std::string> GVOHub::get_subscriptions(const GXml& xml) const
1409 { 1319 {
1410 - // Declare value  
1411 - std::list<std::string> value; 1320 + // Declare subscriptions
  1321 + std::vector<std::string> subscriptions;
1412 1322
1413 // Get the client's private key 1323 // Get the client's private key
1414 - const GXmlNode* node = xml.element("methodCall > params > param > value > struct"); 1324 + const GXmlNode* node = xml.element("methodCall > params > param[1] > value > struct");
1415 if (node != NULL) { 1325 if (node != NULL) {
1416 int num = node->elements("member"); 1326 int num = node->elements("member");
1417 for (int i = 0; i < num; ++i) { 1327 for (int i = 0; i < num; ++i) {
@@ -1421,40 +1331,40 @@ std::list&lt;std::string&gt; GVOHub::get_registrations(const GXml&amp; xml) const @@ -1421,40 +1331,40 @@ std::list&lt;std::string&gt; GVOHub::get_registrations(const GXml&amp; xml) const
1421 if (name != NULL) { 1331 if (name != NULL) {
1422 const GXmlText* text = static_cast<const GXmlText*>((*name)[0]); 1332 const GXmlText* text = static_cast<const GXmlText*>((*name)[0]);
1423 if (text != NULL) { 1333 if (text != NULL) {
1424 - value.push_front(text->text()); 1334 + subscriptions.push_back(text->text());
1425 } 1335 }
1426 } 1336 }
1427 } 1337 }
1428 } 1338 }
1429 } 1339 }
1430 1340
1431 - // Return value  
1432 - return value; 1341 + // Return subscriptions
  1342 + return subscriptions;
1433 } 1343 }
1434 1344
1435 1345
1436 /***********************************************************************//** 1346 /***********************************************************************//**
1437 - * @brief Returns callback port 1347 + * @brief Returns callback URL of client
1438 * 1348 *
1439 * @param[in] xml client query XML document. 1349 * @param[in] xml client query XML document.
1440 - * @return Callback port value. 1350 + * @return Callback URL of client.
1441 ***************************************************************************/ 1351 ***************************************************************************/
1442 -std::string GVOHub::get_callback_port(const GXml& xml) const 1352 +std::string GVOHub::get_callback_url(const GXml& xml) const
1443 { 1353 {
1444 - // Declare value  
1445 - std::string value; 1354 + // Declare URL
  1355 + std::string url;
1446 1356
1447 // Get the client's private key 1357 // Get the client's private key
1448 const GXmlNode* node = xml.element("methodCall > params > param[1] > value"); 1358 const GXmlNode* node = xml.element("methodCall > params > param[1] > value");
1449 if (node != NULL) { 1359 if (node != NULL) {
1450 const GXmlText* text = static_cast<const GXmlText*>((*node)[0]); 1360 const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
1451 if (text != NULL) { 1361 if (text != NULL) {
1452 - value.append(text->text()); 1362 + url.append(text->text());
1453 } 1363 }
1454 } 1364 }
1455 1365
1456 - // Return value  
1457 - return value; 1366 + // Return URL
  1367 + return url;
1458 } 1368 }
1459 1369
1460 1370
@@ -1510,186 +1420,188 @@ std::string GVOHub::get_hub_lockfile(void) const @@ -1510,186 +1420,188 @@ std::string GVOHub::get_hub_lockfile(void) const
1510 1420
1511 1421
1512 /***********************************************************************//** 1422 /***********************************************************************//**
1513 - * @brief Test if any registered client needs to know that the method  
1514 - * has been called 1423 + * @brief Send notifications
1515 * 1424 *
1516 - * @param[in] method: name of the method  
1517 - * @param[in] cl_id id of calling client 1425 + * @param[in] method Name of the method
  1426 + * @param[in] client Reference of the client
  1427 + *
  1428 + * The method send notifications to all registered clients that request so.
1518 ***************************************************************************/ 1429 ***************************************************************************/
1519 -void GVOHub::activate_callbacks(std::string method,char cl_id[31]) 1430 +void GVOHub::send_notifications(const std::string& method,
  1431 + const std::string& client)
1520 { 1432 {
1521 - int k;  
1522 - char port[16];  
1523 - char pkey[16];  
1524 - std::string spkey;  
1525 -  
1526 // Loop over all clients 1433 // Loop over all clients
1527 - for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) { 1434 + for (int i = 0; i < m_clients.size(); ++i) {
1528 1435
1529 // Loop over all methods 1436 // Loop over all methods
1530 - for (int j = 0; j < GVOHUB_NB_METHODS; ++j) { 1437 + for (int j = 0; j < m_clients[i].subscriptions.size(); ++j) {
  1438 +
  1439 + // Continue only if method matches
  1440 + if (method == m_clients[i].subscriptions[j]) {
1531 1441
1532 - // Continue only if method is valid  
1533 - if (strcmp("",m_clients->metadata[i].registered_methods[j]) != 0) {  
1534 -  
1535 - //  
1536 - if (strcmp(method.c_str(), m_clients->metadata[i].registered_methods[j]) == 0) {  
1537 - strcpy(port,m_clients->metadata[i].port);  
1538 - std::string port_string = std::string(port);  
1539 - //Eliminate http://127.0.0.1/ from port string -----> improve this code is necessary  
1540 - port_string.replace(0,17,"");  
1541 - std::size_t pos = port_string.find("/");  
1542 - std::string port_only = port_string.substr(0,pos);  
1543 -  
1544 - // Set hints  
1545 - struct addrinfo hints;  
1546 - std::memset(&hints, 0, sizeof(hints));  
1547 - hints.ai_family = AF_INET;  
1548 - hints.ai_socktype = SOCK_STREAM;  
1549 -  
1550 - // Get server information  
1551 - struct addrinfo* servinfo;  
1552 - if (getaddrinfo("127.0.0.1", port_only.c_str(),  
1553 - &hints, &servinfo) == 0) {  
1554 -  
1555 - // Loop through all the results and connect to the first  
1556 - // we can  
1557 - for (struct addrinfo* ptr = servinfo; ptr != NULL; ptr = ptr->ai_next) {  
1558 -  
1559 - // Create socket  
1560 - m_cback_socket = socket(ptr->ai_family,  
1561 - ptr->ai_socktype,  
1562 - ptr->ai_protocol);  
1563 -  
1564 - // Connect to socket if socket is valid  
1565 - if (m_cback_socket != -1) {  
1566 - if (::connect(m_cback_socket,  
1567 - ptr->ai_addr,  
1568 - ptr->ai_addrlen) == -1) {  
1569 - close(m_cback_socket);  
1570 - m_cback_socket = -1;  
1571 - }  
1572 - }  
1573 -  
1574 - } // endfor: looped through all results  
1575 -  
1576 - } // endif: server information was valid  
1577 -  
1578 - //  
1579 - std::string msg = "";  
1580 -  
1581 - //  
1582 - if (strcmp(method.c_str(),"samp.hub.event.register") == 0) {  
1583 -  
1584 - // Set methodResponse elts for samp.hub.event.register  
1585 - msg.append("<?xml version=\"1.0\"?>\n");  
1586 - msg.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");  
1587 - msg.append("\t<params>\n");  
1588 - msg.append("\t\t<param><value>");  
1589 - msg.append(m_clients->metadata[i].private_key);  
1590 - msg.append("</value></param>\n");  
1591 - msg.append("\t\t<param><value>"+m_hub_id+"</value></param>\n");  
1592 - msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");  
1593 - msg.append("\t\t\t\t\t<member><name>samp.mtype</name><value>samp.hub.event.register</value></member>\n");  
1594 - msg.append("\t\t\t\t\t<member><name>samp.params</name><value>\n\t\t\t\t\t\t<struct>\n\t\t\t\t\t\t\t<member>");  
1595 - msg.append("<name>id</name><value>");  
1596 - msg.append(cl_id);  
1597 - msg.append("</value></member>\n\t\t\t\t\t\t</struct>\n\t\t\t\t\t</value></member>\n");  
1598 - msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");  
1599 - msg.append("\t</params>\n");  
1600 - msg.append("</methodCall>\n"); 1442 + // Declare notification
  1443 + std::string msg = "";
  1444 +
  1445 + // Register
  1446 + if (method == "samp.hub.event.register") {
  1447 +
  1448 + // Set response for samp.hub.event.register
  1449 + msg.append("<?xml version=\"1.0\"?>\n");
  1450 + msg.append("<methodCall>\n");
  1451 + msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
  1452 + msg.append("<params>\n");
  1453 + msg.append(" <param><value>");
  1454 + msg.append(m_clients[i].private_key);
  1455 + msg.append("</value></param>\n");
  1456 + msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
  1457 + msg.append(" <param><value><struct>\n");
  1458 + msg.append(" <member>\n");
  1459 + msg.append(" <name>samp.mtype</name>\n");
  1460 + msg.append(" <value>samp.hub.event.register</value>\n");
  1461 + msg.append(" </member>\n");
  1462 + msg.append(" <member>\n");
  1463 + msg.append(" <name>samp.params</name>\n");
  1464 + msg.append(" <value><struct>\n");
  1465 + msg.append(" <member>\n");
  1466 + msg.append(" <name>id</name>\n");
  1467 + msg.append(" <value>"+client+"</value>\n");
  1468 + msg.append(" </member>\n");
  1469 + msg.append(" </struct></value>\n");
  1470 + msg.append(" </member>\n");
  1471 + msg.append(" </struct></value></param>\n");
  1472 + msg.append("</params>\n");
  1473 + msg.append("</methodCall>\n");
1601 1474
1602 - // Post response  
1603 - post_string_callback(msg); 1475 + // Post notification
  1476 + notify(m_clients[i].url, msg);
1604 1477
1605 - } 1478 + }
1606 1479
1607 - //  
1608 - else if (strcmp(method.c_str(),"samp.hub.event.unregister") == 0) {  
1609 -  
1610 - // Set methodResponse elts for samp.hub.event.unregister  
1611 - msg.append("<?xml version=\"1.0\"?>\n");  
1612 - msg.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");  
1613 - msg.append("\t<params>\n");  
1614 - msg.append("\t\t<param><value>");  
1615 - msg.append(m_clients->metadata[i].private_key);  
1616 - msg.append("</value></param>\n");  
1617 - msg.append("\t\t<param><value>"+m_hub_id+"</value></param>\n");  
1618 - msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");  
1619 - msg.append("\t\t\t\t\t<member><name>samp.mtype</name><value>samp.hub.event.unregister</value></member>\n");  
1620 - msg.append("\t\t\t\t\t<member><name>samp.params</name><value>\n\t\t\t\t\t\t<struct>\n\t\t\t\t\t\t\t<member>");  
1621 - msg.append("<name>id</name><value>");  
1622 - msg.append(cl_id);  
1623 - msg.append("</value></member>\n\t\t\t\t\t\t</struct>\n\t\t\t\t\t</value></member>\n");  
1624 - msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");  
1625 - msg.append("\t</params>\n");  
1626 - msg.append("</methodCall>\n"); 1480 + // Unregister
  1481 + else if (method == "samp.hub.event.unregister") {
  1482 +
  1483 + // Set response for samp.hub.event.unregister
  1484 + msg.append("<?xml version=\"1.0\"?>\n");
  1485 + msg.append("<methodCall>\n");
  1486 + msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
  1487 + msg.append("<params>\n");
  1488 + msg.append(" <param><value>");
  1489 + msg.append(m_clients[i].private_key);
  1490 + msg.append("</value></param>\n");
  1491 + msg.append(" <param><value>");
  1492 + msg.append(m_hub_id);
  1493 + msg.append("</value></param>\n");
  1494 + msg.append(" <param><value><struct>\n");
  1495 + msg.append(" <member>\n");
  1496 + msg.append(" <name>samp.mtype</name>\n");
  1497 + msg.append(" <value>samp.hub.event.unregister</value>\n");
  1498 + msg.append(" </member>\n");
  1499 + msg.append(" <member>\n");
  1500 + msg.append(" <name>samp.params</name>\n");
  1501 + msg.append(" <value><struct>\n");
  1502 + msg.append(" <member>\n");
  1503 + msg.append(" <name>id</name>\n");
  1504 + msg.append(" <value>"+client+"</value>\n");
  1505 + msg.append(" </member>\n");
  1506 + msg.append(" </struct></value>\n");
  1507 + msg.append(" </member>\n");
  1508 + msg.append(" </struct></value></param>\n");
  1509 + msg.append("</params>\n");
  1510 + msg.append("</methodCall>\n");
1627 1511
1628 - // Post response  
1629 - post_string_callback(msg); 1512 + // Post notification
  1513 + notify(m_clients[i].url, msg);
1630 1514
1631 - } 1515 + }
1632 1516
1633 - //  
1634 - else if (strcmp(method.c_str(),"samp.hub.event.metadata") == 0) {  
1635 -  
1636 - // Set methodResponse elts for samp.hub.event.unregister  
1637 - msg.append("<?xml version=\"1.0\"?>\n");  
1638 - msg.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");  
1639 - msg.append("\t<params>\n");  
1640 - msg.append("\t\t<param><value>");  
1641 - msg.append(m_clients->metadata[i].private_key);  
1642 - msg.append("</value></param>\n");  
1643 - msg.append("\t\t<param><value>"+m_hub_id+"</value></param>\n");  
1644 - msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");  
1645 - msg.append("\t\t\t\t\t<member><name>samp.mtype</name><value>samp.hub.event.metadata</value></member>\n");  
1646 - msg.append("\t\t\t\t\t<member><name>samp.params</name><value>\n\t\t\t\t\t\t<struct>\n\t\t\t\t\t\t\t");  
1647 - msg.append("\t\t\t\t\t<member><name>id</name><value>");  
1648 - for (k = 0; k < GVOHUB_NB_CLIENTS; k++) {  
1649 - if (strcmp(cl_id,m_clients->metadata[k].reference) == 0) {  
1650 - break;  
1651 - } 1517 + // Metadata
  1518 + else if (method == "samp.hub.event.metadata") {
  1519 +
  1520 + // Get index of client
  1521 + int k;
  1522 + for (k = 0; k < m_clients.size(); ++k) {
  1523 + if (m_clients[k].reference == client) {
  1524 + break;
1652 } 1525 }
1653 - msg.append(m_clients->metadata[k].reference);  
1654 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1655 - msg.append("\t\t\t\t\t<member><name>metadata</name><value>\n\t\t\t\t\t\t<struct>\n\t\t\t\t\t\t\t");  
1656 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.name</name>\n\t\t\t\t\t\t<value>");  
1657 - msg.append(m_clients->metadata[k].name);  
1658 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1659 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.description.text</name>\n\t\t\t\t\t\t<value>");  
1660 - msg.append(m_clients->metadata[k].description);  
1661 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1662 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.icon.url</name>\n\t\t\t\t\t\t<value>");  
1663 - msg.append(m_clients->metadata[k].icon);  
1664 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1665 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.documentation.url</name>\n\t\t\t\t\t\t<value>");  
1666 - msg.append(m_clients->metadata[k].documentation);  
1667 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1668 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>author.affiliation</name>\n\t\t\t\t\t\t<value>");  
1669 - msg.append(m_clients->metadata[k].affiliation);  
1670 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1671 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>author.email</name>\n\t\t\t\t\t\t<value>");  
1672 - msg.append(m_clients->metadata[k].email);  
1673 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1674 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>author.name</name>\n\t\t\t\t\t\t<value>");  
1675 - msg.append(m_clients->metadata[k].author_name);  
1676 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1677 - msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>home.page</name>\n\t\t\t\t\t\t<value>");  
1678 - msg.append(m_clients->metadata[k].homepage);  
1679 - msg.append("</value>\n\t\t\t\t\t</member>\n");  
1680 - msg.append("</struct></value></member>\n");  
1681 - msg.append("</struct>\n\t\t\t\t\t</value></member>\n");  
1682 - msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");  
1683 - msg.append("\t</params>\n");  
1684 - msg.append("</methodCall>\n"); 1526 + }
  1527 +
  1528 + // Fall through if client index is not valid
  1529 + if (k >= m_clients.size()) {
  1530 + continue;
  1531 + }
  1532 +
  1533 + // Set response for samp.hub.event.metadata
  1534 + msg.append("<?xml version=\"1.0\"?>\n");
  1535 + msg.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");
  1536 + msg.append("<params>\n");
  1537 + msg.append(" <param><value>");
  1538 + msg.append(m_clients[i].private_key);
  1539 + msg.append("</value></param>\n");
  1540 + msg.append(" <param><value>"+m_hub_id+"</value></param>\n");
  1541 + msg.append(" <param><value><struct>\n");
  1542 + msg.append(" <member>\n");
  1543 + msg.append(" <name>samp.mtype</name>\n");
  1544 + msg.append(" <value>samp.hub.event.metadata</value>\n");
  1545 + msg.append(" </member>\n");
  1546 + msg.append(" <member>\n");
  1547 + msg.append(" <name>samp.params</name>\n");
  1548 + msg.append(" <value><struct>\n");
  1549 + msg.append(" <member>\n");
  1550 + msg.append(" <name>id</name>\n");
  1551 + msg.append(" <value>"+m_clients[k].reference+"</value>\n");
  1552 + msg.append(" </member>\n");
  1553 + msg.append(" <member>\n");
  1554 + msg.append(" <name>metadata</name>\n");
  1555 + msg.append(" <value><struct>\n");
  1556 + msg.append(" <member>\n");
  1557 + msg.append(" <name>samp.name</name>\n");
  1558 + msg.append(" <value>"+m_clients[k].name+"</value>\n");
  1559 + msg.append(" </member>\n");
  1560 + msg.append(" <member>\n");
  1561 + msg.append(" <name>samp.description.text</name>\n");
  1562 + msg.append(" <value>"+m_clients[k].description+"</value>\n");
  1563 + msg.append(" </member>\n");
  1564 + msg.append(" <member>\n");
  1565 + msg.append(" <name>samp.icon.url</name>\n");
  1566 + msg.append(" <value>"+m_clients[k].icon+"</value>\n");
  1567 + msg.append(" </member>\n");
  1568 + msg.append(" <member>\n");
  1569 + msg.append(" <name>samp.documentation.url</name>\n");
  1570 + msg.append(" <value>"+m_clients[k].documentation+"</value>\n");
  1571 + msg.append(" </member>\n");
  1572 + msg.append(" <member>\n");
  1573 + msg.append(" <name>author.affiliation</name>\n");
  1574 + msg.append(" <value>"+m_clients[k].affiliation+"</value>\n");
  1575 + msg.append(" </member>\n");
  1576 + msg.append(" <member>\n");
  1577 + msg.append(" <name>author.name</name>\n");
  1578 + msg.append(" <value>"+m_clients[k].author_name+"</value>\n");
  1579 + msg.append(" </member>\n");
  1580 + msg.append(" <member>\n");
  1581 + msg.append(" <name>author.email</name>\n");
  1582 + msg.append(" <value>"+m_clients[k].email+"</value>\n");
  1583 + msg.append(" </member>\n");
  1584 + msg.append(" <member>\n");
  1585 + msg.append(" <name>home.page</name>\n");
  1586 + msg.append(" <value>"+m_clients[k].homepage+"</value>\n");
  1587 + msg.append(" </member>\n");
  1588 + msg.append(" </struct></value>\n");
  1589 + msg.append(" </member>\n");
  1590 + msg.append(" </struct></value>\n");
  1591 + msg.append(" </member>\n");
  1592 + msg.append(" </struct></value></param>\n");
  1593 + msg.append("</params>\n");
  1594 + msg.append("</methodCall>\n");
1685 1595
1686 - // Post response  
1687 - post_string_callback(msg); 1596 + // Post notification
  1597 + notify(m_clients[i].url, msg);
1688 1598
1689 - }  
1690 - }  
1691 - } // endif: method was valid 1599 + } // endelse: metadata
  1600 +
  1601 + } // endif: method was requested one
  1602 +
1692 } // endfor: looped over all methods 1603 } // endfor: looped over all methods
  1604 +
1693 } // endfor: looped over all clients 1605 } // endfor: looped over all clients
1694 1606
1695 // Return 1607 // Return
@@ -1709,37 +1621,61 @@ void GVOHub::create_samp_file(void) const @@ -1709,37 +1621,61 @@ void GVOHub::create_samp_file(void) const
1709 1621
1710 // Open SAMP lockfile. Continue only if opening was successful 1622 // Open SAMP lockfile. Continue only if opening was successful
1711 FILE* fptr = fopen(lockurl.c_str(), "w"); 1623 FILE* fptr = fopen(lockurl.c_str(), "w");
  1624 +
  1625 + // Successful?
1712 if (fptr != NULL) { 1626 if (fptr != NULL) {
1713 1627
1714 - // If successful writes basic hub configuration to the lockfile  
1715 - fputs("# SAMP lockfile \n# Required keys:\n",fptr);  
1716 - char sampsecret[256] = "samp.secret=";  
1717 - strcat(sampsecret,m_secret.c_str());  
1718 - strcat(sampsecret,"\n");  
1719 - fputs (sampsecret,fptr);  
1720 - char sampurl[256] = "samp.hub.xmlrpc.url=";  
1721 - strcat(sampurl,m_hub_url.c_str());  
1722 - strcat(sampurl,"\n");  
1723 - fputs(sampurl,fptr);  
1724 - char samprofile[256] = "samp.profile.version=";  
1725 - strcat(samprofile,m_version.c_str());  
1726 - strcat(samprofile,"\n");  
1727 - fputs(samprofile,fptr);  
1728 - fputs("# Info stored by hub for some private reason:\n",fptr);  
1729 - char sampid[256] = "gammalib.hubid=";  
1730 - strcat(sampid,m_hub_id.c_str());  
1731 - strcat(sampid,"\n");  
1732 - fputs(sampid,fptr); 1628 + // Write lockfile
  1629 + fprintf(fptr, "# SAMP lockfile\n");
  1630 + fprintf(fptr, "# Required keys:\n");
  1631 + fprintf(fptr, "samp.secret=%s\n", m_secret.c_str());
  1632 + fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", m_hub_url.c_str());
  1633 + fprintf(fptr, "samp.profile.version=%s\n", m_version.c_str());
  1634 + fprintf(fptr, "# Info stored by hub for some private reason:\n");
  1635 + fprintf(fptr, "gammalib.hubid=%s\n", m_hub_id.c_str());
  1636 +
  1637 + // Close lockfile
  1638 + fclose(fptr);
  1639 +
1733 } 1640 }
1734 -  
1735 - // Close SAMP lockfile  
1736 - fclose(fptr);  
1737 1641
1738 // Return 1642 // Return
1739 return; 1643 return;
1740 } 1644 }
1741 1645
1742 1646
  1647 +/***********************************************************************//**
  1648 + * @brief Post SAMP ok massage to client
  1649 + *
  1650 + * @param[in] sock Socket.
  1651 + *
  1652 + * Posts a SAMP of massage to a client.
  1653 + ***************************************************************************/
  1654 +void GVOHub::post_samp_ok(const socklen_t& sock) const
  1655 +{
  1656 + // Declare response
  1657 + std::string response = "";
  1658 +
  1659 + // Compose response
  1660 + response.append("<?xml version='1.0' encoding='UTF-8'?>\n");
  1661 + response.append("<methodResponse>\n");
  1662 + response.append("<params>\n");
  1663 + response.append(" <param><value><struct>\n");
  1664 + response.append(" <member>\n");
  1665 + response.append(" <name>samp.status</name>\n");
  1666 + response.append(" <value>samp.ok</value>\n");
  1667 + response.append(" </member>\n");
  1668 + response.append(" </struct></value></param>\n");
  1669 + response.append("</params>\n");
  1670 + response.append("</methodResponse>\n");
  1671 +
  1672 + // Post string
  1673 + post_string(response, sock);
  1674 +
  1675 + // Return
  1676 + return;
  1677 +}
  1678 +
1743 1679
1744 /***********************************************************************//** 1680 /***********************************************************************//**
1745 * @brief Post string content to client 1681 * @brief Post string content to client
@@ -1749,7 +1685,7 @@ void GVOHub::create_samp_file(void) const @@ -1749,7 +1685,7 @@ void GVOHub::create_samp_file(void) const
1749 * 1685 *
1750 * Posts the content of a string to a client. 1686 * Posts the content of a string to a client.
1751 ***************************************************************************/ 1687 ***************************************************************************/
1752 -void GVOHub::post_string(const std::string& content,const socklen_t& sock) const 1688 +void GVOHub::post_string(const std::string& content, const socklen_t& sock) const
1753 { 1689 {
1754 // Continue only if socket is valid 1690 // Continue only if socket is valid
1755 if (sock != -1) { 1691 if (sock != -1) {
@@ -1758,18 +1694,26 @@ void GVOHub::post_string(const std::string&amp; content,const socklen_t&amp; sock) const @@ -1758,18 +1694,26 @@ void GVOHub::post_string(const std::string&amp; content,const socklen_t&amp; sock) const
1758 int length = content.length(); 1694 int length = content.length();
1759 1695
1760 // Set prefix 1696 // Set prefix
1761 - std::string prefix = "HTTP/1.1 200 OK\n"  
1762 - "Connection: close\n" 1697 + std::string prefix = "POST /"+m_hub_path+" HTTP/1.1\n"
1763 "Content-Type: text/xml\n" 1698 "Content-Type: text/xml\n"
  1699 + "User-Agent: GammaLib\n"
  1700 + "Host: "+m_hub_host+":"+m_hub_port+"\n"
  1701 + "Connection: close\n"
1764 "Content-Length: "+gammalib::str(length)+"\n\n"; 1702 "Content-Length: "+gammalib::str(length)+"\n\n";
1765 1703
1766 // Build post string 1704 // Build post string
1767 std::string post = prefix + content; 1705 std::string post = prefix + content;
1768 1706
  1707 + // Dump message to post
  1708 + #if defined(G_CONSOLE_DUMP)
  1709 + std::cout << "\nGVOHub::post_string posts the following message" << std::endl;
  1710 + std::cout << post << std::endl;
  1711 + #endif
  1712 +
1769 // Send content to socket 1713 // Send content to socket
1770 bool done = false; 1714 bool done = false;
1771 do { 1715 do {
1772 - int length = post.length(); 1716 + int length = post.length() + 1; // +1 for terminating 0
1773 int sent_length = send(sock, post.c_str(), length, 0); 1717 int sent_length = send(sock, post.c_str(), length, 0);
1774 if (sent_length < length) { 1718 if (sent_length < length) {
1775 post = post.substr(sent_length, std::string::npos); 1719 post = post.substr(sent_length, std::string::npos);
@@ -1787,38 +1731,116 @@ void GVOHub::post_string(const std::string&amp; content,const socklen_t&amp; sock) const @@ -1787,38 +1731,116 @@ void GVOHub::post_string(const std::string&amp; content,const socklen_t&amp; sock) const
1787 1731
1788 1732
1789 /***********************************************************************//** 1733 /***********************************************************************//**
1790 - * @brief Post string content to client for callback  
1791 - *  
1792 - * @param[in] content String content to post 1734 + * @brief Send notification to client
1793 * 1735 *
1794 - * Posts the content of a string to the client for a callback. 1736 + * @param[in] url URL.
  1737 + * @param[in] notification Notification.
1795 * 1738 *
1796 - * The method does nothing if no callback socket is open. 1739 + * Send a @p notification to a @p url.
1797 ***************************************************************************/ 1740 ***************************************************************************/
1798 -void GVOHub::post_string_callback(const std::string& content) const 1741 +void GVOHub::notify(const std::string& url,
  1742 + const std::string& notification) const
1799 { 1743 {
1800 - // Continue only if Hub connection has been established  
1801 - if (m_cback_socket != -1) { 1744 + // Initalise socket
  1745 + int socket = -1;
  1746 +
  1747 + // Extract host, port and path from URL
  1748 + std::string host = "127.0.0.1";
  1749 + std::string port = "2525";
  1750 + std::string path = "xmlrpc";
  1751 + if (url.compare(0, 7, "http://") == 0) {
  1752 + size_t length;
  1753 + size_t start = 7;
  1754 + size_t stop = url.find(":", start);
  1755 + size_t end = std::string::npos;
  1756 + if (stop != std::string::npos) {
  1757 + length = stop - start;
  1758 + }
  1759 + else {
  1760 + length = std::string::npos;
  1761 + }
  1762 + host = url.substr(start, length);
  1763 + if (stop != std::string::npos) {
  1764 + stop++;
  1765 + end = url.find("/", stop);
  1766 + if (end != std::string::npos) {
  1767 + length = end - stop;
  1768 + }
  1769 + else {
  1770 + length = std::string::npos;
  1771 + }
  1772 + port = url.substr(stop, length);
  1773 + }
  1774 + if (end != std::string::npos) {
  1775 + end++;
  1776 + length = url.length() - end;
  1777 + path = url.substr(end, length);
  1778 + }
  1779 + }
1802 1780
1803 - // Determine content length  
1804 - int length = content.length(); 1781 + // Set hints
  1782 + struct addrinfo hints;
  1783 + std::memset(&hints, 0, sizeof(hints));
  1784 + hints.ai_family = AF_INET;
  1785 + hints.ai_socktype = SOCK_STREAM;
  1786 +
  1787 + // Get server information
  1788 + struct addrinfo* servinfo;
  1789 + if (getaddrinfo(host.c_str(), port.c_str(), &hints, &servinfo) == 0) {
  1790 +
  1791 + // Loop through all the results and connect to the first we can
  1792 + for (struct addrinfo* ptr = servinfo; ptr != NULL; ptr = ptr->ai_next) {
  1793 +
  1794 + // Create socket
  1795 + socket = ::socket(ptr->ai_family,
  1796 + ptr->ai_socktype,
  1797 + ptr->ai_protocol);
  1798 +
  1799 + // Connect to socket if socket is valid
  1800 + if (socket != -1) {
  1801 + if (::connect(socket,
  1802 + ptr->ai_addr,
  1803 + ptr->ai_addrlen) == -1) {
  1804 + close(socket);
  1805 + socket = -1;
  1806 + }
  1807 + else {
  1808 + // Socket connection successful, break now
  1809 + break;
  1810 + }
  1811 + }
  1812 +
  1813 + } // endfor: looped through all results
  1814 +
  1815 + } // endif: server information was valid
  1816 +
  1817 + // Continue only if socket is valid
  1818 + if (socket != -1) {
  1819 +
  1820 + // Determine notification length
  1821 + int length = notification.length();
1805 1822
1806 // Set prefix 1823 // Set prefix
1807 - std::string prefix = "POST /xmlrpc HTTP/1.1\n"  
1808 - "Connection: keep-alive\n" 1824 + std::string prefix = "POST /"+path+" HTTP/1.0\n"
  1825 + "Connection: close\n"
1809 "User-Agent: GammaLib\n" 1826 "User-Agent: GammaLib\n"
1810 - "Host: localhost:"+gammalib::str(m_cback_socket)+"\n"  
1811 "Content-Type: text/xml\n" 1827 "Content-Type: text/xml\n"
1812 "Content-Length: "+gammalib::str(length)+"\n\n"; 1828 "Content-Length: "+gammalib::str(length)+"\n\n";
1813 1829
1814 // Build post string 1830 // Build post string
1815 - std::string post = prefix + content; 1831 + std::string post = prefix + notification;
  1832 +
  1833 + // Dump message to post
  1834 + #if defined(G_CONSOLE_DUMP)
  1835 + std::cout << "\nGVOHub::notify posts the following message" << std::endl;
  1836 + std::cout << post << std::endl;
  1837 + #endif
1816 1838
1817 // Send content to socket 1839 // Send content to socket
1818 bool done = false; 1840 bool done = false;
1819 do { 1841 do {
1820 - int length = post.length();  
1821 - int sent_length = send(m_cback_socket, post.c_str(), length, 0); 1842 + int length = post.length() + 1; // +1 for terminating 0
  1843 + int sent_length = send(socket, post.c_str(), length, 0);
1822 if (sent_length < length) { 1844 if (sent_length < length) {
1823 post = post.substr(sent_length, std::string::npos); 1845 post = post.substr(sent_length, std::string::npos);
1824 } 1846 }
@@ -1827,20 +1849,29 @@ void GVOHub::post_string_callback(const std::string&amp; content) const @@ -1827,20 +1849,29 @@ void GVOHub::post_string_callback(const std::string&amp; content) const
1827 } 1849 }
1828 } while (!done); 1850 } while (!done);
1829 1851
  1852 + /*
  1853 + // Declare response
  1854 + std::string response = "";
  1855 +
1830 // Read buffer until it is empty 1856 // Read buffer until it is empty
1831 char buffer[1001]; 1857 char buffer[1001];
1832 - int timeout = 2000; // Initial timeout is 2 sec 1858 + int timeout = 1000; // Initial timeout is 1 sec
1833 int n = 0; 1859 int n = 0;
1834 do { 1860 do {
1835 - n = gammalib::recv(m_cback_socket, buffer, 1000, 0, timeout); 1861 + n = gammalib::recv(socket, buffer, 1000, 0, timeout);
1836 if (n > 0) { 1862 if (n > 0) {
1837 buffer[n+1] = '\0'; 1863 buffer[n+1] = '\0';
  1864 + response.append(std::string(buffer));
1838 } 1865 }
1839 timeout = 10; // The timeout now is 0.01 sec 1866 timeout = 10; // The timeout now is 0.01 sec
1840 } while (n > 0); 1867 } while (n > 0);
  1868 + */
  1869 +
  1870 + // Close socket
  1871 + close(socket);
  1872 +
  1873 + }
1841 1874
1842 - } // endif: Hub connection had been established  
1843 -  
1844 // Return 1875 // Return
1845 return; 1876 return;
1846 } 1877 }