Commit 74530d3fa706d61af480d4c4d700010ba74ca111

Authored by Jürgen Knödlseder
2 parents 91fe979a 4977c847

Merge branch '1229-GVOHub' into integration

Conflicts:
	src/vo/GVOClient.cpp
	test/test_GVO.cpp
	test/test_GVO.hpp
configure.ac
... ... @@ -32,9 +32,9 @@
32 32 AC_INIT([gammalib], [1.0.0], [jurgen.knodlseder@irap.omp.eu], [gammalib])
33 33 AC_CONFIG_SRCDIR([src/support/GTools.cpp])
34 34 AC_CONFIG_MACRO_DIR([m4])
35   -AM_INIT_AUTOMAKE([gnu no-dependencies -Wno-portability subdir-objects])
  35 +#AM_INIT_AUTOMAKE([gnu no-dependencies -Wno-portability subdir-objects])
36 36 #AM_INIT_AUTOMAKE([gnu no-dependencies subdir-objects])
37   -#AM_INIT_AUTOMAKE([gnu no-dependencies -Wno-portability subdir-objects serial-tests])
  37 +AM_INIT_AUTOMAKE([gnu no-dependencies -Wno-portability subdir-objects serial-tests])
38 38 AC_CONFIG_HEADER([config.h])
39 39  
40 40  
... ...
include/GVOApp.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * GVOApp.hpp - VO SAMP Hub class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 by Thierry Louge *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software: you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation, either version 3 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + * This program is distributed in the hope that it will be useful, *
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15 + * GNU General Public License for more details. *
  16 + * *
  17 + * You should have received a copy of the GNU General Public License *
  18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19 + * *
  20 + ***************************************************************************/
  21 +/**
  22 + * @file GVOApp.hpp
  23 + * @brief SAMP hub class interface definition
  24 + * @author Thierry Louge
  25 + */
  26 +
  27 +#ifndef GVOAPP_HPP
  28 +#define GVOAPP_HPP
  29 +
  30 +/* __ Includes ___________________________________________________________ */
  31 +#include <string>
  32 +#include <list>
  33 +#include "GBase.hpp"
  34 +#include "GXml.hpp"
  35 +#include "GXmlNode.hpp"
  36 +
  37 +
  38 +/***********************************************************************//**
  39 + * @class GVOApp
  40 + *
  41 + * @brief VO SAMP Hub class
  42 + *
  43 + * This class implements a SAMP hub for exchanges
  44 + * through VO-compatible applications.
  45 + ***************************************************************************/
  46 +class GVOApp : public GBase {
  47 +
  48 +friend class GVOHub;
  49 +
  50 +public:
  51 + // Constructors and destructors
  52 + GVOApp(void);
  53 + GVOApp(const GVOApp& hub);
  54 + virtual ~GVOApp(void);
  55 +
  56 + // Operators
  57 + GVOApp& operator=(const GVOApp& hub);
  58 +
  59 + // Methods
  60 + void clear(void);
  61 + GVOApp* clone(void) const;
  62 + void start(void);
  63 + std::string print(const GChatter& chatter = NORMAL) const;
  64 +
  65 +protected:
  66 + // Protected methods
  67 + void init_members(void);
  68 + void copy_members(const GVOApp& client);
  69 + void free_members(void);
  70 + void init_app(void);
  71 + void start_app(void);
  72 + void post_string(const std::string& string) const;
  73 + std::string receive_string(void) const;
  74 + std::string get_response_value(const GXml& xml, const std::string& name) const;
  75 + void get_name_value_pair(const GXmlNode* node, std::string& name, std::string& value) const;
  76 +
  77 + // Protected data area
  78 + std::string m_name; //!< Client name
  79 + char m_id[32]; //!< Id assigned to client by the hub
  80 + std::list <std::string> registeredMethods; //!< Calls for which is registered the application.
  81 + //std::list<std::string>::iterator iterator_calls;
  82 +
  83 +};
  84 +
  85 +#endif /* GVOAPP_HPP */
... ...
include/GVOHub.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * GVOHub.hpp - VO SAMP Hub class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014-2015 by Thierry Louge *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software: you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation, either version 3 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + * This program is distributed in the hope that it will be useful, *
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15 + * GNU General Public License for more details. *
  16 + * *
  17 + * You should have received a copy of the GNU General Public License *
  18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19 + * *
  20 + ***************************************************************************/
  21 +/**
  22 + * @file GVOHub.hpp
  23 + * @brief SAMP hub class interface definition
  24 + * @author Thierry Louge
  25 + */
  26 +
  27 +#ifndef GVOHUB_HPP
  28 +#define GVOHUB_HPP
  29 +#define GVOHUB_NB_CLIENTS 5
  30 +#define GVOHUB_NB_METHODS 128
  31 +#define GVO_HUB_testing 1
  32 +
  33 +/* __ Includes ___________________________________________________________ */
  34 +#include <string>
  35 +#include <list>
  36 +#include <sys/socket.h>
  37 +#include <semaphore.h>
  38 +#include "GBase.hpp"
  39 +#include "GXml.hpp"
  40 +#include "GXmlNode.hpp"
  41 +#include "GVOApp.hpp"
  42 +
  43 +
  44 +/***********************************************************************//**
  45 + * @class GVOHub
  46 + *
  47 + * @brief VO SAMP Hub class
  48 + *
  49 + * This class implements a SAMP hub for exchanges
  50 + * through VO-compatible applications.
  51 + ***************************************************************************/
  52 +class GVOHub : public GBase {
  53 +
  54 +public:
  55 + // Constructors and destructors
  56 + GVOHub(void);
  57 + GVOHub(const GVOHub& hub);
  58 + virtual ~GVOHub(void);
  59 +
  60 + // Operators
  61 + GVOHub& operator=(const GVOHub& hub);
  62 +
  63 + // Methods
  64 + void clear(void);
  65 + GVOHub* clone(void) const;
  66 + std::string print(const GChatter& chatter = NORMAL) const;
  67 +
  68 +
  69 +protected:
  70 + // Protected methods
  71 + void init_members(void);
  72 + void copy_members(const GVOHub& client);
  73 + void free_members(void);
  74 + void create_samp_file(void);
  75 + void start_hub(void);
  76 + void register_service(const GXml& xml,const socklen_t& sock);
  77 + void ping_service(const socklen_t& sock);
  78 + void unregister(const GXml& xml,const socklen_t& sock);
  79 + void handle_request(const socklen_t& sock);
  80 + void register_metadata(const GXml& xml,const socklen_t& sock);
  81 + void set_xml_rpc_callback(const GXml& xml,const socklen_t& sock);
  82 + void get_registered_clients(const GXml& xml,const socklen_t& sock);
  83 + void get_subscribed_clients(const GXml& xml,const socklen_t& sock);
  84 + void get_metadata(const GXml& xml,const socklen_t& sock);
  85 + void get_subscriptions(const GXml& xml,const socklen_t& sock);
  86 + void declare_subscriptions(const GXml& xml,const socklen_t& sock);
  87 + void post_string(const std::string& content,const socklen_t& sock) const;
  88 + std::string receive_string(const socklen_t& sock) const;
  89 +
  90 + // Low-level methods
  91 + void post_string(const std::string& string) const;
  92 + std::string receive_string(void) const;
  93 + std::string get_response_value(const GXml& xml,
  94 + const std::string& name) const;
  95 + std::list<std::string> get_registrations(const GXml& xml,
  96 + const std::string& name) const;
  97 + std::list<std::string> get_clientid(const GXml& xml,
  98 + const std::string& name) const;
  99 + std::string get_callback_port(const GXml& xml,
  100 + const std::string& name) const;
  101 + void get_name_value_pair(const GXmlNode* node,
  102 + std::string& name,
  103 + std::string& value) const;
  104 + std::string get_hub_lockfile(void) const;
  105 + std::string random_string( size_t length );
  106 + void activate_callbacks(std::string method,char cl_id[31]);
  107 + void post_string_toclient(const std::string& content) const;
  108 +
  109 + // Protected members
  110 + std::string m_name; //!< Client name
  111 + std::string m_secret; //!< Secret Hub key
  112 + std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub
  113 + std::string m_hub_host; //!< Hub host (extracted from XML-RPC endpoint)
  114 + std::string m_hub_port; //!< Hub port (extracted from XML-RPC endpoint)
  115 + std::string m_version; //!< The version of the SAMP Standard Profile implemented by the hub
  116 + std::string m_client_key; //!< Private client key
  117 + std::string m_hub_id; //!< Hub identifier used by the hub when it sends message itself rather than forwarding from others
  118 + int m_socket; //!< Hub socket
  119 + int cback_socket; //!< Hub socket to callback clients
  120 + int m_nb_clients; //!< Number of already registered clients
  121 + typedef struct {
  122 + char private_key[16];
  123 + char name[32];
  124 + char reference[32];
  125 + char description[256];
  126 + char icon[32];
  127 + char documentation[32];
  128 + char affiliation[32];
  129 + char author_name[32];
  130 + char email[32];
  131 + char homepage[32];
  132 + char port[32];
  133 + char registered_methods[GVOHUB_NB_METHODS][GVOHUB_NB_METHODS]; //128 methods of 128 cars max.
  134 + } connected_shm;
  135 + typedef struct {
  136 + int registered;
  137 + sem_t lock;
  138 + connected_shm metadatas[GVOHUB_NB_CLIENTS];
  139 + } clients_descriptor;
  140 + clients_descriptor *reg_clients;
  141 + connected_shm *clients;
  142 + void* ptr_mem_partagee; //pointer to shm address
  143 + int shm_handler; //handler to shm
  144 +
  145 +};
  146 +
  147 +#endif /* GVOHUB_HPP */
... ...
include/GammaLib.hpp
... ... @@ -107,6 +107,8 @@
107 107  
108 108 /* __ VO module __________________________________________________________ */
109 109 #include "GVOClient.hpp"
  110 +#include "GVOHub.hpp"
  111 +#include "GVOApp.hpp"
110 112  
111 113 /* __ XSPEC module _______________________________________________________ */
112 114 #include "GArf.hpp"
... ...
include/Makefile.am
... ... @@ -62,6 +62,8 @@ pkginclude_HEADERS = GammaLib.hpp \
62 62 GXmlAttribute.hpp \
63 63 GXmlPI.hpp \
64 64 GVOClient.hpp \
  65 + GVOHub.hpp \
  66 + GVOApp.hpp \
65 67 GPha.hpp \
66 68 GArf.hpp \
67 69 GRmf.hpp \
... ...
pyext/GVOApp.i 0 → 100644
  1 +/***************************************************************************
  2 + * GVOApp.i - VO SAMP Hub class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2015 by Thierry Louge *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software: you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation, either version 3 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + * This program is distributed in the hope that it will be useful, *
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15 + * GNU General Public License for more details. *
  16 + * *
  17 + * You should have received a copy of the GNU General Public License *
  18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19 + * *
  20 + ***************************************************************************/
  21 +/**
  22 + * @file GVOApp.i
  23 + * @brief SAMP hub class interface definition
  24 + * @author Thierry Louge
  25 + */
  26 +%{
  27 +/* Put headers and other declarations here that are needed for compilation */
  28 +#include "GVOApp.hpp"
  29 +%}
  30 +
  31 +
  32 +/***********************************************************************//**
  33 + * @class GVOApp
  34 + *
  35 + * @brief VO Hub class
  36 + ***************************************************************************/
  37 +class GVOApp : public GBase {
  38 +
  39 +public:
  40 + // Constructors and destructors
  41 + GVOApp(void);
  42 + GVOApp(const GVOApp& hub);
  43 + virtual ~GVOApp(void);
  44 +
  45 + // Operators
  46 + GVOApp& operator=(const GVOApp& hub);
  47 +
  48 + // Methods
  49 + void clear(void);
  50 + GVOApp* clone(void) const;
  51 + void start(void);
  52 +};
  53 +
  54 +
  55 +/***********************************************************************//**
  56 + * @brief GVOApp class extension
  57 + ***************************************************************************/
  58 +%extend GVOApp {
  59 + GVOApp copy() {
  60 + return (*self);
  61 + }
  62 +};
  63 +
  64 +
... ...
pyext/GVOHub.i 0 → 100644
  1 +/***************************************************************************
  2 + * GVOHub.i - VO SAMP Hub class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 by Thierry Louge *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software: you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation, either version 3 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + * This program is distributed in the hope that it will be useful, *
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15 + * GNU General Public License for more details. *
  16 + * *
  17 + * You should have received a copy of the GNU General Public License *
  18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19 + * *
  20 + ***************************************************************************/
  21 +/**
  22 + * @file GVOHub.i
  23 + * @brief SAMP hub class interface definition
  24 + * @author Thierry Louge
  25 + */
  26 +%{
  27 +/* Put headers and other declarations here that are needed for compilation */
  28 +#include "GVOHub.hpp"
  29 +%}
  30 +
  31 +
  32 +/***********************************************************************//**
  33 + * @class GVOHub
  34 + *
  35 + * @brief VO Hub class
  36 + ***************************************************************************/
  37 +class GVOHub : public GBase {
  38 +public:
  39 + // Constructors and destructors
  40 + GVOHub(void);
  41 + GVOHub(const GVOHub& hub);
  42 + virtual ~GVOHub(void);
  43 +
  44 + // Methods
  45 + void clear(void);
  46 + GVOHub* clone(void) const;
  47 +};
  48 +
  49 +
  50 +/***********************************************************************//**
  51 + * @brief GVOHub class extension
  52 + ***************************************************************************/
  53 +%extend GVOHub {
  54 + GVOHub copy() {
  55 + return (*self);
  56 + }
  57 +};
  58 +
  59 +
... ...
pyext/gammalib/vo.i
1 1 /***************************************************************************
2 2 * vo.i - Virtual Observatory module *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2014 by Juergen Knoedlseder *
  4 + * copyright (C) 2014-2015 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -48,3 +48,5 @@
48 48  
49 49 /* __ Virtual Observatory module _________________________________________ */
50 50 %include "GVOClient.i"
  51 +%include "GVOHub.i"
  52 +%include "GVOApp.i"
... ...
src/vo/GVOApp.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GVOApp.hpp - VO SAMP Hub class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 by Thierry Louge *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software: you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation, either version 3 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + * This program is distributed in the hope that it will be useful, *
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15 + * GNU General Public License for more details. *
  16 + * *
  17 + * You should have received a copy of the GNU General Public License *
  18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19 + * *
  20 + ***************************************************************************/
  21 +/**
  22 + * @file GVOApp.cpp
  23 + * @brief VO Application connected to SAMP HUB class implementation
  24 + * @author Thierry Louge
  25 + */
  26 +
  27 +/* __ Includes ___________________________________________________________ */
  28 +#ifdef HAVE_CONFIG_H
  29 +#include <config.h>
  30 +#include <errno.h>
  31 +#endif
  32 +#include <cstdlib> // std::getenv() function
  33 +#include <cstdio> // std::fopen(), etc. functions
  34 +#include <cstring> // std::memset() function
  35 +#include <unistd.h> // close() function
  36 +#include "GVOApp.hpp"
  37 +#include "GException.hpp"
  38 +#include "GTools.hpp"
  39 +
  40 +/* __ Method name definitions ____________________________________________ */
  41 +
  42 +/* __ Macros _____________________________________________________________ */
  43 +
  44 +/* __ Coding definitions _________________________________________________ */
  45 +
  46 +/* __ Debug definitions __________________________________________________ */
  47 +
  48 +
  49 +/*==========================================================================
  50 + = =
  51 + = Constructors/destructors =
  52 + = =
  53 + ==========================================================================*/
  54 +
  55 +/***********************************************************************//**
  56 + * @brief Void constructor
  57 + ***************************************************************************/
  58 +GVOApp::GVOApp(void)
  59 +{
  60 + // Initialise members
  61 + init_members();
  62 +
  63 + // Return
  64 + return;
  65 +}
  66 +
  67 +
  68 +/***********************************************************************//**
  69 + * @brief Copy constructor
  70 + *
  71 + * @param[in] hub VO Hub.
  72 + ***************************************************************************/
  73 +GVOApp::GVOApp(const GVOApp& hub)
  74 +{
  75 + // Initialise members
  76 + init_members();
  77 +
  78 + // Copy members
  79 + copy_members(hub);
  80 +
  81 + // Return
  82 + return;
  83 +}
  84 +
  85 +
  86 +/***********************************************************************//**
  87 + * @brief Destructor
  88 + ***************************************************************************/
  89 +GVOApp::~GVOApp(void)
  90 +{
  91 +
  92 + // Return
  93 + return;
  94 +}
  95 +
  96 +
  97 +/*==========================================================================
  98 + = =
  99 + = Operators =
  100 + = =
  101 + ==========================================================================*/
  102 +
  103 +/***********************************************************************//**
  104 + * @brief Assignment operator
  105 + *
  106 + * @param[in] hub VO hub.
  107 + * @return VO hub.
  108 + ***************************************************************************/
  109 +GVOApp& GVOApp::operator=(const GVOApp& hub)
  110 +{
  111 + // Execute only if object is not identical
  112 + if (this != &hub) {
  113 +
  114 + // Free members
  115 + free_members();
  116 +
  117 + // Initialise members
  118 + init_members();
  119 +
  120 + // Copy members
  121 + copy_members(hub);
  122 +
  123 + } // endif: object was not identical
  124 +
  125 + // Return
  126 + return *this;
  127 +}
  128 +
  129 +
  130 +/*==========================================================================
  131 + = =
  132 + = Public methods =
  133 + = =
  134 + ==========================================================================*/
  135 +
  136 +/***********************************************************************//**
  137 + * @brief Clear object.
  138 + *
  139 + * Reset object to a clean initial state.
  140 + ***************************************************************************/
  141 +void GVOApp::clear(void)
  142 +{
  143 + // Free memory and initialise members
  144 + free_members();
  145 + init_members();
  146 +
  147 + // Return
  148 + return;
  149 +}
  150 +
  151 +
  152 +/***********************************************************************//**
  153 + * @brief Clone object
  154 + ***************************************************************************/
  155 +GVOApp* GVOApp::clone(void) const
  156 +{
  157 + // Clone client
  158 + return new GVOApp(*this);
  159 +}
  160 +
  161 +
  162 +/***********************************************************************//**
  163 + * @brief TBD
  164 + *
  165 + ***************************************************************************/
  166 +void GVOApp::start(void)
  167 +{
  168 + // Does nothing
  169 +
  170 + // Return
  171 + return;
  172 +}
  173 +
  174 +
  175 +/***********************************************************************//**
  176 + * @brief Print VO hub information
  177 + *
  178 + * @param[in] chatter Chattiness (defaults to NORMAL).
  179 + * @return String containing VO hub information
  180 + ***************************************************************************/
  181 +std::string GVOApp::print(const GChatter& chatter) const
  182 +{
  183 + // Initialise result string
  184 + std::string result;
  185 + std::list<std::string> temp;
  186 + temp = registeredMethods;
  187 +
  188 + // Continue only if chatter is not silent
  189 + if (chatter != SILENT) {
  190 +
  191 + // Append header
  192 + result.append("=== GVOApp ===");
  193 + result.append(m_id);
  194 + result.append("%d",temp.size());
  195 + for (std::list<std::string>::iterator i = temp.begin(); i != temp.end(); ++i) {
  196 + result.append("Method:\n");
  197 + result.append(*i);
  198 + }
  199 +
  200 +
  201 +
  202 + } // endif: chatter was not silent
  203 +
  204 + // Return result
  205 + return result;
  206 +}
  207 +
  208 +
  209 +/*==========================================================================
  210 + = =
  211 + = Private methods =
  212 + = =
  213 + ==========================================================================*/
  214 +
  215 +/***********************************************************************//**
  216 + * @brief Initialise class members
  217 + ***************************************************************************/
  218 +void GVOApp::init_members(void)
  219 +{
  220 + // Initialise members
  221 + std::list<std::string> registeredMethods;
  222 + // Return
  223 + return;
  224 +}
  225 +
  226 +
  227 +/***********************************************************************//**
  228 + * @brief Copy class members
  229 + *
  230 + * @param[in] app registered in Hub.
  231 + ***************************************************************************/
  232 +void GVOApp::copy_members(const GVOApp& app)
  233 +{
  234 + // Copy members
  235 +
  236 +
  237 + // Return
  238 + return;
  239 +}
  240 +
  241 +
  242 +/***********************************************************************//**
  243 + * @brief Delete class members
  244 + ***************************************************************************/
  245 +void GVOApp::free_members(void)
  246 +{
  247 + // Return
  248 + return;
  249 +}
  250 +
  251 +/***********************************************************************//**
  252 + * @brief Creates nex application container
  253 + ***************************************************************************/
  254 +void GVOApp::start_app(void)
  255 +{
  256 + // Creates Hub
  257 + printf("Creating new application Container\n");
  258 +
  259 + // Return
  260 + return;
  261 +}
... ...
src/vo/GVOHub.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * GVOHub.cpp - VO SAMP Hub class *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014-2015 by Thierry Louge *
  5 + * ----------------------------------------------------------------------- *
  6 + * *
  7 + * This program is free software: you can redistribute it and/or modify *
  8 + * it under the terms of the GNU General Public License as published by *
  9 + * the Free Software Foundation, either version 3 of the License, or *
  10 + * (at your option) any later version. *
  11 + * *
  12 + * This program is distributed in the hope that it will be useful, *
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15 + * GNU General Public License for more details. *
  16 + * *
  17 + * You should have received a copy of the GNU General Public License *
  18 + * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19 + * *
  20 + ***************************************************************************/
  21 +/**
  22 + * @file GVOHub.cpp
  23 + * @brief VO SAMP Hub class implementation
  24 + * @author Thierry Louge
  25 + */
  26 +
  27 +/* __ Includes ___________________________________________________________ */
  28 +#ifdef HAVE_CONFIG_H
  29 +#include <config.h>
  30 +#include <errno.h>
  31 +#endif
  32 +#include <cstdlib> // std::getenv() function
  33 +#include <cstdio> // std::fopen(), etc. functions
  34 +#include <cstring> // std::memset() function
  35 +#include <unistd.h> // close() function
  36 +#include <netdb.h> // getaddrinfo() function
  37 +#include <sys/socket.h> // socket(), connect() functions
  38 +#include <fstream>
  39 +#include "GVOHub.hpp"
  40 +#include "GVOClient.hpp"
  41 +#include "GException.hpp"
  42 +#include "GTools.hpp"
  43 +#include "GVOApp.hpp"
  44 +#include <signal.h>
  45 +#include <sys/types.h>
  46 +#include <sys/wait.h>
  47 +#include <sys/ipc.h>
  48 +#include <sys/shm.h>
  49 +
  50 +
  51 +/* __ Method name definitions ____________________________________________ */
  52 +#define G_HANDLE_REQUEST "GVOHub::handle_request(socklen_t)"
  53 +#define G_START_HUB "GVOHub::start_hub()"
  54 +#define G_INIT_MEMBERS "GVOHub::init_members()"
  55 +
  56 +/* __ Macros _____________________________________________________________ */
  57 +
  58 +/* __ Coding definitions _________________________________________________ */
  59 +#define CLEF 12345
  60 +
  61 +/* __ Debug definitions __________________________________________________ */
  62 +
  63 +
  64 +/*==========================================================================
  65 + = =
  66 + = Constructors/destructors =
  67 + = =
  68 + ==========================================================================*/
  69 +
  70 +/***********************************************************************//**
  71 + * @brief Void constructor
  72 + ***************************************************************************/
  73 +GVOHub::GVOHub(void)
  74 +{
  75 + // Initialise members
  76 + init_members();
  77 +
  78 + // Return
  79 + return;
  80 +}
  81 +
  82 +
  83 +/***********************************************************************//**
  84 + * @brief Copy constructor
  85 + *
  86 + * @param[in] hub VO Hub.
  87 + ***************************************************************************/
  88 +GVOHub::GVOHub(const GVOHub& hub)
  89 +{
  90 + // Initialise members
  91 + init_members();
  92 +
  93 + // Copy members
  94 + copy_members(hub);
  95 +
  96 + // Return
  97 + return;
  98 +}
  99 +
  100 +
  101 +/***********************************************************************//**
  102 + * @brief Destructor
  103 + ***************************************************************************/
  104 +GVOHub::~GVOHub(void)
  105 +{
  106 + free_members();
  107 + // Return
  108 + return;
  109 +}
  110 +
  111 +
  112 +/*==========================================================================
  113 + = =
  114 + = Operators =
  115 + = =
  116 + ==========================================================================*/
  117 +
  118 +/***********************************************************************//**
  119 + * @brief Assignment operator
  120 + *
  121 + * @param[in] hub VO hub.
  122 + * @return VO hub.
  123 + ***************************************************************************/
  124 +GVOHub& GVOHub::operator=(const GVOHub& hub)
  125 +{
  126 + // Execute only if object is not identical
  127 + if (this != &hub) {
  128 +
  129 + // Free members
  130 + free_members();
  131 +
  132 + // Initialise members
  133 + init_members();
  134 +
  135 + // Copy members
  136 + copy_members(hub);
  137 +
  138 + } // endif: object was not identical
  139 +
  140 + // Return
  141 + return *this;
  142 +}
  143 +
  144 +
  145 +/*==========================================================================
  146 + = =
  147 + = Public methods =
  148 + = =
  149 + ==========================================================================*/
  150 +
  151 +/***********************************************************************//**
  152 + * @brief Clear object.
  153 + *
  154 + * Reset object to a clean initial state.
  155 + ***************************************************************************/
  156 +void GVOHub::clear(void)
  157 +{
  158 + // Free memory and initialise members
  159 + free_members();
  160 + init_members();
  161 +
  162 + // Return
  163 + return;
  164 +}
  165 +
  166 +
  167 +/***********************************************************************//**
  168 + * @brief Clone object
  169 + ***************************************************************************/
  170 +GVOHub* GVOHub::clone(void) const
  171 +{
  172 + // Clone client
  173 + return new GVOHub(*this);
  174 +}
  175 +
  176 +
  177 +/***********************************************************************//**
  178 + * @brief
  179 + *
  180 + *
  181 + ***************************************************************************/
  182 +void GVOHub::ping_service(const socklen_t& sock)
  183 +{
  184 + printf("ping call received\n");
  185 + // Declare message
  186 + std::string msg = "";
  187 +
  188 + // Set methodResponse elts
  189 + msg.append("<?xml version=\"1.0\"?>\n");
  190 + msg.append("<methodResponse>\n");
  191 + msg.append("\t<params>\n");
  192 + msg.append("\t\t<param>\n\t\t\t<value/>\n\t\t</param>\n");
  193 + msg.append("\t</params>\n");
  194 + msg.append("</methodResponse>\n");
  195 +
  196 +
  197 +
  198 + post_string(msg,sock);
  199 + //printf("Response message sent\n");
  200 + //Return
  201 + return;
  202 +}
  203 +
  204 +/***********************************************************************//**
  205 + * @brief
  206 + *
  207 + *
  208 + ***************************************************************************/
  209 +void GVOHub::register_service(const GXml& xml, const socklen_t& sock)
  210 +{
  211 +
  212 + printf("Registration request called\n");
  213 + //sem_wait(&reg_clients->lock);
  214 + // Declare message
  215 + std::string msg = "";
  216 + char selfid[124];
  217 + char privatekey[124];
  218 + char cl_id[31];
  219 + std::string secret = random_string(15);
  220 + std::string translator = "http://localhost:8001/xmlrpc";
  221 +
  222 + for (int i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  223 + printf("Reference of client %d on registration call: %s\n",i,reg_clients->metadatas[i].reference);
  224 + if (strcmp(reg_clients->metadatas[i].reference,"NoRef") == 0) {
  225 + printf("Client %d ready to be filled with new application\n",i);
  226 + sprintf(cl_id,"c%d",i);
  227 + strcpy(reg_clients->metadatas[i].reference,cl_id);
  228 + sprintf(reg_clients->metadatas[i].private_key,secret.c_str());
  229 + break;
  230 + } else {
  231 + printf("Reference of client %d : %s\n",i,reg_clients->metadatas[i].reference);
  232 + }
  233 + }
  234 +
  235 + //printf("Message composition 2 \n");
  236 + sprintf(selfid,"\t\t\t\t\t<member><name>samp.self-id</name><value>%s</value></member>\n",cl_id);
  237 + sprintf(privatekey,"\t\t\t\t\t<member><name>samp.private-key</name><value>%s</value></member>\n",secret.c_str());
  238 + reg_clients->registered ++;
  239 + printf(" clients registered %d \n", reg_clients->registered);
  240 +
  241 + // Set methodResponse elts
  242 + msg.append("<?xml version=\"1.0\" ?>\n");
  243 + msg.append("<methodResponse>\n");
  244 + msg.append("\t<params>\n");
  245 + msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  246 + msg.append("\t\t\t\t\t<member><name>samp.hub-id</name><value>" + m_hub_id + "</value></member>\n");
  247 + msg.append(selfid);
  248 + msg.append(privatekey);
  249 + msg.append("\t\t\t\t\t<member><name>samp.status</name><value>samp.ok</value></member>\n");
  250 + msg.append("\t\t\t\t\t<member><name>samp.url-translator</name><value>" + translator + "</value></member>\n");
  251 + msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  252 + msg.append("\t</params>\n");
  253 + msg.append("</methodResponse>\n");
  254 + post_string(msg,sock);
  255 +
  256 + activate_callbacks("samp.hub.event.register",cl_id);
  257 + //sem_post(&reg_clients->lock);
  258 + //Return
  259 + return;
  260 +}
  261 +
  262 +
  263 +/***********************************************************************//**
  264 + * @brief
  265 + *
  266 + *
  267 + ***************************************************************************/
  268 +void GVOHub::unregister(const GXml& xml,const socklen_t& sock)
  269 +{
  270 + // Get the client's private key
  271 + std::string client_calling = "";
  272 + const GXmlNode* node = xml.element("methodCall", 0);
  273 + node = node->element("params", 0);
  274 + node = node->element("param", 0);
  275 + node = node->element("value", 0);
  276 + node = node->element("string", 0);
  277 + if (node != NULL) {
  278 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  279 + if (text != NULL) {
  280 + client_calling = text->text();
  281 + }
  282 + }
  283 +
  284 + // Loop over all clients
  285 + for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) {
  286 +
  287 + //
  288 + printf("Client %s matching candidate:\n",reg_clients->metadatas[i].private_key);
  289 +
  290 + //
  291 + if (strcmp(reg_clients->metadatas[i].private_key, client_calling.c_str()) == 0) {
  292 +
  293 + //
  294 + printf("Client %s unregistration:\n",reg_clients->metadatas[i].reference);
  295 +
  296 + // Declare message
  297 + std::string msg = "";
  298 +
  299 + // Set methodResponse elts
  300 + msg.append("<?xml version=\"1.0\"?>\n");
  301 + msg.append("<methodResponse>\n");
  302 + msg.append("<params>\n");
  303 + msg.append("<param><value/></param>\n");
  304 + msg.append("</params>\n");
  305 + msg.append("</methodResponse>\n");
  306 +
  307 + // Post response
  308 + post_string(msg, sock);
  309 +
  310 + //
  311 + activate_callbacks("samp.hub.event.unregister",reg_clients->metadatas[i].reference);
  312 +
  313 + // Reset client entry
  314 + strcpy(reg_clients->metadatas[i].reference,"NoRef");
  315 + sprintf(reg_clients->metadatas[i].name,"NoName");
  316 + sprintf(reg_clients->metadatas[i].description,"NoDescription");
  317 + sprintf(reg_clients->metadatas[i].icon,"NoIcon");
  318 + sprintf(reg_clients->metadatas[i].documentation,"NoDoc");
  319 + sprintf(reg_clients->metadatas[i].affiliation,"NoAffiliation");
  320 + sprintf(reg_clients->metadatas[i].email,"NoMail");
  321 + sprintf(reg_clients->metadatas[i].author_name,"NoAuthor");
  322 + sprintf(reg_clients->metadatas[i].homepage,"NoPage");
  323 +
  324 + // We can leave the loop now
  325 + break;
  326 +
  327 + }
  328 +
  329 + } // endfor: looped over clients
  330 +
  331 + // Return
  332 + return;
  333 +}
  334 +
  335 +
  336 +/***********************************************************************//**
  337 + * @brief
  338 + *
  339 + *
  340 + ***************************************************************************/
  341 +void GVOHub::register_metadata(const GXml& xml, const socklen_t& sock)
  342 +{
  343 + //
  344 + #if GVO_HUB_testing == 1
  345 + printf("Client Metadata received\n");
  346 + #endif
  347 +
  348 + // Search for value of methodName
  349 + std::string client_calling = "";
  350 + const GXmlNode* node = xml.element("methodCall", 0);
  351 + node = node->element("params", 0);
  352 + node = node->element("param", 0);
  353 + node = node->element("value", 0);
  354 + node = node->element("string", 0);
  355 + if (node != NULL) {
  356 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  357 + if (text != NULL) {
  358 + client_calling = text->text();
  359 + }
  360 + }
  361 +
  362 + // Loop over all clients
  363 + for (int i = 0; i < GVOHUB_NB_CLIENTS; ++i) {
  364 +
  365 + if (strcmp(reg_clients->metadatas[i].private_key,client_calling.c_str()) == 0) {
  366 + printf("Client %s ready to be filled with metadata\n",reg_clients->metadatas[i].reference);
  367 +
  368 + // Get metadata
  369 + std::string client_name = get_response_value(xml, "samp.name");
  370 + std::string client_description = get_response_value(xml, "samp.description.text");
  371 + std::string client_icon = get_response_value(xml, "samp.icon.url");
  372 + std::string client_doc = get_response_value(xml, "samp.documentation.url");
  373 + std::string client_affi = get_response_value(xml, "author.affiliation");
  374 + std::string client_mail = get_response_value(xml, "author.email");
  375 + std::string client_authname = get_response_value(xml, "author.name");
  376 + std::string client_page = get_response_value(xml, "home.page");
  377 +
  378 + // Store metadata
  379 + sprintf(reg_clients->metadatas[i].name, client_name.c_str());
  380 + sprintf(reg_clients->metadatas[i].description, client_description.c_str());
  381 + sprintf(reg_clients->metadatas[i].icon, client_icon.c_str());
  382 + sprintf(reg_clients->metadatas[i].documentation, client_doc.c_str());
  383 + sprintf(reg_clients->metadatas[i].affiliation, client_affi.c_str());
  384 + sprintf(reg_clients->metadatas[i].email, client_mail.c_str());
  385 + sprintf(reg_clients->metadatas[i].author_name, client_authname.c_str());
  386 + sprintf(reg_clients->metadatas[i].homepage, client_page.c_str());
  387 +
  388 + // Declare message
  389 + std::string msg = "";
  390 +
  391 + // The hub response to Metadata declaration has no useful
  392 + // content and can be discarded by the client.
  393 + msg.append("<?xml version=\"1.0\"?>\n");
  394 + msg.append("<methodResponse><params><param><value/></param></params>\n");
  395 + msg.append("</methodResponse>\n");
  396 +
  397 + // Post response
  398 + post_string(msg,sock);
  399 +
  400 + //
  401 + activate_callbacks("samp.hub.event.metadata",
  402 + reg_clients->metadatas[i].reference);
  403 +
  404 + // We are done now and can exit the loop
  405 + break;
  406 + }
  407 + else {
  408 + if (i == GVOHUB_NB_CLIENTS - 1) {
  409 + printf("OOPS... unable to find client: %s\n",client_calling.c_str());
  410 + }
  411 + }
  412 +
  413 + } // endfor: looped over client entries
  414 +
  415 + // Return
  416 + return;
  417 +}
  418 +
  419 +/***********************************************************************//**
  420 + * @brief
  421 + *
  422 + *
  423 + ***************************************************************************/
  424 +void GVOHub::set_xml_rpc_callback(const GXml& xml,const socklen_t& sock)
  425 +{
  426 + char buffer[124];
  427 + int i;
  428 + printf("Client callback registration\n");
  429 +
  430 + std::string client_calling = "";
  431 + // Search for value of methodName
  432 + const GXmlNode* node = xml.element("methodCall", 0);
  433 + node = node->element("params", 0);
  434 + node = node->element("param", 0);
  435 + node = node->element("value", 0);
  436 + if (node != NULL) {
  437 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  438 + if (text != NULL) {
  439 + client_calling = text->text();
  440 + }
  441 + }
  442 + // Search for metadata values to store
  443 + std::string client_port = get_callback_port(xml, "samp.hub.setXmlrpcCallback");
  444 + std::cout << client_port << std::endl;
  445 +
  446 + for (i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  447 + //printf("comparing Reference of client %s with seeked %s\n",reg_clients->metadatas[i].private_key,client_calling.c_str());
  448 + if (strcmp(reg_clients->metadatas[i].private_key,client_calling.c_str()) == 0) {
  449 + printf("Client %s ready to be filled with port information\n",reg_clients->metadatas[i].reference);
  450 + sprintf(reg_clients->metadatas[i].port,client_port.c_str());
  451 + break;
  452 + }
  453 + }
  454 + printf("%s\n",reg_clients->metadatas[i].port);
  455 + // Declare message
  456 + std::string msg = "";
  457 +
  458 + //The hub response to rpc callback declaration has no usefull content and can be discarded by the client.
  459 + // Set methodResponse elts
  460 + msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  461 + msg.append("<methodResponse>\n");
  462 + msg.append("\t<params>\n");
  463 + msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  464 + msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.status</name>\n\t\t\t\t\t\t<value>samp.ok</value>\n\t\t\t\t\t</member>\n");
  465 + msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  466 + msg.append("\t</params>\n");
  467 + msg.append("</methodResponse>\n");
  468 + post_string(msg,sock);
  469 + //Return
  470 + return;
  471 +}
  472 +/***********************************************************************//**
  473 + * @brief
  474 + *
  475 + *
  476 + ***************************************************************************/
  477 +void GVOHub::get_registered_clients(const GXml& xml,const socklen_t& sock)
  478 +{
  479 + std::string buffer;
  480 + const int n = 1000;
  481 + char line[n];
  482 + char reference[64];
  483 + std::string tofind;
  484 + std::size_t found;
  485 + std::string str2;
  486 + // Declare message
  487 + std::string msg = "";
  488 +
  489 + std::string client_calling = "";
  490 + // Search for value of methodName
  491 + const GXmlNode* node = xml.element("methodCall", 0);
  492 + node = node->element("params", 0);
  493 + node = node->element("param", 0);
  494 + node = node->element("value", 0);
  495 + if (node != NULL) {
  496 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  497 + if (text != NULL) {
  498 + client_calling = text->text();
  499 + }
  500 + }
  501 +
  502 + // Set methodResponse elts
  503 + msg.append("<?xml version=\'1.0\' encoding=\"UTF-8\"?>\n");
  504 + msg.append("<methodResponse>\n");
  505 + msg.append("\t<params>\n");
  506 + msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<array>\n\t\t\t\t\t<data>\n");
  507 + msg.append("\t\t\t\t\t\t<value>gammalib_hub</value>\n");
  508 +
  509 +
  510 + for (int i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  511 + if (strcmp(reg_clients->metadatas[i].reference,"NoRef") == 0) {
  512 + printf("Client %d not registered\n",i);
  513 + } else {
  514 + //Do not send back current client's registration
  515 + if (strcmp(reg_clients->metadatas[i].private_key,client_calling.c_str()) != 0) {
  516 + msg.append("\t\t\t\t\t\t<value>");
  517 + msg.append(reg_clients->metadatas[i].reference);
  518 + msg.append("</value>\n");
  519 + printf("Reference of client %d : %s\n",i,reg_clients->metadatas[i].reference);
  520 + }
  521 + }
  522 + }
  523 +
  524 + msg.append("\t\t\t\t\t</data>\n\t\t\t\t</array>\n\t\t\t</value>\n");
  525 + msg.append("\t\t</param>\n");
  526 + msg.append("\t</params>\n");
  527 + msg.append("</methodResponse>\n");
  528 + printf("Message ready to be sent \n");
  529 + post_string(msg,sock);
  530 +
  531 + //Return
  532 + return;
  533 +
  534 +}
  535 +/***********************************************************************//**
  536 + * @brief
  537 + *
  538 + *
  539 + ***************************************************************************/
  540 +void GVOHub::get_subscribed_clients(const GXml& xml,const socklen_t& sock)
  541 +{
  542 + std::string buffer;
  543 + const int n = 1000;
  544 + char line[n];
  545 + FILE* fptr = fopen("SAMP-registered.txt", "r");
  546 + if (fptr != NULL) {
  547 + while (fgets(line, n, fptr) != NULL) {
  548 +
  549 + // Convert line to C++ string
  550 + std::string cline = std::string(line);
  551 +
  552 + // Check for secret key
  553 + if (cline.compare(0, 10, "Registered") == 0) {
  554 + buffer = gammalib::strip_chars(cline.substr(10, std::string::npos), "\r\n");
  555 + }
  556 + }
  557 +
  558 + // Closes file
  559 + fclose(fptr);
  560 + // Declare message
  561 + std::string msg = "";
  562 +
  563 + //The hub response to rpc callback declaration has no usefull content and can be discarded by the client.
  564 + // Set methodResponse elts
  565 +
  566 + msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  567 + msg.append("<methodResponse>\n");
  568 + msg.append("\t<params>\n");
  569 + msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  570 + msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>c0</name>\n\t\t\t\t\t\t<value><struct></struct></value>\n\t\t\t\t\t</member>\n");
  571 + msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>gammalib_hub</name>\n\t\t\t\t\t\t<value><struct></struct></value>\n\t\t\t\t\t</member>\n");
  572 + msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  573 + msg.append("\t</params>\n");
  574 + msg.append("</methodResponse>\n");
  575 +
  576 +
  577 + //int length = msg.length();
  578 + post_string(msg,sock);
  579 +
  580 + //Return
  581 + return;
  582 + }
  583 +}
  584 +/***********************************************************************//**
  585 + * @brief
  586 + *
  587 + *
  588 + ***************************************************************************/
  589 +void GVOHub::declare_subscriptions(const GXml& xml,const socklen_t& sock)
  590 +{
  591 + std::list<std::string>::iterator p;
  592 + int i,j;
  593 + std::ofstream myfile;
  594 + //char content[GVOHUB_NB_METHODS];
  595 + printf("Declare Subscriptions\n");
  596 +
  597 + std::string client_calling = "";
  598 + std::string tempo;
  599 + // Search for value of methodName
  600 + const GXmlNode* node = xml.element("methodCall", 0);
  601 + node = node->element("params", 0);
  602 + node = node->element("param", 0);
  603 + node = node->element("value", 0);
  604 + if (node != NULL) {
  605 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  606 + if (text != NULL) {
  607 + client_calling = text->text();
  608 + }
  609 + }
  610 +
  611 + std::list<std::string> client_subscriptions = get_registrations(xml, "samp.hub.declareSubscriptions");
  612 + std::cout << "Client registered to following methods calls:" << std::endl;
  613 +
  614 + for (int i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  615 + //printf("comparing Reference of client %s with seeked %s\n",reg_clients->metadatas[i].private_key,client_calling.c_str());
  616 + if (strcmp(reg_clients->metadatas[i].private_key,client_calling.c_str()) == 0) {
  617 + for( j=0,p=client_subscriptions.begin(); j<client_subscriptions.size()-1; j++,p++ ) {
  618 + std::cout << *p << std::endl;
  619 + tempo = *p;
  620 + //content = *p;
  621 + sprintf(reg_clients->metadatas[i].registered_methods[j],tempo.c_str());
  622 + /*printf("Registered: %s\n",reg_clients->metadatas[i].registered_methods[j]);
  623 + printf("Registration done\n");*/
  624 + }
  625 + }
  626 + }
  627 +
  628 +
  629 +
  630 + // Declare message
  631 + std::string msg = "";
  632 + // Set methodResponse elts
  633 + msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  634 + msg.append("<methodResponse>\n");
  635 + msg.append("\t<params>\n");
  636 + msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  637 + msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.status</name>\n\t\t\t\t\t\t<value>samp.ok</value>\n\t\t\t\t\t</member>\n");
  638 + msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  639 + msg.append("\t</params>\n");
  640 + msg.append("</methodResponse>\n");
  641 +
  642 + post_string(msg,sock);
  643 + //Return
  644 + return;
  645 +}
  646 +
  647 +/***********************************************************************//**
  648 + * @brief
  649 + *
  650 + *
  651 + ***************************************************************************/
  652 +void GVOHub::get_metadata(const GXml& xml,const socklen_t& sock)
  653 +{
  654 + std::list<std::string>::iterator p;
  655 + int i;
  656 + std::ofstream myfile;
  657 + std::string content;
  658 + printf("Retrieving metadata\n");
  659 +
  660 + std::string client_calling = "";
  661 + // Search for value of methodName
  662 + const GXmlNode* node = xml.element("methodCall", 0);
  663 + node = node->element("params", 0);
  664 + node = node->element("param", 1);
  665 + node = node->element("value", 0);
  666 + if (node != NULL) {
  667 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  668 + if (text != NULL) {
  669 + client_calling = text->text();
  670 + }
  671 + }
  672 + // Declare message
  673 + std::string msg = "";
  674 + // Set methodResponse elts
  675 + msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  676 + msg.append("<methodResponse>\n");
  677 + msg.append("\t<params>\n");
  678 + msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  679 + msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.status</name>\n\t\t\t\t\t\t<value>samp.ok</value>\n\t\t\t\t\t</member>\n");
  680 +
  681 + for (int i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  682 + if (strcmp("gammalib_hub",client_calling.c_str()) == 0) {
  683 + 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>gammalib_hub</value>\n\t\t\t\t\t</member>\n");
  684 + 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>Gamma lib hub.</value>\n\t\t\t\t\t</member>\n");
  685 + 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></value>\n\t\t\t\t\t</member>\n");
  686 + 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>gammalib github documentation</value>\n\t\t\t\t\t</member>\n");
  687 + 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>IRAP, CNRS Toulouse</value>\n\t\t\t\t\t</member>\n");
  688 + 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>dontcontactme@please</value>\n\t\t\t\t\t</member>\n");
  689 + 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>J. Knödlseder, T. Louge</value>\n\t\t\t\t\t</member>\n");
  690 + 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>no dedicated page</value>\n\t\t\t\t\t</member>\n");
  691 + break;
  692 + }
  693 + if (strcmp(reg_clients->metadatas[i].reference,client_calling.c_str()) == 0) {
  694 + printf("Client %s metadata retrieval:\n",reg_clients->metadatas[i].reference);
  695 + 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>");
  696 + msg.append(reg_clients->metadatas[i].name);
  697 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  698 + 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>");
  699 + msg.append(reg_clients->metadatas[i].description);
  700 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  701 + 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>");
  702 + msg.append(reg_clients->metadatas[i].icon);
  703 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  704 + 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>");
  705 + msg.append(reg_clients->metadatas[i].documentation);
  706 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  707 + 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>");
  708 + msg.append(reg_clients->metadatas[i].affiliation);
  709 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  710 + 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>");
  711 + msg.append(reg_clients->metadatas[i].email);
  712 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  713 + 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>");
  714 + msg.append(reg_clients->metadatas[i].author_name);
  715 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  716 + 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>");
  717 + msg.append(reg_clients->metadatas[i].homepage);
  718 + msg.append("</value>\n\t\t\t\t\t</member>\n");
  719 + break;
  720 + } else {
  721 + if (i == GVOHUB_NB_CLIENTS - 1) {
  722 + printf("OOPS... unable to find metadata for client: %s\n",client_calling.c_str());
  723 + }
  724 + }
  725 + }
  726 +
  727 + msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  728 + msg.append("\t</params>\n");
  729 + msg.append("</methodResponse>\n");
  730 + printf("Metadata for %s : \n %s",client_calling.c_str(),msg.c_str());
  731 + post_string(msg,sock);
  732 +
  733 + //Return
  734 + return;
  735 +}
  736 +/***********************************************************************//**
  737 + * @brief
  738 + *
  739 + *
  740 + ***************************************************************************/
  741 +void GVOHub::get_subscriptions(const GXml& xml,const socklen_t& sock)
  742 +{
  743 + std::list<std::string>::iterator p;
  744 + int i,j;
  745 + std::ofstream myfile;
  746 + std::string content;
  747 + printf("Retrieving subscriptions\n");
  748 + std::string client_calling = "";
  749 + // Search for value of methodName
  750 + const GXmlNode* node = xml.element("methodCall", 0);
  751 + node = node->element("params", 0);
  752 + node = node->element("param", 1);
  753 + node = node->element("value", 0);
  754 + if (node != NULL) {
  755 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  756 + if (text != NULL) {
  757 + client_calling = text->text();
  758 + }
  759 + }
  760 + // Declare message
  761 + std::string msg = "";
  762 + // Set methodResponse elts
  763 + msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  764 + msg.append("<methodResponse>\n");
  765 + msg.append("\t<params>\n");
  766 + msg.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  767 + //msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>samp.status</name>\n\t\t\t\t\t\t<value>samp.ok</value>\n\t\t\t\t\t</member>\n");
  768 + char tempo[128];
  769 + for (i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  770 + if (strcmp(reg_clients->metadatas[i].reference,client_calling.c_str()) == 0) {
  771 + //printf("retrieving client %s\n",reg_clients->metadatas[i].reference);
  772 + for (j = 0; j < GVOHUB_NB_METHODS; j++) {
  773 + strcpy(tempo,reg_clients->metadatas[i].registered_methods[j]);
  774 + if (strcmp("",tempo) == 0) {
  775 + continue;
  776 + } else {
  777 + msg.append("\t\t\t\t\t<member>\n\t\t\t\t\t\t<name>");
  778 + msg.append(tempo);
  779 + msg.append("</name>\n\t\t\t\t\t\t<value></value>\n\t\t\t\t\t</member>\n");
  780 + }
  781 + }
  782 + }
  783 + }
  784 +
  785 + msg.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  786 + msg.append("\t</params>\n");
  787 + msg.append("</methodResponse>\n");
  788 + post_string(msg,sock);
  789 +
  790 + //Return
  791 + return;
  792 +}
  793 +/***********************************************************************//**
  794 + * @brief Print VO hub information
  795 + *
  796 + * @param[in] chatter Chattiness (defaults to NORMAL).
  797 + * @return String containing VO hub information
  798 + ***************************************************************************/
  799 +std::string GVOHub::print(const GChatter& chatter) const
  800 +{
  801 + // Initialise result string
  802 + std::string result;
  803 +
  804 + // Continue only if chatter is not silent
  805 + if (chatter != SILENT) {
  806 +
  807 + // Append header
  808 + result.append("=== GVOHub ===");
  809 +
  810 + // Append client information
  811 + result.append("\n"+gammalib::parformat("Name")+m_name);
  812 +
  813 + // Append Hub information
  814 + result.append("\n"+gammalib::parformat("Hub key")+m_secret);
  815 + result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url);
  816 + result.append("\n"+gammalib::parformat("Hub host (port)"));
  817 + result.append(m_hub_host+" ("+m_hub_port+")");
  818 + result.append("\n"+gammalib::parformat("SAMP protocol version"));
  819 + result.append(m_version);
  820 + result.append("\n"+gammalib::parformat("Hub connection"));
  821 + if (m_socket == -1) {
  822 + result.append("no");
  823 + }
  824 + else {
  825 + if (!m_client_key.empty()) {
  826 + //result.append("registered as \""+m_client_id);
  827 + result.append("\" on Hub \""+m_hub_id);
  828 + result.append("\" via socket "+gammalib::str(m_socket));
  829 + }
  830 + else {
  831 + result.append("established on socket ");
  832 + result.append(gammalib::str(m_socket));
  833 + }
  834 + }
  835 +
  836 + } // endif: chatter was not silent
  837 +
  838 + // Return result
  839 + return result;
  840 +}
  841 +
  842 +
  843 +/*==========================================================================
  844 + = =
  845 + = Private methods =
  846 + = =
  847 + ==========================================================================*/
  848 +
  849 +/***********************************************************************//**
  850 + * @brief Initialise class members
  851 + ***************************************************************************/
  852 +void GVOHub::init_members(void)
  853 +{
  854 + // Initialise members
  855 + m_name = "GammaLib";
  856 + //m_secret is a private string to identify clients. Every client has his own m_secret
  857 + m_secret = "";
  858 + m_hub_url = "http://localhost:8001/xmlrpc";
  859 + m_hub_host = "127.0.0.1";
  860 + m_hub_port = "8001";
  861 + m_version = "1.3";
  862 + m_client_key.clear();
  863 + m_hub_id = "gammalib_hub";
  864 + //m_client_id.clear();
  865 + m_socket = -1; // Signals no socket
  866 + m_nb_clients = 0; // No registered clients at initialization
  867 +
  868 + //puts the structure array of clients in shared memory
  869 + if ((shm_handler = shmget(CLEF, sizeof(clients_descriptor), 0666 | IPC_CREAT)) < 0)
  870 + {
  871 + std::string msg = "Could not open shared memory.";
  872 + throw GException::invalid_value(G_INIT_MEMBERS, msg);
  873 + }
  874 + if ((ptr_mem_partagee = shmat(shm_handler, NULL, 0)) == (void*) -1)
  875 + {
  876 + std::string msg = "Could not attach shared memory.";
  877 + throw GException::invalid_value(G_INIT_MEMBERS, msg);
  878 + }
  879 + reg_clients = (clients_descriptor *)ptr_mem_partagee;
  880 + reg_clients->registered = 0;
  881 + for (int i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  882 + strcpy(reg_clients->metadatas[i].reference,"NoRef");
  883 + strcpy(reg_clients->metadatas[i].private_key,"Unknown");
  884 + strcpy(reg_clients->metadatas[i].name,"Unknown");
  885 + strcpy(reg_clients->metadatas[i].icon,"Unknown");
  886 + strcpy(reg_clients->metadatas[i].documentation,"Unknown");
  887 + strcpy(reg_clients->metadatas[i].affiliation,"Unknown");
  888 + strcpy(reg_clients->metadatas[i].author_name,"Unknown");
  889 + strcpy(reg_clients->metadatas[i].email,"Unknown");
  890 + strcpy(reg_clients->metadatas[i].homepage,"Unknown");
  891 + strcpy(reg_clients->metadatas[i].port,"Unknown");
  892 + strcpy(reg_clients->metadatas[i].description,"Unknown");
  893 +
  894 + }
  895 + for (int j = 0; j < GVOHUB_NB_CLIENTS; j++) {
  896 + printf("%s\n",reg_clients->metadatas[j].reference);
  897 + }
  898 + //sem_init(&reg_clients->lock, 0, 1);
  899 + // Creates Hub
  900 + printf("Creating the hub\n");
  901 + create_samp_file();
  902 +
  903 + // Starts the hub
  904 + printf("Starting the hub\n");
  905 + start_hub();
  906 + // Return
  907 + return;
  908 +}
  909 +
  910 +
  911 +/***********************************************************************//**
  912 + * @brief Copy class members
  913 + *
  914 + * @param[in] hub VO hub.
  915 + ***************************************************************************/
  916 +void GVOHub::copy_members(const GVOHub& hub)
  917 +{
  918 + // Copy members
  919 + m_name = hub.m_name;
  920 + m_hub_url = hub.m_hub_url;
  921 + m_hub_host = hub.m_hub_host;
  922 + m_hub_port = hub.m_hub_port;
  923 + m_version = hub.m_version;
  924 + m_client_key = hub.m_client_key;
  925 + m_hub_id = hub.m_hub_id;
  926 + m_socket = hub.m_socket;
  927 +
  928 + // Return
  929 + return;
  930 +}
  931 +
  932 +
  933 +/***********************************************************************//**
  934 + * @brief Delete class members
  935 + ***************************************************************************/
  936 +void GVOHub::free_members(void)
  937 +{
  938 + struct shmid_ds *buf;
  939 +
  940 + std::cout << "I am here" << std::endl;
  941 + std::string lockurl = get_hub_lockfile();
  942 + printf("Deleting file: %s\n",lockurl.c_str());
  943 + fflush(stdout);
  944 + std::remove(lockurl.c_str());
  945 + shmdt(ptr_mem_partagee);
  946 + shmctl(shm_handler, IPC_RMID, buf);
  947 + // Return
  948 + return;
  949 +}
  950 +
  951 +
  952 +/***********************************************************************//**
  953 + * @brief Creates the lockfile, fill it
  954 + *
  955 + *
  956 + * Implements IVOA standard REC-SAMP-1.3-20120411.
  957 + ***************************************************************************/
  958 +void GVOHub::create_samp_file(void)
  959 +{
  960 + // Get lockfile URL
  961 + std::string lockurl = get_hub_lockfile();
  962 +
  963 + // Open SAMP lockfile. Continue only if opening was successful
  964 + FILE* fptr = fopen(lockurl.c_str(), "w");
  965 + if (fptr != NULL) {
  966 +
  967 + // If successfull writes basic hub configuration to the lockfile
  968 + fputs ("# SAMP lockfile \n# Required keys:\n",fptr);
  969 + char sampsecret[256] = "samp.secret=";
  970 + strcat(sampsecret,m_secret.c_str());
  971 + strcat(sampsecret,"\n");
  972 + fputs (sampsecret,fptr);
  973 + char sampurl[256] = "samp.hub.xmlrpc.url=";
  974 + strcat(sampurl,m_hub_url.c_str());
  975 + strcat(sampurl,"\n");
  976 + fputs (sampurl,fptr);
  977 + char samprofile[256] = "samp.profile.version=";
  978 + strcat(samprofile,m_version.c_str());
  979 + strcat(samprofile,"\n");
  980 + fputs (samprofile,fptr);
  981 + fputs ("# Info stored by hub for some private reason:\n",fptr);
  982 + char sampid[256] = "gammalib.hubid=";
  983 + strcat(sampid,m_hub_id.c_str());
  984 + strcat(sampid,"\n");
  985 + fputs (sampid,fptr);
  986 + }
  987 +
  988 + // Close SAMP lockfile
  989 + fclose(fptr);
  990 +
  991 + // Return
  992 + return;
  993 +}
  994 +
  995 +
  996 +/***********************************************************************//**
  997 + * @brief Returns SAMP Hub lockfile URL
  998 + *
  999 + * @return SAMP Hub lockfile URL (empty if no lockfile was found).
  1000 + *
  1001 + * Implements IVOA standard REC-SAMP-1.3-20120411.
  1002 + ***************************************************************************/
  1003 +std::string GVOHub::get_hub_lockfile(void) const
  1004 +{
  1005 + // Initialise result
  1006 + std::string url = "";
  1007 +
  1008 + // Check for existence of the SAMP_HUB environment variable first
  1009 + char* hub_ptr = std::getenv("SAMP_HUB");
  1010 + if (hub_ptr != NULL) {
  1011 +
  1012 + // Check for mandatory std-lockurl: prefix (no other prefixe is
  1013 + // supported so far)
  1014 + std::string lockurl = std::string(hub_ptr);
  1015 + if (lockurl.compare(0, 12, "std-lockurl:") == 0) {
  1016 +
  1017 + // Extract URL
  1018 + url = lockurl.substr(12, std::string::npos);
  1019 +
  1020 + } // endif: std-lockurl: prefix found
  1021 +
  1022 + }
  1023 +
  1024 + // ... otherwise the lockfile should be $HOME/.samp
  1025 + else {
  1026 +
  1027 + // Get user's HOME directory path as the prefix of the full
  1028 + // path. If the HOME environment variable is not set we
  1029 + // expect that .samp is in the local directory. This is non
  1030 + // standard, but prevents for creating an exception here.
  1031 + std::string prefix = "";
  1032 + char* home_ptr = std::getenv("HOME");
  1033 + if (home_ptr != NULL) {
  1034 + prefix = std::string(home_ptr) + "/";
  1035 + }
  1036 +
  1037 + // Set filename
  1038 + url = prefix + ".samp";
  1039 +
  1040 + } // endelse: no SAMP_HUB environment variable found
  1041 +
  1042 + // Return URL
  1043 + return url;
  1044 +}
  1045 +
  1046 +
  1047 +/***********************************************************************//**
  1048 + * @brief Reads the client message and runs appropriate function
  1049 + *
  1050 + * @exception GExpection::invalid_value
  1051 + * Buffer could not be read or written
  1052 + ***************************************************************************/
  1053 +void GVOHub::handle_request(const socklen_t& sock)
  1054 +{
  1055 + // Initialize buffer
  1056 + char buffer[8192];
  1057 + bzero(buffer,8192);
  1058 + int i,j;
  1059 + // Declare empty XML document
  1060 + GXml xml;
  1061 +
  1062 + // Read buffer
  1063 + int n = read(sock,buffer,8192);
  1064 + if (n < 0) {
  1065 + std::string msg = "Could not read socket buffer.";
  1066 + throw GException::invalid_value(G_HANDLE_REQUEST, msg);
  1067 + }
  1068 + printf("Here is the message: %s\n",buffer);
  1069 + std::string response = buffer;
  1070 +
  1071 + // Find start of XML text
  1072 + size_t start = response.find("<?xml");
  1073 + // If found then convert text into XML document
  1074 + if (start != std::string::npos) {
  1075 + xml = GXml(response.substr(start, std::string::npos));
  1076 + } else {
  1077 + //No XML tag found.
  1078 + return;
  1079 +
  1080 + }
  1081 +
  1082 + std::string method_called = "";
  1083 + // Search for value of methodName
  1084 + const GXmlNode* node = xml.element("methodCall", 0);
  1085 + const GXmlNode* ptr = node->element("methodName", 0);
  1086 + if (ptr != NULL) {
  1087 + const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
  1088 + if (text != NULL) {
  1089 + method_called = text->text();
  1090 + }
  1091 + }
  1092 + if (method_called.compare("samp.hub.ping") == 0) {
  1093 + ping_service(sock);
  1094 + }
  1095 + if (method_called.compare("samp.hub.register") == 0) {
  1096 + register_service(xml, sock);
  1097 + }
  1098 + if (method_called.compare("samp.hub.unregister") == 0) {
  1099 + unregister(xml,sock);
  1100 + }
  1101 + if (method_called.compare("samp.hub.declareMetadata") == 0) {
  1102 + register_metadata(xml,sock);
  1103 + }
  1104 + if (method_called.compare("samp.hub.declareSubscriptions") == 0) {
  1105 + declare_subscriptions(xml,sock);
  1106 + }
  1107 + if (method_called.compare("samp.hub.setXmlrpcCallback") == 0) {
  1108 + set_xml_rpc_callback(xml,sock);
  1109 + }
  1110 + if (method_called.compare("samp.hub.getSubscriptions") == 0) {
  1111 + get_subscriptions(xml, sock);
  1112 + }
  1113 + if (method_called.compare("samp.hub.getRegisteredClients") == 0) {
  1114 + get_registered_clients(xml, sock);
  1115 + }
  1116 + if (method_called.compare("samp.hub.getSubscribedClients") == 0) {
  1117 + get_subscribed_clients(xml, sock);
  1118 + }
  1119 + if (method_called.compare("samp.hub.getMetadata") == 0) {
  1120 + get_metadata(xml, sock);
  1121 + }
  1122 + if (method_called.compare("samp.hub.notify") == 0) {
  1123 + ping_service(sock);
  1124 + }
  1125 + if (method_called.compare("samp.hub.notifyAll") == 0) {
  1126 + ping_service(sock);
  1127 + }
  1128 + if (method_called.compare("samp.hub.call") == 0) {
  1129 + ping_service(sock);
  1130 + }
  1131 + if (method_called.compare("samp.hub.callAll") == 0) {
  1132 + ping_service(sock);
  1133 + }
  1134 + if (method_called.compare("samp.hub.callAndWait") == 0) {
  1135 + ping_service(sock);
  1136 + }
  1137 + if (method_called.compare("samp.hub.reply") == 0) {
  1138 + ping_service(sock);
  1139 + }
  1140 +
  1141 +
  1142 + // Return
  1143 + return;
  1144 +}
  1145 +
  1146 +/***********************************************************************//**
  1147 + * @brief Starts the SAMP hub socket and listens on it
  1148 + *
  1149 + * @return 1 if error comes out, nothing if everything is right (infinite listening loop)
  1150 + *
  1151 + ***************************************************************************/
  1152 +void GVOHub::start_hub(void)
  1153 +{
  1154 + struct sockaddr_in serv_addr,cli_addr;
  1155 + int max_sd, portno,pid,max_clients = 10, i,activity,addrlen;
  1156 + socklen_t sockfd, client_socket[10];
  1157 + int opt = 1;
  1158 + // Prepare TCP/IP structure
  1159 + bzero((char *) &serv_addr, sizeof(serv_addr));
  1160 + portno = 8001;
  1161 + serv_addr.sin_family = AF_INET;
  1162 + serv_addr.sin_addr.s_addr = INADDR_ANY;
  1163 + serv_addr.sin_port = htons(portno);
  1164 +
  1165 + //set of socket descriptors
  1166 + fd_set readfds;
  1167 +
  1168 + // Initialise all client_socket[] to 0 so not checked
  1169 + for (i = 0; i < max_clients; ++i) {
  1170 + client_socket[i] = 0;
  1171 + }
  1172 +
  1173 + // ...
  1174 + socklen_t hub_socket = socket(AF_INET, SOCK_STREAM, 0);
  1175 +
  1176 + // Creation of hub main socket
  1177 + if (hub_socket < 0) {
  1178 + std::string msg = "Hub socket could not be created.";
  1179 + throw GException::invalid_value(G_START_HUB, msg);
  1180 + }
  1181 +
  1182 + // Set hub main socket to allow multiple connections
  1183 + if (setsockopt(hub_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) {
  1184 + std::string msg = "Hub socket could not be set to multiple connections.";
  1185 + throw GException::invalid_value(G_START_HUB, msg);
  1186 + }
  1187 +
  1188 + // Server socket is opened. Now, bind it to the port, with family etc.
  1189 + if (bind(hub_socket, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
  1190 + std::string msg = "Hub socket could not bind to server socket.";
  1191 + throw GException::invalid_value(G_START_HUB, msg);
  1192 + }
  1193 +
  1194 + // Now start listening for the clients: 5 requests simultaneously pending maximum
  1195 + if (listen(hub_socket, 5) < 0) {
  1196 + std::string msg = "Hub socket could not start listening.";
  1197 + throw GException::invalid_value(G_START_HUB, msg);
  1198 + }
  1199 +
  1200 + // ...
  1201 + socklen_t clilen = sizeof(cli_addr);
  1202 +
  1203 + //Catching ctrl+C to close SHM
  1204 + //signal(SIGINT, intHandler);
  1205 +
  1206 + // Main event handling loop
  1207 +
  1208 + while (1) {
  1209 +
  1210 + // Accept connection from the client
  1211 + socklen_t newsocket = accept(hub_socket, (struct sockaddr *)&cli_addr, &clilen);
  1212 + if (newsocket < 0) {
  1213 + std::string msg = "Client connection to socket not accepted.";
  1214 + throw GException::invalid_value(G_START_HUB, msg);
  1215 + }
  1216 + /*
  1217 + handle_request(newsocket);
  1218 + close(newsocket);
  1219 + */
  1220 + // Create child process to handle the request
  1221 +
  1222 + pid = fork();
  1223 + if (pid < 0) {
  1224 + std::string msg = "No child process created.";
  1225 + throw GException::invalid_value(G_START_HUB, msg);
  1226 + }
  1227 + if (pid == 0) {
  1228 + // Child process: client process
  1229 + handle_request(newsocket);
  1230 + close(newsocket);
  1231 + exit(0);
  1232 + }
  1233 + else {
  1234 + //Father process code zone: set SIG_IGN to child
  1235 + // so that kernel can close it without senndit it to zombie state <defunct>
  1236 + int status = 0;
  1237 + waitpid( pid, &status, 0 );
  1238 + signal(pid, SIG_IGN);
  1239 + }
  1240 +
  1241 + }
  1242 +
  1243 +
  1244 + // Return
  1245 + return;
  1246 +}
  1247 +
  1248 +
  1249 +/***********************************************************************//**
  1250 + * @brief Returns value for a SAMP client query parameter
  1251 + *
  1252 + * @param[in] xml client query XML document.
  1253 + * @param[in] name Parameter name.
  1254 + * @return Parameter value.
  1255 + *
  1256 + * Returns value for a SAMP client query parameter. If the specified
  1257 + * parameter was not found or if the response structure is not compliant,
  1258 + * an empty string is returned.
  1259 + ***************************************************************************/
  1260 +std::string GVOHub::get_response_value(const GXml& xml,
  1261 + const std::string& name) const
  1262 +{
  1263 + // Declare value
  1264 + std::string value = "";
  1265 +
  1266 + // Search for value of specified member
  1267 + const GXmlNode* node = xml.element("methodCall", 0);
  1268 + if (node != NULL) {
  1269 + node = node->element("params", 0);
  1270 + if (node != NULL) {
  1271 + node = node->element("param", 1);
  1272 + if (node != NULL) {
  1273 + node = node->element("value", 0);
  1274 + if (node != NULL) {
  1275 + node = node->element("struct", 0);
  1276 + if (node != NULL) {
  1277 + int num = node->elements("member");
  1278 + for (int i = 0; i < num; ++i) {
  1279 + /*std::cout << i << std::endl;
  1280 + std::cout << *(node->element("member", i)) << std::cout;*/
  1281 + const GXmlNode* member = node->element("member", i);
  1282 + //const GXmlNode* member_name = member->element("name", 0);
  1283 + std::string one_name;
  1284 + std::string one_value;
  1285 + get_name_value_pair(member, one_name, one_value);
  1286 + if (one_name == name) {
  1287 + value = one_value;
  1288 + break;
  1289 + }
  1290 + }
  1291 + }
  1292 + }
  1293 + }
  1294 + }
  1295 + }
  1296 +
  1297 + // Return value
  1298 + return value;
  1299 +}
  1300 +/***********************************************************************//**
  1301 + * @brief Returns value for a SAMP client query parameter
  1302 + *
  1303 + * @param[in] xml client query XML document.
  1304 + * @param[in] name Parameter name.
  1305 + * @return Parameter value.
  1306 + *
  1307 + * Returns value for a SAMP client query parameter. If the specified
  1308 + * parameter was not found or if the response structure is not compliant,
  1309 + * an empty string is returned.
  1310 + ***************************************************************************/
  1311 +std::list<std::string> GVOHub::get_registrations(const GXml& xml,
  1312 + const std::string& name) const
  1313 +{
  1314 + // Declare value
  1315 + std::list<std::string> value;
  1316 +
  1317 + // Search for value of specified member
  1318 + const GXmlNode* node = xml.element("methodCall", 0);
  1319 + const GXmlNode* subnode;
  1320 + const GXmlText* subtext;
  1321 + if (node != NULL) {
  1322 + node = node->element("params", 0);
  1323 + if (node != NULL) {
  1324 + node = node->element("param", 1);
  1325 + if (node != NULL) {
  1326 + node = node->element("value", 0);
  1327 + if (node != NULL) {
  1328 + node = node->element("struct", 0);
  1329 + if (node != NULL) {
  1330 + int num = node->elements("member");
  1331 + for (int i = 0; i < num; ++i) {
  1332 + /*std::cout << i << std::endl;
  1333 + std::cout << "Affichage du membre\n";
  1334 + std::cout << *(node->element("member", i)) << std::cout;*/
  1335 + subnode = node->element("member", i);
  1336 + subnode = subnode->element("name", 0);
  1337 + //std::cout << node->element("member",i)->element("name", 0)->print(NORMAL,0) << std::cout;
  1338 + const GXmlText* text = static_cast<const GXmlText*>((*subnode)[0]);
  1339 + if (text != NULL) {
  1340 + value.push_front(text->text());
  1341 + }
  1342 + }
  1343 + }
  1344 + }
  1345 +
  1346 + }
  1347 +
  1348 + }
  1349 + }
  1350 +
  1351 + // Return value
  1352 + return value;
  1353 +}
  1354 +/***********************************************************************//**
  1355 + * @brief Returns value for a SAMP client query parameter
  1356 + *
  1357 + * @param[in] xml client query XML document.
  1358 + * @param[in] name Parameter name.
  1359 + * @return Parameter value.
  1360 + *
  1361 + * Returns value for a SAMP client query parameter. If the specified
  1362 + * parameter was not found or if the response structure is not compliant,
  1363 + * an empty string is returned.
  1364 + ***************************************************************************/
  1365 +std::string GVOHub::get_callback_port(const GXml& xml,
  1366 + const std::string& name) const
  1367 +{
  1368 + // Declare value
  1369 + std::string value;
  1370 +
  1371 + // Search for value of specified member
  1372 + const GXmlNode* node = xml.element("methodCall", 0);
  1373 + const GXmlNode* subnode;
  1374 + const GXmlText* subtext;
  1375 + if (node != NULL) {
  1376 + node = node->element("params", 0);
  1377 + if (node != NULL) {
  1378 + subnode = node->element("param", 0);
  1379 + if (subnode != NULL) {
  1380 + subnode = subnode->element("value", 0);
  1381 + if (subnode != NULL) {
  1382 + const GXmlText* text = static_cast<const GXmlText*>((*subnode)[0]);
  1383 + /*if (text != NULL) {
  1384 + value = text->text();
  1385 + value.append(" port : ");
  1386 + }*/
  1387 + }
  1388 + }
  1389 + subnode = node->element("param", 1);
  1390 + if (subnode != NULL) {
  1391 + subnode = subnode->element("value", 0);
  1392 + if (subnode != NULL) {
  1393 + const GXmlText* text = static_cast<const GXmlText*>((*subnode)[0]);
  1394 + if (text != NULL) {
  1395 + value.append(text->text());
  1396 + }
  1397 + }
  1398 + }
  1399 + }
  1400 + }
  1401 +
  1402 + // Return value
  1403 + return value;
  1404 +}
  1405 +/***********************************************************************//**
  1406 + * @brief Extract name / value pair from XML node
  1407 + *
  1408 + * @param[in] node Pointer to XML node.
  1409 + * @param[out] name Name string.
  1410 + * @param[out] value Value string.
  1411 + *
  1412 + * Extracts a name / value pair from a XML node. If the XML node pointer is
  1413 + * NULL, the name and value strings will be empty.
  1414 + ***************************************************************************/
  1415 +void GVOHub::get_name_value_pair(const GXmlNode* node,
  1416 + std::string& name,
  1417 + std::string& value) const
  1418 +{
  1419 + // Clear name and value strings
  1420 + name.clear();
  1421 + value.clear();
  1422 +
  1423 + // Continue only if node is valid
  1424 + if (node != NULL) {
  1425 +
  1426 + // Get name node and extract text content
  1427 + const GXmlNode* ptr = node->element("name", 0);
  1428 + if (ptr != NULL) {
  1429 + const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
  1430 + if (text != NULL) {
  1431 + name = text->text();
  1432 + }
  1433 + }
  1434 +
  1435 + // Get value node and extract text content
  1436 + ptr = node->element("value", 0);
  1437 + if (ptr != NULL) {
  1438 + const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
  1439 + if (text != NULL) {
  1440 + value = text->text();
  1441 + }
  1442 + }
  1443 + }
  1444 +
  1445 + // Return
  1446 + return;
  1447 +}
  1448 +
  1449 +/***********************************************************************//**
  1450 + * @brief Post string content to Hub
  1451 + *
  1452 + * @param[in] content String content to post
  1453 + *
  1454 + * Posts the content of a string to the Hub.
  1455 + *
  1456 + * The method does nothing if no Hub connection has been established.
  1457 + ***************************************************************************/
  1458 +void GVOHub::post_string(const std::string& content,const socklen_t& sock) const
  1459 +{
  1460 + // Continue only if Hub connection has been established
  1461 + if (sock != -1) {
  1462 +
  1463 + // Determine content length
  1464 + int length = content.length();
  1465 +
  1466 + // Set prefix
  1467 + std::string prefix = "HTTP/1.1 200 OK\n"
  1468 + "Connection: close\n"
  1469 + "Content-Type: text/xml\n"
  1470 + "Content-Length: "+gammalib::str(length)+"\n\n";
  1471 +
  1472 + // Build post string
  1473 + std::string post = prefix + content;
  1474 + #if GVO_HUB_testing == 1
  1475 + printf(post.c_str());
  1476 + #endif
  1477 + // Send content to socket
  1478 + bool done = false;
  1479 + do {
  1480 + int length = post.length();
  1481 + int sent_length = send(sock, post.c_str(), length, 0);
  1482 + //printf("Sent through socket: \n %s",post.c_str());
  1483 + if (sent_length < length) {
  1484 + post = post.substr(sent_length, std::string::npos);
  1485 + }
  1486 + else {
  1487 + done = true;
  1488 + }
  1489 + } while (!done);
  1490 +
  1491 + } // endif: Hub connection had been established
  1492 + // Return
  1493 + return;
  1494 +}
  1495 +/***********************************************************************//**
  1496 + * @brief Receive string content from Hub
  1497 + *
  1498 + * @return String received from Hub.
  1499 + *
  1500 + * Reads information sent by Hub into a string.
  1501 + *
  1502 + * The method does nothing if no Hub connection has been established.
  1503 + ***************************************************************************/
  1504 +std::string GVOHub::receive_string(const socklen_t& sock) const
  1505 +{
  1506 + // Initialise empty string
  1507 + std::string result = "";
  1508 +
  1509 + // Continue only if Hub connection has been established
  1510 + printf("sock = %d\n",sock);
  1511 + if (sock != -1) {
  1512 +
  1513 + // Define buffer
  1514 + char buffer[4097];
  1515 +
  1516 + // Read buffer until it is empty
  1517 + int n = 0;
  1518 + int m = 0;
  1519 + //do {
  1520 +
  1521 + printf("reading socket\n");
  1522 + n = recv(sock, buffer, 4096,0);
  1523 + printf("%d octets received: message %s\n",n,buffer);
  1524 + fflush(stdout);
  1525 + if (n > 0) {
  1526 + //buffer[n+1] = '\0';
  1527 + result.append(std::string(buffer));
  1528 + }
  1529 +
  1530 + printf("reading socket\n");
  1531 + m = recv(sock, buffer, 4096,0);
  1532 + printf("%d octets received: message %s\n",n,buffer);
  1533 + fflush(stdout);
  1534 + if (n > 0) {
  1535 + buffer[n+m+1] = '\0';
  1536 + result.append(std::string(buffer));
  1537 + }
  1538 + //} while (n > 0);
  1539 +
  1540 + } // endif: Hub connection had been established
  1541 + printf("receive_string now returning\n");
  1542 + fflush(stdout);
  1543 + // Return result
  1544 + return result;
  1545 +}
  1546 +/***********************************************************************//**
  1547 + * @brief Returns value for a SAMP client query parameter
  1548 + *
  1549 + * @param[in] xml client query XML document.
  1550 + * @param[in] name Parameter name.
  1551 + * @return Parameter value.
  1552 + *
  1553 + * Returns value for a SAMP client query parameter. If the specified
  1554 + * parameter was not found or if the response structure is not compliant,
  1555 + * an empty string is returned.
  1556 + ***************************************************************************/
  1557 +std::list<std::string> GVOHub::get_clientid(const GXml& xml,
  1558 + const std::string& name) const
  1559 +{
  1560 + // Declare value
  1561 + std::list<std::string> value;
  1562 +
  1563 + // Search for value of specified member
  1564 + const GXmlNode* node = xml.element("methodCall", 0);
  1565 + const GXmlNode* subnode;
  1566 + const GXmlText* subtext;
  1567 + if (node != NULL) {
  1568 + node = node->element("params", 0);
  1569 + if (node != NULL) {
  1570 + node = node->element("param", 1);
  1571 + if (node != NULL) {
  1572 + node = node->element("value", 0);
  1573 + //std::cout << node->element("member",i)->element("name", 0)->print(NORMAL,0) << std::cout;
  1574 + const GXmlText* text = static_cast<const GXmlText*>((*node)[0]);
  1575 + if (text != NULL) {
  1576 + value.push_front(text->text());
  1577 + #if GVO_HUB_testing == 1
  1578 + std::cout << "Client id for which information is seeked:" + text->text() + "\n";
  1579 + #endif
  1580 + }
  1581 + }
  1582 + }
  1583 + }
  1584 +
  1585 +
  1586 + // Return value
  1587 + return value;
  1588 +}
  1589 +/***********************************************************************//**
  1590 + * @brief
  1591 + *
  1592 + * @param[in]
  1593 + *
  1594 + *
  1595 + ***************************************************************************/
  1596 +std::string GVOHub::random_string( size_t length )
  1597 +{
  1598 + srand(time(0));
  1599 + std::string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  1600 + int pos;
  1601 + while(str.size() != length) {
  1602 + pos = ((rand() % (str.size() - 1)));
  1603 + str.erase (pos, 1);
  1604 + }
  1605 + return str;
  1606 +}
  1607 +
  1608 +/***********************************************************************//**
  1609 + * @brief Test if any registered client needs to know that the method
  1610 + has been called
  1611 + *
  1612 + * @param[in] method: name of the method, cl_id id of calling client
  1613 + *
  1614 + *
  1615 + *
  1616 + *
  1617 + ***************************************************************************/
  1618 +void GVOHub::activate_callbacks(std::string method,char cl_id[31])
  1619 +{
  1620 + int i,j,k;
  1621 + char port[16];
  1622 + char pkey[16];
  1623 + std::string spkey;
  1624 +
  1625 + for (i = 0; i < GVOHUB_NB_CLIENTS; i++) {
  1626 + for (j = 0; j < GVOHUB_NB_METHODS; j++) {
  1627 + if (strcmp("",reg_clients->metadatas[i].registered_methods[j]) == 0) {
  1628 + continue;
  1629 + } else {
  1630 + //printf("Comparing %s and %s \n",method.c_str(),reg_clients->metadatas[i].registered_methods[j]);
  1631 + if (strcmp(method.c_str(),reg_clients->metadatas[i].registered_methods[j]) == 0) {
  1632 + strcpy(port,reg_clients->metadatas[i].port);
  1633 + printf("Callback needed on port %s\n",port);
  1634 + std::string port_string = std::string(port);
  1635 + //Eliminate http://127.0.0.1/ from port string -----> improve this code is necessary
  1636 + port_string.replace(0,17,"");
  1637 + printf("Callback needed on port %s\n",port_string.c_str());
  1638 + std::size_t pos = port_string.find("/");
  1639 + std::string port_only = port_string.substr(0,pos);
  1640 + printf("%s\n",port_only.c_str());
  1641 + // Set hints
  1642 + struct addrinfo hints;
  1643 + std::memset(&hints, 0, sizeof(hints));
  1644 + hints.ai_family = AF_INET;
  1645 + hints.ai_socktype = SOCK_STREAM;
  1646 +
  1647 + // Get server information
  1648 + struct addrinfo* servinfo;
  1649 + if (getaddrinfo("127.0.0.1", port_only.c_str(),
  1650 + &hints, &servinfo) == 0) {
  1651 +
  1652 + // Loop through all the results and connect to the first
  1653 + // we can
  1654 + for (struct addrinfo* ptr = servinfo; ptr != NULL; ptr = ptr->ai_next) {
  1655 +
  1656 + // Create socket
  1657 + cback_socket = socket(ptr->ai_family,
  1658 + ptr->ai_socktype,
  1659 + ptr->ai_protocol);
  1660 +
  1661 + // Connect to socket if socket is valid
  1662 + if (cback_socket != -1) {
  1663 + if (::connect(cback_socket,
  1664 + ptr->ai_addr,
  1665 + ptr->ai_addrlen) == -1) {
  1666 + close(cback_socket);
  1667 + cback_socket = -1;
  1668 + }
  1669 + }
  1670 +
  1671 + } // endfor: looped through all results
  1672 +
  1673 + } // endif: server information was valid
  1674 + std::string msg_cback = "";
  1675 +
  1676 + if (strcmp(method.c_str(),"samp.hub.event.register") == 0) {
  1677 + // Set methodResponse elts for samp.hub.event.register
  1678 + msg_cback.append("<?xml version=\"1.0\"?>\n");
  1679 +
  1680 + msg_cback.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");
  1681 + msg_cback.append("\t<params>\n");
  1682 + msg_cback.append("\t\t<param><value>");
  1683 + msg_cback.append(reg_clients->metadatas[i].private_key);
  1684 + msg_cback.append("</value></param>\n");
  1685 + msg_cback.append("\t\t<param><value>"+m_hub_id+"</value></param>\n");
  1686 + msg_cback.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  1687 + msg_cback.append("\t\t\t\t\t<member><name>samp.mtype</name><value>samp.hub.event.register</value></member>\n");
  1688 + msg_cback.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>");
  1689 + msg_cback.append("<name>id</name><value>");
  1690 + msg_cback.append(cl_id);
  1691 + msg_cback.append("</value></member>\n\t\t\t\t\t\t</struct>\n\t\t\t\t\t</value></member>\n");
  1692 + msg_cback.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  1693 + msg_cback.append("\t</params>\n");
  1694 +
  1695 + msg_cback.append("</methodCall>\n");
  1696 + post_string_toclient(msg_cback);
  1697 + }
  1698 + if (strcmp(method.c_str(),"samp.hub.event.unregister") == 0) {
  1699 + // Set methodResponse elts for samp.hub.event.unregister
  1700 + msg_cback.append("<?xml version=\"1.0\"?>\n");
  1701 +
  1702 + msg_cback.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");
  1703 + msg_cback.append("\t<params>\n");
  1704 + msg_cback.append("\t\t<param><value>");
  1705 + msg_cback.append(reg_clients->metadatas[i].private_key);
  1706 + msg_cback.append("</value></param>\n");
  1707 + msg_cback.append("\t\t<param><value>"+m_hub_id+"</value></param>\n");
  1708 + msg_cback.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  1709 + msg_cback.append("\t\t\t\t\t<member><name>samp.mtype</name><value>samp.hub.event.unregister</value></member>\n");
  1710 + msg_cback.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>");
  1711 + msg_cback.append("<name>id</name><value>");
  1712 + msg_cback.append(cl_id);
  1713 + msg_cback.append("</value></member>\n\t\t\t\t\t\t</struct>\n\t\t\t\t\t</value></member>\n");
  1714 + msg_cback.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  1715 + msg_cback.append("\t</params>\n");
  1716 +
  1717 + msg_cback.append("</methodCall>\n");
  1718 + post_string_toclient(msg_cback);
  1719 +
  1720 + }
  1721 + if (strcmp(method.c_str(),"samp.hub.event.metadata") == 0) {
  1722 + // Set methodResponse elts for samp.hub.event.unregister
  1723 + msg_cback.append("<?xml version=\"1.0\"?>\n");
  1724 +
  1725 + msg_cback.append("<methodCall><methodName>samp.client.receiveNotification</methodName>\n");
  1726 + msg_cback.append("\t<params>\n");
  1727 + msg_cback.append("\t\t<param><value>");
  1728 + msg_cback.append(reg_clients->metadatas[i].private_key);
  1729 + msg_cback.append("</value></param>\n");
  1730 + msg_cback.append("\t\t<param><value>"+m_hub_id+"</value></param>\n");
  1731 + msg_cback.append("\t\t<param>\n\t\t\t<value>\n\t\t\t\t<struct>\n");
  1732 + msg_cback.append("\t\t\t\t\t<member><name>samp.mtype</name><value>samp.hub.event.metadata</value></member>\n");
  1733 + msg_cback.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");
  1734 + msg_cback.append("\t\t\t\t\t<member><name>id</name><value>");
  1735 + for (k = 0; k < GVOHUB_NB_CLIENTS; k++) {
  1736 + if (strcmp(cl_id,reg_clients->metadatas[k].reference) == 0) {
  1737 + break;
  1738 + }
  1739 + }
  1740 + msg_cback.append(reg_clients->metadatas[k].reference);
  1741 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1742 + msg_cback.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");
  1743 + msg_cback.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>");
  1744 + msg_cback.append(reg_clients->metadatas[k].name);
  1745 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1746 + msg_cback.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>");
  1747 + msg_cback.append(reg_clients->metadatas[k].description);
  1748 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1749 + msg_cback.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>");
  1750 + msg_cback.append(reg_clients->metadatas[k].icon);
  1751 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1752 + msg_cback.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>");
  1753 + msg_cback.append(reg_clients->metadatas[k].documentation);
  1754 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1755 + msg_cback.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>");
  1756 + msg_cback.append(reg_clients->metadatas[k].affiliation);
  1757 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1758 + msg_cback.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>");
  1759 + msg_cback.append(reg_clients->metadatas[k].email);
  1760 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1761 + msg_cback.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>");
  1762 + msg_cback.append(reg_clients->metadatas[k].author_name);
  1763 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1764 + msg_cback.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>");
  1765 + msg_cback.append(reg_clients->metadatas[k].homepage);
  1766 + msg_cback.append("</value>\n\t\t\t\t\t</member>\n");
  1767 + msg_cback.append("</struct></value></member>\n");
  1768 + msg_cback.append("</struct>\n\t\t\t\t\t</value></member>\n");
  1769 + msg_cback.append("\t\t\t\t</struct>\n\t\t\t</value>\n\t\t</param>\n");
  1770 + msg_cback.append("\t</params>\n");
  1771 +
  1772 + msg_cback.append("</methodCall>\n");
  1773 + post_string_toclient(msg_cback);
  1774 +
  1775 + }
  1776 +
  1777 +
  1778 +
  1779 + }
  1780 + }
  1781 + }
  1782 +
  1783 + }
  1784 +}
  1785 +/***********************************************************************//**
  1786 + * @brief Post string content to Hub
  1787 + *
  1788 + * @param[in] content String content to post
  1789 + *
  1790 + * Posts the content of a string to the Hub.
  1791 + *
  1792 + * The method does nothing if no Hub connection has been established.
  1793 + ***************************************************************************/
  1794 +void GVOHub::post_string_toclient(const std::string& content) const
  1795 +{
  1796 + // Continue only if Hub connection has been established
  1797 + if (cback_socket != -1) {
  1798 +
  1799 + // Determine content length
  1800 + int length = content.length();
  1801 +
  1802 + // Set prefix
  1803 + std::string prefix = "POST /xmlrpc HTTP/1.1\n"
  1804 + "Connection: keep-alive\n"
  1805 + "User-Agent: GammaLib\n"
  1806 + "Host: localhost:"+gammalib::str(cback_socket)+"\n"
  1807 + "Content-Type: text/xml\n"
  1808 + "Content-Length: "+gammalib::str(length)+"\n\n";
  1809 +
  1810 + // Build post string
  1811 + std::string post = prefix + content;
  1812 +
  1813 + // Send content to socket
  1814 + bool done = false;
  1815 + do {
  1816 + int length = post.length();
  1817 + int sent_length = send(cback_socket, post.c_str(), length, 0);
  1818 + #if GVO_HUB_testing == 1
  1819 + printf("Send to client: %s\n",post.c_str());
  1820 + #endif
  1821 + if (sent_length < length) {
  1822 + post = post.substr(sent_length, std::string::npos);
  1823 + }
  1824 + else {
  1825 + done = true;
  1826 + }
  1827 + } while (!done);
  1828 +
  1829 + // Read buffer until it is empty
  1830 + char buffer[1001];
  1831 + int n = 0;
  1832 + do {
  1833 + printf("receive socket instruction from callback response\n");
  1834 + fflush(stdout);
  1835 + n = recv(cback_socket, buffer, 1000, 0);
  1836 + printf("data received: %s\n",buffer);
  1837 + fflush(stdout);
  1838 + if (n > 0) {
  1839 + buffer[n+1] = '\0';
  1840 +
  1841 + }
  1842 + } while (n > 0);
  1843 + /*printf("%s",buffer);
  1844 + // Declare message
  1845 + std::string msg = "";
  1846 +
  1847 + // Set methodResponse elts
  1848 + msg.append("<?xml version=\"1.0\"?>\n");
  1849 + msg.append("<methodResponse>\n");
  1850 + msg.append("\t<params>\n");
  1851 + msg.append("\t\t<param>\n\t\t\t<value/>\n\t\t</param>\n");
  1852 + msg.append("\t</params>\n");
  1853 + msg.append("</methodResponse>\n");
  1854 +
  1855 +
  1856 +
  1857 + post_string(msg,cback_socket);*/
  1858 + } // endif: Hub connection had been established
  1859 +
  1860 + // Return
  1861 + return;
  1862 +}
  1863 +
... ...
src/vo/Makefile.am
... ... @@ -6,7 +6,9 @@ INCLUDES = -I$(top_srcdir)/include \
6 6 -I$(top_srcdir)/src/support
7 7  
8 8 # Define sources for this directory
9   -sources = GVOClient.cpp
  9 +sources = GVOClient.cpp \
  10 + GVOHub.cpp \
  11 + GVOApp.cpp
10 12  
11 13 # Build libtool library
12 14 noinst_LTLIBRARIES = libvo.la
... ...
test/test_GVO.cpp
1 1 /***************************************************************************
2   - * test_GVO.hpp - Test VO module *
  2 + * test_GVO.cpp - Test VO module *
3 3 * ----------------------------------------------------------------------- *
4 4 * copyright (C) 2013-2015 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
... ... @@ -28,11 +28,27 @@
28 28 #ifdef HAVE_CONFIG_H
29 29 #include <config.h>
30 30 #endif
  31 +#include <pthread.h>
31 32 #include "test_GVO.hpp"
32 33 #include "GTools.hpp"
33 34  
34 35  
35 36 /***********************************************************************//**
  37 + * @brief Thread start routine to test GVOHub class
  38 + *
  39 + * @param[in] ptr Start routine argument.
  40 + **************************************************************************/
  41 +void* vo_thread(void* ptr)
  42 +{
  43 + // Create VO Hub
  44 + GVOHub hub;
  45 +
  46 + // Return
  47 + return NULL;
  48 +}
  49 +
  50 +
  51 +/***********************************************************************//**
36 52 * @brief Set parameters and tests
37 53 **************************************************************************/
38 54 void TestGVO::set(void)
... ... @@ -41,6 +57,7 @@ void TestGVO::set(void)
41 57 name("GVO");
42 58  
43 59 // Append tests
  60 + append(static_cast<pfunction>(&TestGVO::test_GVOHub), "Test GVOHub class");
44 61 append(static_cast<pfunction>(&TestGVO::test_GVOClient), "Test GVOClient class");
45 62  
46 63 // Return
... ... @@ -61,6 +78,51 @@ TestGVO* TestGVO::clone(void) const
61 78  
62 79  
63 80 /***********************************************************************//**
  81 + * @brief Test VO hub class
  82 + **************************************************************************/
  83 +void TestGVO::test_GVOHub(void)
  84 +{
  85 + // Start Hub
  86 + test_try("Start hub");
  87 + try {
  88 + pthread_t thread;
  89 +std::cout << "Start thread now" << std::endl;
  90 + int rc = pthread_create(&thread, NULL, vo_thread, NULL);
  91 +std::cout << "Thread started" << std::endl;
  92 + test_try_success();
  93 + }
  94 + catch (std::exception &e) {
  95 + test_try_failure(e);
  96 + }
  97 +
  98 + // Test Hub connection
  99 + test_try("GVOClient hub connection and disconnection");
  100 + try {
  101 + for (int i = 0; i < 3; ++i) {
  102 + sleep(1);
  103 +std::cout << "*** Try to connect client" << std::endl;
  104 + GVOClient client;
  105 + client.connect();
  106 +std::cout << "*** called client.connect" << std::endl;
  107 + if (client.is_connected()) {
  108 + break;
  109 + }
  110 + std::cout << client << std::endl;
  111 + }
  112 + //test_try_failure();
  113 + test_try_success();
  114 + }
  115 + catch (std::exception &e) {
  116 + //test_try_success();
  117 + test_try_failure(e);
  118 + }
  119 +
  120 + // Return
  121 + return;
  122 +}
  123 +
  124 +
  125 +/***********************************************************************//**
64 126 * @brief Test VO client class
65 127 **************************************************************************/
66 128 void TestGVO::test_GVOClient(void)
... ...
test/test_GVO.hpp
1 1 /***************************************************************************
2 2 * test_GVO.hpp - Test VO module *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2013-2014 by Juergen Knoedlseder *
  4 + * copyright (C) 2013-2015 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -47,6 +47,7 @@ public:
47 47 virtual void set(void);
48 48 virtual TestGVO* clone(void) const;
49 49 virtual std::string classname(void) const { return "TestGVO"; }
  50 + void test_GVOHub(void);
50 51 void test_GVOClient(void);
51 52  
52 53 private:
... ...