Commit 1204163444396ab8bf480030c7a5028b4e7fcdee

Authored by Jürgen Knödlseder
1 parent c93d18a6

Integrate code from GVOTable branch of Thierry Louge.

include/GVOClient.hpp
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 #include "GBase.hpp" 32 #include "GBase.hpp"
33 #include "GXml.hpp" 33 #include "GXml.hpp"
34 #include "GXmlNode.hpp" 34 #include "GXmlNode.hpp"
35 - 35 +#include "GFits.hpp"
36 36
37 /***********************************************************************//** 37 /***********************************************************************//**
38 * @class GVOClient 38 * @class GVOClient
@@ -74,8 +74,9 @@ public: @@ -74,8 +74,9 @@ public:
74 bool ping_hub(void) const; 74 bool ping_hub(void) const;
75 void shutdown_hub(void) const; 75 void shutdown_hub(void) const;
76 GXml execute(const std::string& request) const; 76 GXml execute(const std::string& request) const;
  77 + void publish(const GFitsHDU& hdu);
77 std::string print(const GChatter& chatter = NORMAL) const; 78 std::string print(const GChatter& chatter = NORMAL) const;
78 - 79 +
79 protected: 80 protected:
80 // Protected methods 81 // Protected methods
81 void init_members(void); 82 void init_members(void);
@@ -97,7 +98,7 @@ protected: @@ -97,7 +98,7 @@ protected:
97 bool response_is_valid(const GXml& xml) const; 98 bool response_is_valid(const GXml& xml) const;
98 int response_error_code(const GXml& xml) const; 99 int response_error_code(const GXml& xml) const;
99 std::string response_error_message(const GXml& xml) const; 100 std::string response_error_message(const GXml& xml) const;
100 - 101 +
101 // Protected data area 102 // Protected data area
102 std::string m_name; //!< Client name 103 std::string m_name; //!< Client name
103 std::string m_secret; //!< Secret Hub key 104 std::string m_secret; //!< Secret Hub key
include/GVOHub.hpp
@@ -103,19 +103,22 @@ protected: @@ -103,19 +103,22 @@ protected:
103 std::vector<std::string> get_subscriptions(const GXml& xml) const; 103 std::vector<std::string> get_subscriptions(const GXml& xml) const;
104 std::string get_callback_url(const GXml& xml) const; 104 std::string get_callback_url(const GXml& xml) const;
105 std::string get_hub_lockfile(void) const; 105 std::string get_hub_lockfile(void) const;
106 - void send_notifications(const std::string& method, 106 + void send_notifications(const std::string& method,
107 const std::string& client); 107 const std::string& client);
  108 + void send_notifications(const std::string& method,
  109 + const std::string& client,
  110 + const GXml& xml);
  111 + void broadcast(const GXml& xml, const socklen_t& sock);
  112 + std::string get_mtype(const GXml& xml) const;
  113 + std::string get_destination(const GXml& xml) const;
108 114
109 // Low-level methods 115 // Low-level methods
110 void create_samp_file(void) const; 116 void create_samp_file(void) const;
111 - void delete_samp_file(void) const;  
112 - int get_socket(void);  
113 void post_samp_ok(const socklen_t& sock) const; 117 void post_samp_ok(const socklen_t& sock) const;
114 void post_samp_void(const socklen_t& sock) const; 118 void post_samp_void(const socklen_t& sock) const;
115 void post_string(const std::string& content, const socklen_t& sock) const; 119 void post_string(const std::string& content, const socklen_t& sock) const;
116 void notify(const std::string& url, const std::string& notification) const; 120 void notify(const std::string& url, const std::string& notification) const;
117 std::string random_string(const size_t& length) const; 121 std::string random_string(const size_t& length) const;
118 - std::string hub_url(void) const;  
119 122
120 // Protected structure 123 // Protected structure
121 struct client { 124 struct client {
@@ -135,12 +138,13 @@ protected: @@ -135,12 +138,13 @@ protected:
135 138
136 // Protected members 139 // Protected members
137 std::string m_secret; //!< Secret Hub key 140 std::string m_secret; //!< Secret Hub key
  141 + std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub
138 std::string m_hub_host; //!< Hub host 142 std::string m_hub_host; //!< Hub host
139 std::string m_hub_port; //!< Hub port 143 std::string m_hub_port; //!< Hub port
140 std::string m_hub_path; //!< Hub path 144 std::string m_hub_path; //!< Hub path
141 std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub 145 std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub
142 std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others 146 std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others
143 - int m_socket; //!< Hub socket 147 + socklen_t m_socket; //!< Hub socket
144 bool m_shutdown; //!< Shutdown request 148 bool m_shutdown; //!< Shutdown request
145 std::vector<client> m_clients; //!< Clients 149 std::vector<client> m_clients; //!< Clients
146 }; 150 };
src/vo/GVOClient.cpp
@@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
34 #include <unistd.h> // close() function 34 #include <unistd.h> // close() function
35 #include <netdb.h> // getaddrinfo() function 35 #include <netdb.h> // getaddrinfo() function
36 #include <sys/socket.h> // socket(), connect() functions 36 #include <sys/socket.h> // socket(), connect() functions
  37 +#include <fstream>
37 #include "GVOClient.hpp" 38 #include "GVOClient.hpp"
38 #include "GVOHub.hpp" 39 #include "GVOHub.hpp"
39 #include "GException.hpp" 40 #include "GException.hpp"
@@ -359,6 +360,47 @@ GXml GVOClient::execute(const std::string&amp; request) const @@ -359,6 +360,47 @@ GXml GVOClient::execute(const std::string&amp; request) const
359 360
360 361
361 /***********************************************************************//** 362 /***********************************************************************//**
  363 + * @brief Publish FITS HDU
  364 + *
  365 + * @param[in] hdu FITS HDU
  366 + *
  367 + * Publishes a FITS HDU.
  368 + ***************************************************************************/
  369 +void GVOClient::publish(const GFitsHDU& hdu)
  370 +{
  371 + // Save FITS HDU into a temporary file
  372 + std::string samp_share = std::tmpnam(NULL);
  373 + GFits fits;
  374 + fits.append(hdu);
  375 + fits.saveto(samp_share, true);
  376 +
  377 + // Compose notification to be passed to the Hub
  378 + std::string hub_command = "";
  379 + hub_command.append("<?xml version=\"1.0\"?>\n");
  380 + hub_command.append("<methodCall>");
  381 + hub_command.append(" <methodName>samp.hub.notifyAll</methodName>\n");
  382 + hub_command.append(" <params>\n");
  383 + hub_command.append(" <param><value>image.load.fits</value></param>\n");
  384 + hub_command.append(" <param><value>"+m_secret+"</value></param>\n");
  385 + hub_command.append(" <param><value><struct>\n");
  386 + hub_command.append(" <member><name>samp.params</name><value><struct>\n");
  387 + hub_command.append(" <member><name>name</name><value>Gammalib_FITS_FILE</value></member>\n");
  388 + hub_command.append(" <member><name>url</name><value>file://localhost"+samp_share+"</value></member>\n");
  389 + hub_command.append(" <member><name>image-id</name><value>Gammalib Data</value></member>\n");
  390 + hub_command.append(" </struct></value></member>\n");
  391 + hub_command.append(" <member><name>samp.mtype</name><value>image.load.fits</value></member>\n");
  392 + hub_command.append(" </struct></value></param>\n");
  393 + hub_command.append(" </params>\n</methodCall>\n");
  394 +
  395 + // Send notification
  396 + execute(hub_command);
  397 +
  398 + // Return
  399 + return;
  400 +}
  401 +
  402 +
  403 +/***********************************************************************//**
362 * @brief Print VO client information 404 * @brief Print VO client information
363 * 405 *
364 * @param[in] chatter Chattiness (defaults to NORMAL). 406 * @param[in] chatter Chattiness (defaults to NORMAL).
@@ -517,7 +559,7 @@ bool GVOClient::find_hub(void) @@ -517,7 +559,7 @@ bool GVOClient::find_hub(void)
517 if (!lockurl.empty()) { 559 if (!lockurl.empty()) {
518 560
519 // If we have a file:// prefix then strip it now. This is a kluge 561 // If we have a file:// prefix then strip it now. This is a kluge
520 - // and should be replaced by a method that allows opening any kind 562 + // and should be remplaced by a method that allows opening any kind
521 // of URL 563 // of URL
522 if (lockurl.compare(0, 7, "file://") == 0) { 564 if (lockurl.compare(0, 7, "file://") == 0) {
523 lockurl = lockurl.substr(7, std::string::npos); 565 lockurl = lockurl.substr(7, std::string::npos);
@@ -955,6 +997,7 @@ std::string GVOClient::receive_string(void) const @@ -955,6 +997,7 @@ std::string GVOClient::receive_string(void) const
955 int n = 0; 997 int n = 0;
956 do { 998 do {
957 n = gammalib::recv(m_socket, buffer, 1000, 0, timeout); 999 n = gammalib::recv(m_socket, buffer, 1000, 0, timeout);
  1000 + //n = recv(m_socket, buffer, 1000, 0);
958 if (n > 0) { 1001 if (n > 0) {
959 buffer[n] = '\0'; 1002 buffer[n] = '\0';
960 result.append(std::string(buffer)); 1003 result.append(std::string(buffer));
@@ -1073,7 +1116,7 @@ std::string GVOClient::get_hub_lockfile(void) const @@ -1073,7 +1116,7 @@ std::string GVOClient::get_hub_lockfile(void) const
1073 char* hub_ptr = std::getenv("SAMP_HUB"); 1116 char* hub_ptr = std::getenv("SAMP_HUB");
1074 if (hub_ptr != NULL) { 1117 if (hub_ptr != NULL) {
1075 1118
1076 - // Check for mandatory std-lockurl: prefix (no other prefix is 1119 + // Check for mandatory std-lockurl: prefix (no other prefixe is
1077 // supported so far) 1120 // supported so far)
1078 std::string lockurl = std::string(hub_ptr); 1121 std::string lockurl = std::string(hub_ptr);
1079 if (lockurl.compare(0, 12, "std-lockurl:") == 0) { 1122 if (lockurl.compare(0, 12, "std-lockurl:") == 0) {
@@ -1083,7 +1126,7 @@ std::string GVOClient::get_hub_lockfile(void) const @@ -1083,7 +1126,7 @@ std::string GVOClient::get_hub_lockfile(void) const
1083 1126
1084 } // endif: std-lockurl: prefix found 1127 } // endif: std-lockurl: prefix found
1085 1128
1086 - } // endif: SAMP_HUB environment variable found 1129 + }
1087 1130
1088 // ... otherwise the lockfile should be $HOME/.samp 1131 // ... otherwise the lockfile should be $HOME/.samp
1089 else { 1132 else {
src/vo/GVOHub.cpp
@@ -47,15 +47,14 @@ @@ -47,15 +47,14 @@
47 47
48 /* __ Method name definitions ____________________________________________ */ 48 /* __ Method name definitions ____________________________________________ */
49 #define G_START_HUB "GVOHub::start_hub()" 49 #define G_START_HUB "GVOHub::start_hub()"
50 -#define G_START_SOCKET "GVOHub::start_socket()"  
51 50
52 /* __ Macros _____________________________________________________________ */ 51 /* __ Macros _____________________________________________________________ */
53 52
54 /* __ Coding definitions _________________________________________________ */ 53 /* __ Coding definitions _________________________________________________ */
55 54
56 /* __ Debug definitions __________________________________________________ */ 55 /* __ Debug definitions __________________________________________________ */
57 -//#define G_CONSOLE_DUMP  
58 -//#define G_SHOW_MESSAGE 56 +#define G_CONSOLE_DUMP
  57 +#define G_SHOW_MESSAGE
59 58
60 59
61 /*========================================================================== 60 /*==========================================================================
@@ -86,7 +85,7 @@ GVOHub::GVOHub(const GVOHub&amp; hub) @@ -86,7 +85,7 @@ GVOHub::GVOHub(const GVOHub&amp; hub)
86 { 85 {
87 // Initialise members 86 // Initialise members
88 init_members(); 87 init_members();
89 - 88 +
90 // Copy members 89 // Copy members
91 copy_members(hub); 90 copy_members(hub);
92 91
@@ -180,6 +179,9 @@ GVOHub* GVOHub::clone(void) const @@ -180,6 +179,9 @@ GVOHub* GVOHub::clone(void) const
180 ***************************************************************************/ 179 ***************************************************************************/
181 void GVOHub::start(void) 180 void GVOHub::start(void)
182 { 181 {
  182 + // Create SAMP file
  183 + create_samp_file();
  184 +
183 // Start Hub 185 // Start Hub
184 start_hub(); 186 start_hub();
185 187
@@ -208,7 +210,7 @@ std::string GVOHub::print(const GChatter&amp; chatter) const @@ -208,7 +210,7 @@ std::string GVOHub::print(const GChatter&amp; chatter) const
208 // Append Hub information 210 // Append Hub information
209 result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id); 211 result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id);
210 result.append("\n"+gammalib::parformat("Hub key")+m_secret); 212 result.append("\n"+gammalib::parformat("Hub key")+m_secret);
211 - result.append("\n"+gammalib::parformat("Hub URL")+hub_url()); 213 + result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url);
212 result.append("\n"+gammalib::parformat("Hub host")+m_hub_host); 214 result.append("\n"+gammalib::parformat("Hub host")+m_hub_host);
213 result.append("\n"+gammalib::parformat("Hub port")+m_hub_port); 215 result.append("\n"+gammalib::parformat("Hub port")+m_hub_port);
214 result.append("\n"+gammalib::parformat("Hub path")+m_hub_path); 216 result.append("\n"+gammalib::parformat("Hub path")+m_hub_path);
@@ -238,6 +240,7 @@ void GVOHub::init_members(void) @@ -238,6 +240,7 @@ void GVOHub::init_members(void)
238 m_hub_host = "127.0.0.1"; 240 m_hub_host = "127.0.0.1";
239 m_hub_port = "2526"; 241 m_hub_port = "2526";
240 m_hub_path = "xmlrpc"; 242 m_hub_path = "xmlrpc";
  243 + m_hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path;
241 m_version = "1.3"; 244 m_version = "1.3";
242 m_hub_id = "gammalib_hub"; 245 m_hub_id = "gammalib_hub";
243 m_socket = -1; // Signals no socket 246 m_socket = -1; // Signals no socket
@@ -258,6 +261,7 @@ void GVOHub::copy_members(const GVOHub&amp; hub) @@ -258,6 +261,7 @@ void GVOHub::copy_members(const GVOHub&amp; hub)
258 { 261 {
259 // Copy members 262 // Copy members
260 m_secret = hub.m_secret; 263 m_secret = hub.m_secret;
  264 + m_hub_url = hub.m_hub_url;
261 m_hub_host = hub.m_hub_host; 265 m_hub_host = hub.m_hub_host;
262 m_hub_port = hub.m_hub_port; 266 m_hub_port = hub.m_hub_port;
263 m_hub_path = hub.m_hub_path; 267 m_hub_path = hub.m_hub_path;
@@ -284,7 +288,8 @@ void GVOHub::free_members(void) @@ -284,7 +288,8 @@ void GVOHub::free_members(void)
284 } 288 }
285 289
286 // Remove lockfile 290 // Remove lockfile
287 - delete_samp_file(); 291 + std::string lockurl = get_hub_lockfile();
  292 + std::remove(lockurl.c_str());
288 293
289 // Return 294 // Return
290 return; 295 return;
@@ -301,13 +306,46 @@ void GVOHub::free_members(void) @@ -301,13 +306,46 @@ void GVOHub::free_members(void)
301 ***************************************************************************/ 306 ***************************************************************************/
302 void GVOHub::start_hub(void) 307 void GVOHub::start_hub(void)
303 { 308 {
304 - // Get socket  
305 - m_socket = get_socket();  
306 -  
307 - // Create SAMP file  
308 - create_samp_file(); 309 + // Prepare TCP/IP structure
  310 + struct sockaddr_in serv_addr;
  311 + std::memset(&serv_addr, 0, sizeof(serv_addr));
  312 + serv_addr.sin_family = AF_INET;
  313 + serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str());
  314 + serv_addr.sin_port = htons(gammalib::toint(m_hub_port));
  315 +
  316 + // Create Hub socket
  317 + m_socket = socket(AF_INET, SOCK_STREAM, 0);
  318 +
  319 + // Creation of hub main socket
  320 + if (m_socket < 0) {
  321 + std::string msg = "Unable to create Hub socket. Errno="+
  322 + gammalib::str(errno);
  323 + throw GException::runtime_error(G_START_HUB, msg);
  324 + }
  325 +
  326 + // Set hub main socket to allow multiple connections
  327 + int opt = 1;
  328 + if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0) {
  329 + std::string msg = "Unable to set Hub socket to multiple connections."
  330 + " Errno="+gammalib::str(errno);
  331 + throw GException::runtime_error(G_START_HUB, msg);
  332 + }
  333 + #ifdef SO_REUSEPORT
  334 + if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt)) < 0) {
  335 + std::string msg = "Unable to set Hub socket to multiple connections."
  336 + " Errno="+gammalib::str(errno);
  337 + throw GException::runtime_error(G_START_HUB, msg);
  338 + }
  339 + #endif
  340 +
  341 + // Server socket is opened. Now, bind it to the port, with family etc.
  342 + if (bind(m_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
  343 + std::string msg = "Unable to bind Hub socket to server socket. Errno="+
  344 + gammalib::str(errno);
  345 + throw GException::runtime_error(G_START_HUB, msg);
  346 + }
309 347
310 - // Start listening for the clients: 5 requests simultaneously pending 348 + // Now start listening for the clients: 5 requests simultaneously pending
311 // at maximum 349 // at maximum
312 if (listen(m_socket, 5) < 0) { 350 if (listen(m_socket, 5) < 0) {
313 std::string msg = "Unable to start listening on Hub socket. Errno="+ 351 std::string msg = "Unable to start listening on Hub socket. Errno="+
@@ -323,7 +361,7 @@ void GVOHub::start_hub(void) @@ -323,7 +361,7 @@ void GVOHub::start_hub(void)
323 while (1) { 361 while (1) {
324 362
325 // Accept connection from the client 363 // Accept connection from the client
326 - int socket = accept(m_socket, (struct sockaddr *)&cli_addr, &clilen); 364 + socklen_t socket = accept(m_socket, (struct sockaddr *)&cli_addr, &clilen);
327 if (socket < 0) { 365 if (socket < 0) {
328 std::string msg = "Client connection to socket not accepted."; 366 std::string msg = "Client connection to socket not accepted.";
329 throw GException::runtime_error(G_START_HUB, msg); 367 throw GException::runtime_error(G_START_HUB, msg);
@@ -347,9 +385,6 @@ void GVOHub::start_hub(void) @@ -347,9 +385,6 @@ void GVOHub::start_hub(void)
347 close(m_socket); 385 close(m_socket);
348 m_socket = -1; 386 m_socket = -1;
349 387
350 - // Delete SAMP file  
351 - delete_samp_file();  
352 -  
353 // Return 388 // Return
354 return; 389 return;
355 } 390 }
@@ -395,11 +430,12 @@ void GVOHub::handle_request(const socklen_t&amp; sock) @@ -395,11 +430,12 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
395 430
396 // Extract response into an XML object 431 // Extract response into an XML object
397 GXml xml; 432 GXml xml;
  433 +
398 size_t start = message.find("<?xml"); 434 size_t start = message.find("<?xml");
399 if (start != std::string::npos) { 435 if (start != std::string::npos) {
400 xml = GXml(message.substr(start, std::string::npos)); 436 xml = GXml(message.substr(start, std::string::npos));
401 } 437 }
402 - 438 +
403 // Get methodName value 439 // Get methodName value
404 std::string method_called; 440 std::string method_called;
405 const GXmlNode* node = xml.element("methodCall > methodName"); 441 const GXmlNode* node = xml.element("methodCall > methodName");
@@ -446,11 +482,18 @@ void GVOHub::handle_request(const socklen_t&amp; sock) @@ -446,11 +482,18 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
446 else if (method_called.compare("samp.hub.getMetadata") == 0) { 482 else if (method_called.compare("samp.hub.getMetadata") == 0) {
447 request_get_metadata(xml, sock); 483 request_get_metadata(xml, sock);
448 } 484 }
  485 + else if (method_called.compare("table.load.votable") == 0) {
  486 + request_ping(sock);
  487 + }
449 else if (method_called.compare("samp.hub.notify") == 0) { 488 else if (method_called.compare("samp.hub.notify") == 0) {
450 request_ping(sock); 489 request_ping(sock);
451 } 490 }
452 else if (method_called.compare("samp.hub.notifyAll") == 0) { 491 else if (method_called.compare("samp.hub.notifyAll") == 0) {
453 - request_ping(sock); 492 + #if defined(G_CONSOLE_DUMP)
  493 + std::cout << "==========================================" << std::endl;
  494 + std::cout << "samp.hub.notifyAll" << std::endl;
  495 + #endif
  496 + broadcast(xml, sock);
454 } 497 }
455 else if (method_called.compare("samp.hub.call") == 0) { 498 else if (method_called.compare("samp.hub.call") == 0) {
456 request_ping(sock); 499 request_ping(sock);
@@ -561,7 +604,7 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock) @@ -561,7 +604,7 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock)
561 response.append(" </member>\n"); 604 response.append(" </member>\n");
562 response.append(" <member>\n"); 605 response.append(" <member>\n");
563 response.append(" <name>samp.url-translator</name>\n"); 606 response.append(" <name>samp.url-translator</name>\n");
564 - response.append(" <value>"+hub_url()+"</value>\n"); 607 + response.append(" <value>"+m_hub_url+"</value>\n");
565 response.append(" </member>\n"); 608 response.append(" </member>\n");
566 response.append(" </struct></value></param>\n"); 609 response.append(" </struct></value></param>\n");
567 response.append("</params>\n"); 610 response.append("</params>\n");
@@ -743,7 +786,7 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml, @@ -743,7 +786,7 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml,
743 if (i != -1) { 786 if (i != -1) {
744 787
745 // Get callback URL 788 // Get callback URL
746 - //std::string client_url = get_callback_url(xml); 789 + std::string client_url = get_callback_url(xml);
747 790
748 // Set callback URL 791 // Set callback URL
749 m_clients[i].url = get_callback_url(xml); 792 m_clients[i].url = get_callback_url(xml);
@@ -869,9 +912,8 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so @@ -869,9 +912,8 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so
869 912
870 // Declare message 913 // Declare message
871 std::string msg = ""; 914 std::string msg = "";
872 -  
873 // Set response 915 // Set response
874 - msg.append("<?xml version=\'1.0\' encoding=\"UTF-8\"?>\n"); 916 + msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
875 msg.append("<methodResponse>\n"); 917 msg.append("<methodResponse>\n");
876 msg.append("<params>\n"); 918 msg.append("<params>\n");
877 msg.append(" <param><value><array><data>\n"); 919 msg.append(" <param><value><array><data>\n");
@@ -890,7 +932,6 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so @@ -890,7 +932,6 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so
890 msg.append(" </data></array></value></param>\n"); 932 msg.append(" </data></array></value></param>\n");
891 msg.append("</params>\n"); 933 msg.append("</params>\n");
892 msg.append("</methodResponse>\n"); 934 msg.append("</methodResponse>\n");
893 -  
894 // Post response 935 // Post response
895 post_string(msg, sock); 936 post_string(msg, sock);
896 937
@@ -915,29 +956,16 @@ void GVOHub::request_get_subscribed_clients(const GXml&amp; xml, const socklen_t&amp; so @@ -915,29 +956,16 @@ void GVOHub::request_get_subscribed_clients(const GXml&amp; xml, const socklen_t&amp; so
915 std::cout << "GVOHub::request_get_subscribed_clients" << std::endl; 956 std::cout << "GVOHub::request_get_subscribed_clients" << std::endl;
916 #endif 957 #endif
917 958
918 -/*  
919 - std::string buffer;  
920 - const int n = 1000;  
921 - char line[n];  
922 - FILE* fptr = fopen("SAMP-registered.txt", "r");  
923 - if (fptr != NULL) {  
924 - while (fgets(line, n, fptr) != NULL) {  
925 -  
926 - // Convert line to C++ string  
927 - std::string cline = std::string(line); 959 + // Declare message
  960 + std::string msg = "";
928 961
929 - // Check for secret key  
930 - if (cline.compare(0, 10, "Registered") == 0) {  
931 - buffer = gammalib::strip_chars(cline.substr(10, std::string::npos), "\r\n");  
932 - }  
933 - }  
934 -  
935 - // Closes file  
936 - fclose(fptr);  
937 -*/ 962 + msg.append("<?xml version=\'1.0\' encoding=\"UTF-8\"?>\n");
  963 + msg.append("<methodResponse>\n");
  964 + msg.append("<params>\n");
  965 + msg.append(" <param><value><struct><member><name>c0</name><value><struct></struct></value></member><member><name>gammalib_hub</name><value><struct></struct></value></member></struct></value></param></params></methodResponse>");
938 966
939 - // Post void message  
940 - post_samp_void(sock); 967 + // Post response
  968 + post_string(msg, sock);
941 969
942 // Return 970 // Return
943 return; 971 return;
@@ -1079,6 +1107,51 @@ void GVOHub::request_get_metadata(const GXml&amp; xml, const socklen_t&amp; sock) @@ -1079,6 +1107,51 @@ void GVOHub::request_get_metadata(const GXml&amp; xml, const socklen_t&amp; sock)
1079 return; 1107 return;
1080 } 1108 }
1081 1109
  1110 +/***********************************************************************//**
  1111 + * @brief Broadcasts a message
  1112 + *
  1113 + * @param[in] xml XML message sent by client.
  1114 + * @param[in] sock Socket.
  1115 + *
  1116 + * Broadcasts an image to every registered client.
  1117 + ***************************************************************************/
  1118 +void GVOHub::broadcast(const GXml& xml, const socklen_t& sock)
  1119 +{
  1120 + // Header
  1121 +
  1122 + // Get client index
  1123 + int i = get_client_index(xml);
  1124 +
  1125 + // Get message mtype
  1126 + std::string mtype = get_mtype(xml);
  1127 + #if defined(G_CONSOLE_DUMP)
  1128 + std::cout<<"mtype is: " +mtype + " i value: " + gammalib::str(i)<<std::endl;
  1129 + #endif
  1130 + post_samp_void(sock);
  1131 +
  1132 + if (mtype == "image.load.fits") {
  1133 + #if defined(G_CONSOLE_DUMP)
  1134 + std::cout<<"notifying image.load.fits"<<std::endl;
  1135 + #endif
  1136 +
  1137 + // Send notifications
  1138 + send_notifications("image.load.fits",m_clients[i].reference,xml);
  1139 + }
  1140 +
  1141 + if (mtype == "table.load.votable") {
  1142 +
  1143 + // Send notifications
  1144 + send_notifications("table.load.votable",m_clients[i].reference,xml);
  1145 + }
  1146 +
  1147 + #if defined(G_CONSOLE_DUMP)
  1148 + std::cout<<"Returning from broadcast function"<<std::endl;
  1149 + #endif
  1150 +
  1151 + // Return
  1152 + return;
  1153 +
  1154 +}
1082 1155
1083 /***********************************************************************//** 1156 /***********************************************************************//**
1084 * @brief Handles Hub shutdown requests 1157 * @brief Handles Hub shutdown requests
@@ -1408,11 +1481,14 @@ std::string GVOHub::get_hub_lockfile(void) const @@ -1408,11 +1481,14 @@ std::string GVOHub::get_hub_lockfile(void) const
1408 * @param[in] method Name of the method 1481 * @param[in] method Name of the method
1409 * @param[in] client Reference of the client 1482 * @param[in] client Reference of the client
1410 * 1483 *
1411 - * The method send notifications to all registered clients that request so. 1484 + * Send notifications to all registered clients that request so.
1412 ***************************************************************************/ 1485 ***************************************************************************/
1413 void GVOHub::send_notifications(const std::string& method, 1486 void GVOHub::send_notifications(const std::string& method,
1414 const std::string& client) 1487 const std::string& client)
1415 { 1488 {
  1489 + #if defined(G_CONSOLE_DUMP)
  1490 + std::cout << "GVOHub::send_notifications 1st form" << std::endl;
  1491 + #endif
1416 // Loop over all clients 1492 // Loop over all clients
1417 for (int i = 0; i < m_clients.size(); ++i) { 1493 for (int i = 0; i < m_clients.size(); ++i) {
1418 1494
@@ -1459,7 +1535,7 @@ void GVOHub::send_notifications(const std::string&amp; method, @@ -1459,7 +1535,7 @@ void GVOHub::send_notifications(const std::string&amp; method,
1459 notify(m_clients[i].url, msg); 1535 notify(m_clients[i].url, msg);
1460 1536
1461 } 1537 }
1462 - 1538 +
1463 // Unregister 1539 // Unregister
1464 else if (method == "samp.hub.event.unregister") { 1540 else if (method == "samp.hub.event.unregister") {
1465 1541
@@ -1579,7 +1655,7 @@ void GVOHub::send_notifications(const std::string&amp; method, @@ -1579,7 +1655,7 @@ void GVOHub::send_notifications(const std::string&amp; method,
1579 // Post notification 1655 // Post notification
1580 notify(m_clients[i].url, msg); 1656 notify(m_clients[i].url, msg);
1581 1657
1582 - } // endelse: metadata 1658 + } // endelse: metadata
1583 1659
1584 } // endif: method was requested one 1660 } // endif: method was requested one
1585 1661
@@ -1590,13 +1666,135 @@ void GVOHub::send_notifications(const std::string&amp; method, @@ -1590,13 +1666,135 @@ void GVOHub::send_notifications(const std::string&amp; method,
1590 // Return 1666 // Return
1591 return; 1667 return;
1592 } 1668 }
  1669 +/***********************************************************************//**
  1670 + * @brief Send notifications
  1671 + *
  1672 + * @param[in] method Name of the method
  1673 + * @param[in] client Reference of the client
  1674 + * @param[in] xml message sent by the client
  1675 + *
  1676 + * Send notifications to all registered clients that request so.
  1677 + ***************************************************************************/
  1678 +void GVOHub::send_notifications(const std::string& method,
  1679 + const std::string& client,
  1680 + const GXml& xml)
  1681 +{
  1682 + // Debug: dump information to console
  1683 + #if defined(G_CONSOLE_DUMP)
  1684 + std::cout << "GVOHub::send_notifications 2nd form" << std::endl;
  1685 + std::cout << "GVOHub::send_notifications "+method << std::endl;
  1686 + #endif
  1687 +
  1688 + // Loop over all clients
  1689 + for (int i = 0; i < m_clients.size(); ++i) {
  1690 +
  1691 + // Loop over all methods
  1692 + for (int j = 0; j < m_clients[i].subscriptions.size(); ++j) {
  1693 +
  1694 + // Continue only if method matches
  1695 + if (method == m_clients[i].subscriptions[j]) {
  1696 +
  1697 + // Declare notification
  1698 + std::string msg = "";
  1699 +
  1700 + // Image loading
  1701 + if (method == "image.load.fits") {
  1702 +
  1703 + // Debug: dump information to console
  1704 + #if defined(G_CONSOLE_DUMP)
  1705 + std::cout << "GVOHub:: Preparing broadcast message" << std::endl;
  1706 + #endif
  1707 +
  1708 + // Declare value
  1709 + std::string value = "";
  1710 +
  1711 + // Search for value of specified member
  1712 + const GXmlNode* node = xml.element("methodCall > params > param[2] > value > struct > member > value > struct");
  1713 + #if defined(G_CONSOLE_DUMP)
  1714 + std::cout << "Searching url value" << std::endl;
  1715 + #endif
  1716 + if (node != NULL) {
  1717 + #if defined(G_CONSOLE_DUMP)
  1718 + std::cout << "Node found" << std::endl;
  1719 + #endif
  1720 + int num = node->elements("member");
  1721 + for (int i = 0; i < num; ++i) {
  1722 + const GXmlNode* member = node->element("member", i);
  1723 + std::string one_name;
  1724 + std::string one_value;
  1725 + get_name_value_pair(member, one_name, one_value);
  1726 + #if defined(G_CONSOLE_DUMP)
  1727 + std::cout << "name: "+one_name << std::endl;
  1728 + #endif
  1729 + if (one_name == "url") {
  1730 + value = one_value;
  1731 + break;
  1732 + }
  1733 + }
  1734 + } else {
  1735 + #if defined(G_CONSOLE_DUMP)
  1736 + std::cout << "Node not found" << std::endl;
  1737 + #endif
  1738 + }
  1739 +
  1740 + // Set response for image.load.fits
  1741 + msg.append("<?xml version=\"1.0\"?>\n");
  1742 + msg.append("<methodCall>\n");
  1743 + msg.append("<methodName>samp.client.receiveNotification</methodName>\n");
  1744 + msg.append("<params>\n");
  1745 + msg.append(" <param><value>");
  1746 + msg.append(m_clients[i].private_key);
  1747 + msg.append("</value></param>\n");
  1748 + msg.append(" <param><value>");
  1749 + msg.append(m_hub_id);
  1750 + msg.append("</value></param>\n");
  1751 + msg.append(" <param><value><struct>\n");
  1752 + msg.append(" <member>\n");
  1753 + msg.append(" <name>samp.mtype</name>\n");
  1754 + msg.append(" <value>image.load.fits</value>\n");
  1755 + msg.append(" </member>\n");
  1756 + msg.append(" <member>\n");
  1757 + msg.append(" <name>samp.params</name>\n");
  1758 + msg.append(" <value><struct>\n");
  1759 + msg.append(" <member>\n");
  1760 + msg.append(" <name>name</name>\n");
  1761 + msg.append(" <value>Gammalib_shared_fits</value>\n");
  1762 + msg.append(" </member>\n");
  1763 + msg.append(" <member>\n");
  1764 + msg.append(" <name>image-id</name>\n");
  1765 + msg.append(" <value>Gammalib_shared_fits_id</value>\n");
  1766 + msg.append(" </member>\n");
  1767 + msg.append(" <member>\n");
  1768 + msg.append(" <name>url</name>\n");
  1769 + msg.append(" <value>"+value+"</value>\n");
  1770 + msg.append(" </member>\n");
  1771 + msg.append(" </struct></value>\n");
  1772 + msg.append(" </member>\n");
  1773 + msg.append(" </struct></value></param>\n");
  1774 + msg.append("</params>\n");
  1775 + msg.append("</methodCall>\n");
  1776 + #if defined(G_CONSOLE_DUMP)
  1777 + std::cout << msg << std::endl;
  1778 + #endif
1593 1779
  1780 + // Post notification
  1781 + notify(m_clients[i].url, msg);
  1782 +
  1783 + }
  1784 + } // endif: method was requested one
  1785 +
  1786 + } // endfor: looped over all methods
  1787 +
  1788 + } // endfor: looped over all clients
  1789 +
  1790 + // Return
  1791 + return;
  1792 +}
1594 1793
1595 /***********************************************************************//** 1794 /***********************************************************************//**
1596 - * @brief Create the lockfile 1795 + * @brief Creates the lockfile, fill it
1597 * 1796 *
1598 - * Creates the SAMP lockfile and fill it with information. Implements IVOA  
1599 - * standard REC-SAMP-1.3-20120411. 1797 + * Implements IVOA standard REC-SAMP-1.3-20120411.
1600 ***************************************************************************/ 1798 ***************************************************************************/
1601 void GVOHub::create_samp_file(void) const 1799 void GVOHub::create_samp_file(void) const
1602 { 1800 {
@@ -1613,7 +1811,7 @@ void GVOHub::create_samp_file(void) const @@ -1613,7 +1811,7 @@ void GVOHub::create_samp_file(void) const
1613 fprintf(fptr, "# SAMP lockfile\n"); 1811 fprintf(fptr, "# SAMP lockfile\n");
1614 fprintf(fptr, "# Required keys:\n"); 1812 fprintf(fptr, "# Required keys:\n");
1615 fprintf(fptr, "samp.secret=%s\n", m_secret.c_str()); 1813 fprintf(fptr, "samp.secret=%s\n", m_secret.c_str());
1616 - fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", hub_url().c_str()); 1814 + fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", m_hub_url.c_str());
1617 fprintf(fptr, "samp.profile.version=%s\n", m_version.c_str()); 1815 fprintf(fptr, "samp.profile.version=%s\n", m_version.c_str());
1618 fprintf(fptr, "# Info stored by hub for some private reason:\n"); 1816 fprintf(fptr, "# Info stored by hub for some private reason:\n");
1619 fprintf(fptr, "gammalib.hubid=%s\n", m_hub_id.c_str()); 1817 fprintf(fptr, "gammalib.hubid=%s\n", m_hub_id.c_str());
@@ -1629,87 +1827,6 @@ void GVOHub::create_samp_file(void) const @@ -1629,87 +1827,6 @@ void GVOHub::create_samp_file(void) const
1629 1827
1630 1828
1631 /***********************************************************************//** 1829 /***********************************************************************//**
1632 - * @brief Delete the lockfile  
1633 - *  
1634 - * Deletes the SAMP lockfile on disk.  
1635 - ***************************************************************************/  
1636 -void GVOHub::delete_samp_file(void) const  
1637 -{  
1638 - // Get lockfile URL  
1639 - std::string lockurl = get_hub_lockfile();  
1640 -  
1641 - // Delete lockfile  
1642 - std::remove(lockurl.c_str());  
1643 -  
1644 - // Return  
1645 - return;  
1646 -}  
1647 -  
1648 -  
1649 -/***********************************************************************//**  
1650 - * @brief Get Hub socket  
1651 - *  
1652 - * @return Hub socket (-1 if no socket was found).  
1653 - *  
1654 - * Returns Hub socket. Starting from an initial port of 2526 the method  
1655 - * searches for the next free port and binds it to a socket.  
1656 - ***************************************************************************/  
1657 -int GVOHub::get_socket(void)  
1658 -{  
1659 - // Initialise socket, port and socket address structure  
1660 - int sock = -1;  
1661 - int port = 2526;  
1662 - struct sockaddr_in serv_addr;  
1663 -  
1664 - // Loop over 100 ports at most  
1665 - for (int i = 0; i < 100; ++i) {  
1666 -  
1667 - // Clean TCP/IP structure  
1668 - std::memset(&serv_addr, 0, sizeof(serv_addr));  
1669 -  
1670 - // Set TCP/IP structure  
1671 - serv_addr.sin_family = AF_INET;  
1672 - serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str());  
1673 - serv_addr.sin_port = htons(port);  
1674 -  
1675 - // Create Hub socket  
1676 - sock = socket(AF_INET, SOCK_STREAM, 0);  
1677 -  
1678 - // Creation of hub main socket  
1679 - if (sock < 0) {  
1680 - std::string msg = "Unable to create Hub socket. Errno="+  
1681 - gammalib::str(errno);  
1682 - throw GException::runtime_error(G_START_SOCKET, msg);  
1683 - }  
1684 -  
1685 - // Now bind socket to the address and port  
1686 - if (bind(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {  
1687 - if (errno == EADDRINUSE) {  
1688 - port++;  
1689 - close(sock);  
1690 - }  
1691 - else {  
1692 - std::string msg = "Unable to bind Hub socket to address "+  
1693 - m_hub_host+":"+gammalib::str(port)+  
1694 - ". Errno="+gammalib::str(errno);  
1695 - throw GException::runtime_error(G_START_HUB, msg);  
1696 - }  
1697 - }  
1698 - else {  
1699 - break;  
1700 - }  
1701 -  
1702 - } // endfor: looped over ports  
1703 -  
1704 - // Store port as string  
1705 - m_hub_port = gammalib::str(port);  
1706 -  
1707 - // Return socket  
1708 - return sock;  
1709 -}  
1710 -  
1711 -  
1712 -/***********************************************************************//**  
1713 * @brief Post string content to client 1830 * @brief Post string content to client
1714 * 1831 *
1715 * @param[in] content String content to post. 1832 * @param[in] content String content to post.
@@ -1948,24 +2065,6 @@ void GVOHub::notify(const std::string&amp; url, @@ -1948,24 +2065,6 @@ void GVOHub::notify(const std::string&amp; url,
1948 } 2065 }
1949 } while (!done); 2066 } while (!done);
1950 2067
1951 - /*  
1952 - // Declare response  
1953 - std::string response = "";  
1954 -  
1955 - // Read buffer until it is empty  
1956 - char buffer[1001];  
1957 - int timeout = 1000; // Initial timeout is 1 sec  
1958 - int n = 0;  
1959 - do {  
1960 - n = gammalib::recv(socket, buffer, 1000, 0, timeout);  
1961 - if (n > 0) {  
1962 - buffer[n+1] = '\0';  
1963 - response.append(std::string(buffer));  
1964 - }  
1965 - timeout = 10; // The timeout now is 0.01 sec  
1966 - } while (n > 0);  
1967 - */  
1968 -  
1969 // Close socket 2068 // Close socket
1970 close(socket); 2069 close(socket);
1971 2070
@@ -1994,21 +2093,61 @@ std::string GVOHub::random_string(const size_t&amp; length) const @@ -1994,21 +2093,61 @@ std::string GVOHub::random_string(const size_t&amp; length) const
1994 // Return string 2093 // Return string
1995 return str; 2094 return str;
1996 } 2095 }
  2096 +/***********************************************************************//**
  2097 + * @brief Extract mtype from XML request
  2098 + *
  2099 + * @param[in] xml XML message sent by client.
  2100 + *
  2101 + * Extracts the mtype identifying calling message from the XML request.
  2102 + ***************************************************************************/
  2103 +std::string GVOHub::get_mtype(const GXml& xml) const
  2104 +{
  2105 + // Header
  2106 + #if defined(G_CONSOLE_DUMP)
  2107 + std::cout << "GVOHub::get_mtype" << std::endl;
  2108 + #endif
1997 2109
  2110 + // Initialise response
  2111 + std::string client_key = "";
  2112 +
  2113 + // Get the client's private key
  2114 + const GXmlNode* node = xml.element("methodCall > params > param > value");
  2115 + if (node != NULL) {
  2116 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  2117 + if (text != NULL) {
  2118 + client_key = text->text();
  2119 + }
  2120 + }
1998 2121
  2122 + // Return key
  2123 + return client_key;
  2124 +}
1999 /***********************************************************************//** 2125 /***********************************************************************//**
2000 - * @brief Return Hub URL 2126 + * @brief Extract client destination from XML request
2001 * 2127 *
2002 - * @return Hub URL. 2128 + * @param[in] xml XML message sent by client.
2003 * 2129 *
2004 - * Returns the XML-RPC endpoint for communication with the hub. 2130 + * Extracts identifier of destination client from the XML request.
2005 ***************************************************************************/ 2131 ***************************************************************************/
2006 -std::string GVOHub::hub_url(void) const 2132 +std::string GVOHub::get_destination(const GXml& xml) const
2007 { 2133 {
2008 - // Set Hub URL  
2009 - std::string hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path; 2134 + // Header
  2135 + #if defined(G_CONSOLE_DUMP)
  2136 + std::cout << "GVOHub::get_mtype" << std::endl;
  2137 + #endif
2010 2138
2011 - // Return Hub URL  
2012 - return (hub_url);  
2013 -} 2139 + // Initialise response
  2140 + std::string client_key = "";
  2141 +
  2142 + // Get the client's private key
  2143 + const GXmlNode* node = xml.element("methodCall > params > param > value");
  2144 + if (node != NULL) {
  2145 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  2146 + if (text != NULL) {
  2147 + client_key = text->text();
  2148 + }
  2149 + }
2014 2150
  2151 + // Return key
  2152 + return client_key;
  2153 +}