Commit def74ccbcb555ecdaf5b55d714c43aed9b7f5282

Authored by Jürgen Knödlseder
1 parent b76e4481

Put back code in GVOHub that got erased during the last code merge.

include/GVOHub.hpp
... ... @@ -45,8 +45,8 @@ class GXmlNode;
45 45 *
46 46 * @brief VO SAMP Hub class
47 47 *
48   - * This class implements a SAMP hub for exchanges through VO-compatible
49   - * applications.
  48 + * This class implements a SAMP hub to support the interoperability of
  49 + * Virtual Observatory applications.
50 50 ***************************************************************************/
51 51 class GVOHub : public GBase {
52 52  
... ... @@ -65,7 +65,6 @@ public:
65 65 std::string classname(void) const;
66 66 void start(void);
67 67 std::string print(const GChatter& chatter = NORMAL) const;
68   -
69 68  
70 69 protected:
71 70 // Protected methods
... ... @@ -108,7 +107,6 @@ protected:
108 107 std::string get_callback_url(const GXml& xml) const;
109 108 std::string get_hub_lockfile(void) const;
110 109 std::string get_mtype(const GXml& xml) const;
111   - std::string get_destination(const GXml& xml) const;
112 110  
113 111 // Client structure
114 112 struct client {
... ... @@ -128,6 +126,8 @@ protected:
128 126  
129 127 // Low-level methods
130 128 void create_samp_file(void) const;
  129 + void delete_samp_file(void) const;
  130 + int get_socket(void);
131 131 void post_samp_ok(const socklen_t& sock) const;
132 132 void post_samp_void(const socklen_t& sock) const;
133 133 void post_string(const std::string& content,
... ... @@ -143,16 +143,16 @@ protected:
143 143 void notify_image_load(const client& client,
144 144 const GXml& xml);
145 145 std::string random_string(const size_t& length) const;
  146 + std::string hub_url(void) const;
146 147  
147 148 // Protected members
148 149 std::string m_secret; //!< Secret Hub key
149   - std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub
150 150 std::string m_hub_host; //!< Hub host
151 151 std::string m_hub_port; //!< Hub port
152 152 std::string m_hub_path; //!< Hub path
153 153 std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub
154 154 std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others
155   - socklen_t m_socket; //!< Hub socket
  155 + int m_socket; //!< Hub socket
156 156 bool m_shutdown; //!< Shutdown request
157 157 std::vector<client> m_clients; //!< Clients
158 158 };
... ...
src/vo/GVOHub.cpp
... ... @@ -49,6 +49,7 @@
49 49  
50 50 /* __ Method name definitions ____________________________________________ */
51 51 #define G_START_HUB "GVOHub::start_hub()"
  52 +#define G_GET_SOCKET "GVOHub::get_socket()"
52 53  
53 54 /* __ Macros _____________________________________________________________ */
54 55  
... ... @@ -182,9 +183,6 @@ GVOHub* GVOHub::clone(void) const
182 183 ***************************************************************************/
183 184 void GVOHub::start(void)
184 185 {
185   - // Create SAMP file
186   - create_samp_file();
187   -
188 186 // Start Hub
189 187 start_hub();
190 188  
... ... @@ -213,7 +211,7 @@ std::string GVOHub::print(const GChatter&amp; chatter) const
213 211 // Append Hub information
214 212 result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id);
215 213 result.append("\n"+gammalib::parformat("Hub key")+m_secret);
216   - result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url);
  214 + result.append("\n"+gammalib::parformat("Hub URL")+hub_url());
217 215 result.append("\n"+gammalib::parformat("Hub host")+m_hub_host);
218 216 result.append("\n"+gammalib::parformat("Hub port")+m_hub_port);
219 217 result.append("\n"+gammalib::parformat("Hub path")+m_hub_path);
... ... @@ -243,7 +241,6 @@ void GVOHub::init_members(void)
243 241 m_hub_host = "127.0.0.1";
244 242 m_hub_port = "2526";
245 243 m_hub_path = "xmlrpc";
246   - m_hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path;
247 244 m_version = "1.3";
248 245 m_hub_id = "gammalib_hub";
249 246 m_socket = -1; // Signals no socket
... ... @@ -264,7 +261,6 @@ void GVOHub::copy_members(const GVOHub&amp; hub)
264 261 {
265 262 // Copy members
266 263 m_secret = hub.m_secret;
267   - m_hub_url = hub.m_hub_url;
268 264 m_hub_host = hub.m_hub_host;
269 265 m_hub_port = hub.m_hub_port;
270 266 m_hub_path = hub.m_hub_path;
... ... @@ -291,8 +287,7 @@ void GVOHub::free_members(void)
291 287 }
292 288  
293 289 // Remove lockfile
294   - std::string lockurl = get_hub_lockfile();
295   - std::remove(lockurl.c_str());
  290 + delete_samp_file();
296 291  
297 292 // Return
298 293 return;
... ... @@ -309,46 +304,13 @@ void GVOHub::free_members(void)
309 304 ***************************************************************************/
310 305 void GVOHub::start_hub(void)
311 306 {
312   - // Prepare TCP/IP structure
313   - struct sockaddr_in serv_addr;
314   - std::memset(&serv_addr, 0, sizeof(serv_addr));
315   - serv_addr.sin_family = AF_INET;
316   - serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str());
317   - serv_addr.sin_port = htons(gammalib::toint(m_hub_port));
318   -
319   - // Create Hub socket
320   - m_socket = socket(AF_INET, SOCK_STREAM, 0);
321   -
322   - // Creation of hub main socket
323   - if (m_socket < 0) {
324   - std::string msg = "Unable to create Hub socket. Errno="+
325   - gammalib::str(errno);
326   - throw GException::runtime_error(G_START_HUB, msg);
327   - }
328   -
329   - // Set hub main socket to allow multiple connections
330   - int opt = 1;
331   - if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0) {
332   - std::string msg = "Unable to set Hub socket to multiple connections."
333   - " Errno="+gammalib::str(errno);
334   - throw GException::runtime_error(G_START_HUB, msg);
335   - }
336   - #ifdef SO_REUSEPORT
337   - if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt)) < 0) {
338   - std::string msg = "Unable to set Hub socket to multiple connections."
339   - " Errno="+gammalib::str(errno);
340   - throw GException::runtime_error(G_START_HUB, msg);
341   - }
342   - #endif
343   -
344   - // Server socket is opened. Now, bind it to the port, with family etc.
345   - if (bind(m_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
346   - std::string msg = "Unable to bind Hub socket to server socket. Errno="+
347   - gammalib::str(errno);
348   - throw GException::runtime_error(G_START_HUB, msg);
349   - }
  307 + // Get socket
  308 + m_socket = get_socket();
  309 +
  310 + // Create SAMP file
  311 + create_samp_file();
350 312  
351   - // Now start listening for the clients: 5 requests simultaneously pending
  313 + // Start listening for the clients: 5 requests simultaneously pending
352 314 // at maximum
353 315 if (listen(m_socket, 5) < 0) {
354 316 std::string msg = "Unable to start listening on Hub socket. Errno="+
... ... @@ -364,7 +326,7 @@ void GVOHub::start_hub(void)
364 326 while (1) {
365 327  
366 328 // Accept connection from the client
367   - socklen_t socket = accept(m_socket, (struct sockaddr *)&cli_addr, &clilen);
  329 + int socket = accept(m_socket, (struct sockaddr *)&cli_addr, &clilen);
368 330 if (socket < 0) {
369 331 std::string msg = "Client connection to socket not accepted.";
370 332 throw GException::runtime_error(G_START_HUB, msg);
... ... @@ -388,6 +350,9 @@ void GVOHub::start_hub(void)
388 350 close(m_socket);
389 351 m_socket = -1;
390 352  
  353 + // Delete SAMP file
  354 + delete_samp_file();
  355 +
391 356 // Return
392 357 return;
393 358 }
... ... @@ -433,12 +398,11 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
433 398  
434 399 // Extract response into an XML object
435 400 GXml xml;
436   -
437 401 size_t start = message.find("<?xml");
438 402 if (start != std::string::npos) {
439 403 xml = GXml(message.substr(start, std::string::npos));
440 404 }
441   -
  405 +
442 406 // Get methodName value
443 407 std::string method_called;
444 408 const GXmlNode* node = xml.element("methodCall > methodName");
... ... @@ -486,9 +450,6 @@ void GVOHub::handle_request(const socklen_t&amp; sock)
486 450 else if (method_called.compare("samp.hub.getMetadata") == 0) {
487 451 request_get_metadata(xml, sock);
488 452 }
489   - else if (method_called.compare("table.load.votable") == 0) {
490   - request_ping(sock);
491   - }
492 453 else if (method_called.compare("samp.hub.notify") == 0) {
493 454 request_ping(sock);
494 455 }
... ... @@ -604,7 +565,7 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock)
604 565 response.append(" </member>\n");
605 566 response.append(" <member>\n");
606 567 response.append(" <name>samp.url-translator</name>\n");
607   - response.append(" <value>"+m_hub_url+"</value>\n");
  568 + response.append(" <value>"+hub_url()+"</value>\n");
608 569 response.append(" </member>\n");
609 570 response.append(" </struct></value></param>\n");
610 571 response.append("</params>\n");
... ... @@ -816,9 +777,6 @@ void GVOHub::request_set_xml_rpc_callback(const GXml&amp; xml,
816 777 // Continue only if index is valid
817 778 if (i != -1) {
818 779  
819   - // Get callback URL
820   - std::string client_url = get_callback_url(xml);
821   -
822 780 // Set callback URL
823 781 m_clients[i].url = get_callback_url(xml);
824 782  
... ... @@ -947,6 +905,7 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so
947 905  
948 906 // Declare message
949 907 std::string msg = "";
  908 +
950 909 // Set response
951 910 msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
952 911 msg.append("<methodResponse>\n");
... ... @@ -967,12 +926,12 @@ void GVOHub::request_get_registered_clients(const GXml&amp; xml, const socklen_t&amp; so
967 926 msg.append(" </data></array></value></param>\n");
968 927 msg.append("</params>\n");
969 928 msg.append("</methodResponse>\n");
  929 +
970 930 // Post response
971 931 post_string(msg, sock);
972 932  
973 933 // Return
974 934 return;
975   -
976 935 }
977 936  
978 937  
... ... @@ -1530,9 +1489,10 @@ std::string GVOHub::get_hub_lockfile(void) const
1530 1489  
1531 1490  
1532 1491 /***********************************************************************//**
1533   - * @brief Creates the lockfile, fill it
  1492 + * @brief Create the lockfile
1534 1493 *
1535   - * Implements IVOA standard REC-SAMP-1.3-20120411.
  1494 + * Creates the SAMP lockfile and fill it with information. Implements IVOA
  1495 + * standard REC-SAMP-1.3-20120411.
1536 1496 ***************************************************************************/
1537 1497 void GVOHub::create_samp_file(void) const
1538 1498 {
... ... @@ -1549,7 +1509,7 @@ void GVOHub::create_samp_file(void) const
1549 1509 fprintf(fptr, "# SAMP lockfile\n");
1550 1510 fprintf(fptr, "# Required keys:\n");
1551 1511 fprintf(fptr, "samp.secret=%s\n", m_secret.c_str());
1552   - fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", m_hub_url.c_str());
  1512 + fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", hub_url().c_str());
1553 1513 fprintf(fptr, "samp.profile.version=%s\n", m_version.c_str());
1554 1514 fprintf(fptr, "# Info stored by hub for some private reason:\n");
1555 1515 fprintf(fptr, "gammalib.hubid=%s\n", m_hub_id.c_str());
... ... @@ -1565,6 +1525,87 @@ void GVOHub::create_samp_file(void) const
1565 1525  
1566 1526  
1567 1527 /***********************************************************************//**
  1528 + * @brief Delete the lockfile
  1529 + *
  1530 + * Deletes the SAMP lockfile on disk.
  1531 + ***************************************************************************/
  1532 +void GVOHub::delete_samp_file(void) const
  1533 +{
  1534 + // Get lockfile URL
  1535 + std::string lockurl = get_hub_lockfile();
  1536 +
  1537 + // Delete lockfile
  1538 + std::remove(lockurl.c_str());
  1539 +
  1540 + // Return
  1541 + return;
  1542 +}
  1543 +
  1544 +
  1545 +/***********************************************************************//**
  1546 + * @brief Get Hub socket
  1547 + *
  1548 + * @return Hub socket (-1 if no socket was found).
  1549 + *
  1550 + * Returns Hub socket. Starting from an initial port of 2526 the method
  1551 + * searches for the next free port and binds it to a socket.
  1552 + ***************************************************************************/
  1553 +int GVOHub::get_socket(void)
  1554 +{
  1555 + // Initialise socket, port and socket address structure
  1556 + int sock = -1;
  1557 + int port = 2526;
  1558 + struct sockaddr_in serv_addr;
  1559 +
  1560 + // Loop over 100 ports at most
  1561 + for (int i = 0; i < 100; ++i) {
  1562 +
  1563 + // Clean TCP/IP structure
  1564 + std::memset(&serv_addr, 0, sizeof(serv_addr));
  1565 +
  1566 + // Set TCP/IP structure
  1567 + serv_addr.sin_family = AF_INET;
  1568 + serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str());
  1569 + serv_addr.sin_port = htons(port);
  1570 +
  1571 + // Create Hub socket
  1572 + sock = socket(AF_INET, SOCK_STREAM, 0);
  1573 +
  1574 + // Creation of hub main socket
  1575 + if (sock < 0) {
  1576 + std::string msg = "Unable to create Hub socket. Errno="+
  1577 + gammalib::str(errno);
  1578 + throw GException::runtime_error(G_GET_SOCKET, msg);
  1579 + }
  1580 +
  1581 + // Now bind socket to the address and port
  1582 + if (bind(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
  1583 + if (errno == EADDRINUSE) {
  1584 + port++;
  1585 + close(sock);
  1586 + }
  1587 + else {
  1588 + std::string msg = "Unable to bind Hub socket to address "+
  1589 + m_hub_host+":"+gammalib::str(port)+
  1590 + ". Errno="+gammalib::str(errno);
  1591 + throw GException::runtime_error(G_GET_SOCKET, msg);
  1592 + }
  1593 + }
  1594 + else {
  1595 + break;
  1596 + }
  1597 +
  1598 + } // endfor: looped over ports
  1599 +
  1600 + // Store port as string
  1601 + m_hub_port = gammalib::str(port);
  1602 +
  1603 + // Return socket
  1604 + return sock;
  1605 +}
  1606 +
  1607 +
  1608 +/***********************************************************************//**
1568 1609 * @brief Post string content to client
1569 1610 *
1570 1611 * @param[in] content String content to post.
... ... @@ -2083,7 +2124,7 @@ std::string GVOHub::random_string(const size_t&amp; length) const
2083 2124 int pos;
2084 2125 while(str.size() != length) {
2085 2126 pos = ((rand() % (str.size() - 1)));
2086   - str.erase (pos, 1);
  2127 + str.erase(pos, 1);
2087 2128 }
2088 2129  
2089 2130 // Return string
... ... @@ -2123,31 +2164,17 @@ std::string GVOHub::get_mtype(const GXml&amp; xml) const
2123 2164  
2124 2165  
2125 2166 /***********************************************************************//**
2126   - * @brief Extract client destination from XML request
  2167 + * @brief Return Hub URL
2127 2168 *
2128   - * @param[in] xml XML message sent by client.
  2169 + * @return Hub URL.
2129 2170 *
2130   - * Extracts identifier of destination client from the XML request.
  2171 + * Returns the XML-RPC endpoint for communication with the hub.
2131 2172 ***************************************************************************/
2132   -std::string GVOHub::get_destination(const GXml& xml) const
  2173 +std::string GVOHub::hub_url(void) const
2133 2174 {
2134   - // Header
2135   - #if defined(G_CONSOLE_DUMP)
2136   - std::cout << "GVOHub::get_destination" << std::endl;
2137   - #endif
2138   -
2139   - // Initialise response
2140   - std::string client_key = "";
  2175 + // Set Hub URL
  2176 + std::string hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path;
2141 2177  
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   - }
2150   -
2151   - // Return key
2152   - return client_key;
  2178 + // Return Hub URL
  2179 + return (hub_url);
2153 2180 }
... ...