diff --git a/include/GVOHub.hpp b/include/GVOHub.hpp index 9a6339a..2445cf1 100644 --- a/include/GVOHub.hpp +++ b/include/GVOHub.hpp @@ -1,7 +1,7 @@ /*************************************************************************** - * GVOHub.hpp - VO SAMP Hub class * + * GVOHub.hpp - VO SAMP Hub class * * ----------------------------------------------------------------------- * - * copyright (C) 2014 by Juergen Knoedlseder & Thierry Louge * + * copyright (C) 2014 by Thierry Louge * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * @@ -21,7 +21,7 @@ /** * @file GVOHub.hpp * @brief SAMP hub class interface definition - * @author Juergen Knoedlseder, Thierry Louge + * @author Thierry Louge */ #ifndef GVOHUB_HPP @@ -43,38 +43,40 @@ * This class implements a SAMP hub for exchanges * through VO-compatible applications. ***************************************************************************/ -class GVOHub { +class GVOHub : public GBase { public: // Constructors and destructors GVOHub(void); - //GVOHub(const GVOHub& hub); + GVOHub(const GVOHub& hub); virtual ~GVOHub(void); // Operators GVOHub& operator=(const GVOHub& hub); // Methods - //void clear(void); - //GVOHub* clone(void) const; + void clear(void); + GVOHub* clone(void) const; + void start(void); + std::string print(const GChatter& chatter = NORMAL) const; //void connect(void); //void disconnect(void); //bool has_hub(void) const; //bool is_connected(void) const; //GXml response(void) const; - //std::string print(const GChatter& chatter = NORMAL) const; protected: // Protected methods void init_members(void); - void init_hub(void); - int start_hub(void); - //void free_members(void); + void copy_members(const GVOHub& client); + void free_members(void); + void init_hub(void); + void start_hub(void); //bool find_hub(void); //void connect_to_hub(void); void register_service(void); void unregister(void); - void handle_request(socklen_t); + void handle_request(const socklen_t& sock); //void send_metadata(void); // Low-level methods diff --git a/pyext/GVOHub.i b/pyext/GVOHub.i index 72f0bfc..a8fb557 100644 --- a/pyext/GVOHub.i +++ b/pyext/GVOHub.i @@ -1,7 +1,7 @@ /*************************************************************************** - * GVOHub.i - VO Hub class * + * GVOHub.i - VO SAMP Hub class * * ----------------------------------------------------------------------- * - * copyright (C) 2014 by Juergen Knoedlseder * + * copyright (C) 2014 by Thierry Louge * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * @@ -20,8 +20,8 @@ ***************************************************************************/ /** * @file GVOHub.i - * @brief VO Hub class interface definition - * @author Juergen Knoedlseder + * @brief SAMP hub class interface definition + * @author Thierry Louge */ %{ /* Put headers and other declarations here that are needed for compilation */ @@ -39,12 +39,12 @@ public: // Constructors and destructors // Constructors and destructors GVOHub(void); - //GVOHub(const GVOHub& hub); + GVOHub(const GVOHub& hub); virtual ~GVOHub(void); // Methods - //void clear(void); - //GVOHub* clone(void) const; + void clear(void); + GVOHub* clone(void) const; //void connect(void); //void disconnect(void); //bool has_hub(void) const; diff --git a/src/vo/GVOHub.cpp b/src/vo/GVOHub.cpp index 5193e44..8c3070f 100644 --- a/src/vo/GVOHub.cpp +++ b/src/vo/GVOHub.cpp @@ -1,7 +1,7 @@ /*************************************************************************** - * GVOHub.hpp - VO SAMP Hub class * + * GVOHub.hpp - VO SAMP Hub class * * ----------------------------------------------------------------------- * - * copyright (C) 2014 by Juergen Knoedlseder & Thierry Louge * + * copyright (C) 2014 by Thierry Louge * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * @@ -21,7 +21,7 @@ /** * @file GVOHub.cpp * @brief VO SAMP Hub class implementation - * @author Juergen Knoedlseder, Thierry Louge + * @author Thierry Louge */ /* __ Includes ___________________________________________________________ */ @@ -38,6 +38,18 @@ #include "GVOClient.hpp" #include "GException.hpp" #include "GTools.hpp" + +/* __ Method name definitions ____________________________________________ */ +#define G_HANDLE_REQUEST "GVOHub::handle_request(socklen_t)" +#define G_START_HUB "GVOHub::start_hub()" + +/* __ Macros _____________________________________________________________ */ + +/* __ Coding definitions _________________________________________________ */ + +/* __ Debug definitions __________________________________________________ */ + + /*========================================================================== = = = Constructors/destructors = @@ -50,21 +62,30 @@ GVOHub::GVOHub(void) { // Initialise members - printf("Initializing members\n"); init_members(); - // Creates Hub - printf("Creating the hub\n"); - init_hub(); - - // Starts the hub - printf("Starting the hub"); - start_hub(); // Return return; } +/***********************************************************************//** + * @brief Copy constructor + * + * @param[in] hub VO Hub. + ***************************************************************************/ +GVOHub::GVOHub(const GVOHub& hub) +{ + // Initialise members + init_members(); + + // Copy members + copy_members(hub); + + // Return + return; +} + /***********************************************************************//** * @brief Destructor @@ -79,11 +100,88 @@ GVOHub::~GVOHub(void) /*========================================================================== = = + = Operators = + = = + ==========================================================================*/ + +/***********************************************************************//** + * @brief Assignment operator + * + * @param[in] hub VO hub. + * @return VO hub. + ***************************************************************************/ +GVOHub& GVOHub::operator=(const GVOHub& hub) +{ + // Execute only if object is not identical + if (this != &hub) { + + // Free members + free_members(); + + // Initialise members + init_members(); + + // Copy members + copy_members(hub); + + } // endif: object was not identical + + // Return + return *this; +} + + +/*========================================================================== + = = = Public methods = = = ==========================================================================*/ /***********************************************************************//** + * @brief Clear object. + * + * Reset object to a clean initial state. + ***************************************************************************/ +void GVOHub::clear(void) +{ + // Free memory and initialise members + free_members(); + init_members(); + + // Return + return; +} + + +/***********************************************************************//** + * @brief Clone object + ***************************************************************************/ +GVOHub* GVOHub::clone(void) const +{ + // Clone client + return new GVOHub(*this); +} + + +/***********************************************************************//** + * @brief Start Hub + ***************************************************************************/ +void GVOHub::start(void) +{ + // Creates Hub + printf("Creating the hub\n"); + init_hub(); + + // Starts the hub + printf("Starting the hub\n"); + start_hub(); + + // Return + return; +} + + +/***********************************************************************//** * @brief * * @@ -95,6 +193,7 @@ void GVOHub::register_service(void) return; } + /***********************************************************************//** * @brief * @@ -107,31 +206,119 @@ void GVOHub::unregister(void) return; } + +/***********************************************************************//** + * @brief Print VO hub information + * + * @param[in] chatter Chattiness (defaults to NORMAL). + * @return String containing VO hub information + ***************************************************************************/ +std::string GVOHub::print(const GChatter& chatter) const +{ + // Initialise result string + std::string result; + + // Continue only if chatter is not silent + if (chatter != SILENT) { + + // Append header + result.append("=== GVOHub ==="); + + // Append client information + result.append("\n"+gammalib::parformat("Name")+m_name); + + // Append Hub information + result.append("\n"+gammalib::parformat("Hub key")+m_secret); + result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url); + result.append("\n"+gammalib::parformat("Hub host (port)")); + result.append(m_hub_host+" ("+m_hub_port+")"); + result.append("\n"+gammalib::parformat("SAMP protocol version")); + result.append(m_version); + result.append("\n"+gammalib::parformat("Hub connection")); + if (m_socket == -1) { + result.append("no"); + } + else { + if (!m_client_key.empty()) { + result.append("registered as \""+m_client_id); + result.append("\" on Hub \""+m_hub_id); + result.append("\" via socket "+gammalib::str(m_socket)); + } + else { + result.append("established on socket "); + result.append(gammalib::str(m_socket)); + } + } + + } // endif: chatter was not silent + + // Return result + return result; +} + + /*========================================================================== = = = Private methods = = = ==========================================================================*/ + /***********************************************************************//** * @brief Initialise class members ***************************************************************************/ void GVOHub::init_members(void) { // Initialise members - m_name = "GammaLib"; - m_secret = "mysupersecret#0032557sentence"; - m_hub_url = "http://localhost:8001"; + m_name = "GammaLib"; + m_secret = "mysupersecret#0032557sentence"; + m_hub_url = "http://localhost:8001"; m_hub_host = "127.0.0.1"; m_hub_port = "8001"; - m_version = "1.3"; - //m_client_key.clear(); - m_hub_id = "b79884e0"; - //m_client_id.clear(); - //m_socket = -1; // Signals no socket + m_version = "1.3"; + m_client_key.clear(); + m_hub_id = "b79884e0"; + m_client_id.clear(); + m_socket = -1; // Signals no socket + + // Return + return; +} + + +/***********************************************************************//** + * @brief Copy class members + * + * @param[in] hub VO hub. + ***************************************************************************/ +void GVOHub::copy_members(const GVOHub& hub) +{ + // Copy members + m_name = hub.m_name; + m_secret = hub.m_secret; + m_hub_url = hub.m_hub_url; + m_hub_host = hub.m_hub_host; + m_hub_port = hub.m_hub_port; + m_version = hub.m_version; + m_client_key = hub.m_client_key; + m_hub_id = hub.m_hub_id; + m_client_id = hub.m_client_id; + m_socket = hub.m_socket; + + // Return + return; +} + +/***********************************************************************//** + * @brief Delete class members + ***************************************************************************/ +void GVOHub::free_members(void) +{ // Return return; } + + /***********************************************************************//** * @brief Creates the lockfile, fill it * @@ -140,36 +327,42 @@ void GVOHub::init_members(void) ***************************************************************************/ void GVOHub::init_hub(void) { - // Get lockfile URL - std::string lockurl = get_hub_lockfile(); - - // Open SAMP lockfile. Continue only if opening was successful - FILE* fptr = fopen(lockurl.c_str(), "w"); - if (fptr != NULL) { - //If successfull writes basic hub configuration to the lockfile - fputs ("# SAMP lockfile \n# Required keys:\n",fptr); - char sampsecret[256] = "samp.secret= "; - strcat(sampsecret,m_secret.c_str()); - strcat(sampsecret,"\n"); - fputs (sampsecret,fptr); - char sampurl[256] = "samp.hub.xmlrpc.url="; - strcat(sampurl,m_hub_url.c_str()); - strcat(sampurl,"\n"); - fputs (sampurl,fptr); - char samprofile[256] = "samp.profile.version="; - strcat(samprofile,m_version.c_str()); - strcat(samprofile,"\n"); - fputs (samprofile,fptr); - fputs ("# Info stored by hub for some private reason:\n",fptr); - char sampid[256] = "gammalib.hubid="; - strcat(sampid,m_hub_id.c_str()); - strcat(sampid,"\n"); - fputs (sampid,fptr); - } - // Close SAMP lockfile - fclose(fptr); + // Get lockfile URL + std::string lockurl = get_hub_lockfile(); + + // Open SAMP lockfile. Continue only if opening was successful + FILE* fptr = fopen(lockurl.c_str(), "w"); + if (fptr != NULL) { + + // If successfull writes basic hub configuration to the lockfile + fputs ("# SAMP lockfile \n# Required keys:\n",fptr); + char sampsecret[256] = "samp.secret= "; + strcat(sampsecret,m_secret.c_str()); + strcat(sampsecret,"\n"); + fputs (sampsecret,fptr); + char sampurl[256] = "samp.hub.xmlrpc.url="; + strcat(sampurl,m_hub_url.c_str()); + strcat(sampurl,"\n"); + fputs (sampurl,fptr); + char samprofile[256] = "samp.profile.version="; + strcat(samprofile,m_version.c_str()); + strcat(samprofile,"\n"); + fputs (samprofile,fptr); + fputs ("# Info stored by hub for some private reason:\n",fptr); + char sampid[256] = "gammalib.hubid="; + strcat(sampid,m_hub_id.c_str()); + strcat(sampid,"\n"); + fputs (sampid,fptr); + } + + // Close SAMP lockfile + fclose(fptr); + + // Return + return; } + /***********************************************************************//** * @brief Returns SAMP Hub lockfile URL * @@ -220,48 +413,52 @@ std::string GVOHub::get_hub_lockfile(void) const return url; } + /***********************************************************************//** - * @brief reads the client message and runs appropriate function - * - * @return 0 if no problem, 1 if error comes out. + * @brief Reads the client message and runs appropriate function * + * @exception GExpection::invalid_value + * Buffer could not be read or written ***************************************************************************/ -void GVOHub::handle_request (socklen_t sock) +void GVOHub::handle_request(const socklen_t& sock) { - int n; + // Initialize buffer char buffer[256]; - bzero(buffer,256); - n = read(sock,buffer,255); - /*if (n < 0) - { - return(1); - }*/ + // Read buffer + int n = read(sock,buffer,255); + if (n < 0) { + std::string msg = "Could not read socket buffer."; + throw GException::invalid_value(G_HANDLE_REQUEST, msg); + } printf("Here is the message: %s\n",buffer); - //Here, obviously not simple string matching but xml parsing to be done with - //help of GXml object. This is only for architectural purpose. + // Here, obviously not simple string matching but xml parsing to be done with + // help of GXml object. This is only for architectural purpose. if (strcmp(buffer,"register") == 0) { - register_service(); + register_service(); } - //Same for writing, we'll use GXml + + // Same for writing, we'll use GXml n = write(sock,"I got your message",18); - /* -if (n < 0) - { - return(1); + if (n < 0) { + std::string msg = "Could not write socket buffer."; + throw GException::invalid_value(G_HANDLE_REQUEST, msg); } - return(0); - */ + + // Return + return; } + + /***********************************************************************//** * @brief Starts the SAMP hub socket and listens on it * * @return 1 if error comes out, nothing if everything is right (infinite listening loop) * ***************************************************************************/ -int GVOHub::start_hub(void) +void GVOHub::start_hub(void) { struct sockaddr_in serv_addr,cli_addr; int portno,pid; @@ -269,60 +466,56 @@ int GVOHub::start_hub(void) // Prepare TCP/IP structure bzero((char *) &serv_addr, sizeof(serv_addr)); - portno = 8001; - serv_addr.sin_family = AF_INET; + portno = 8001; + serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(portno); - hub_socket = socket(AF_INET, SOCK_STREAM, 0); - if (hub_socket < 0) - { - return(1); + serv_addr.sin_port = htons(portno); + hub_socket = socket(AF_INET, SOCK_STREAM, 0); + if (hub_socket < 0) { + std::string msg = "Socket could not be created."; + throw GException::invalid_value(G_START_HUB, msg); } - //Server socket is opened. Now, bind it to the port, with family etc. - if (bind(hub_socket, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) - { - return(1); + // Server socket is opened. Now, bind it to the port, with family etc. + if (bind(hub_socket, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { + std::string msg = "Could not bind to server socket."; + throw GException::invalid_value(G_START_HUB, msg); } - //Now start listening for the clients: 5 requests simultaneously maximum + // Now start listening for the clients: 5 requests simultaneously maximum listen(hub_socket,5); clilen = sizeof(cli_addr); - while (1) - { + while (1) { + // Accept actual connection from the client +//std::cout << "Now accept connection the socket" << std::endl; newsocket = accept(hub_socket, (struct sockaddr *)&cli_addr, &clilen); - if (newsocket < 0) - { - return(1); +//std::cout << "Connection accepted" << std::endl; + if (newsocket < 0) { + std::string msg = "Client connection to socket not accepted."; + throw GException::invalid_value(G_START_HUB, msg); } + // Create child process to handle the request pid = fork(); - if (pid < 0) - { - return(1); +//std::cout << "Called fork " << pid << std::endl; + if (pid < 0) { + std::string msg = "Not child process created."; + throw GException::invalid_value(G_START_HUB, msg); } - if (pid == 0) - { + if (pid == 0) { // Child process: client process handle_request(newsocket); exit(0); } - else - { + else { +//std::cout << "Now close the socket" << std::endl; close(newsocket); +//std::cout << "Socket closed" << std::endl; } + } -} -/***********************************************************************//** - * @brief For testing purposes only - * - * - ***************************************************************************/ -int main() -{ - GVOHub* myhub = new GVOHub; - return 0; + // Return + return; } - diff --git a/test/test_GVO.cpp b/test/test_GVO.cpp index 78bc50e..fe5ba3e 100644 --- a/test/test_GVO.cpp +++ b/test/test_GVO.cpp @@ -28,6 +28,7 @@ #ifdef HAVE_CONFIG_H #include #endif +#include #include "test_GVO.hpp" #include "GTools.hpp" @@ -35,12 +36,29 @@ /***********************************************************************//** * @brief Set parameters and tests **************************************************************************/ +void* vo_thread(void* ptr) +{ + // Create VO Hub + GVOHub hub; + + // Start Hub. We will never return from this ... + hub.start(); + + // Return + return NULL; +} + + +/***********************************************************************//** + * @brief Set parameters and tests + **************************************************************************/ void TestGVO::set(void) { // Test name name("GVO"); // Append tests + append(static_cast(&TestGVO::test_GVOHub), "Test GHub class"); append(static_cast(&TestGVO::test_GVOClient), "Test GVOClient class"); // Return @@ -61,6 +79,49 @@ TestGVO* TestGVO::clone(void) const /***********************************************************************//** + * @brief Test VO hub class + **************************************************************************/ +void TestGVO::test_GVOHub(void) +{ + // Declare thread + pthread_t thread; + + // Start Hub + test_try("Start hub"); + try { + int rc = pthread_create(&thread, NULL, vo_thread, NULL); + test_try_success(); + } + catch (std::exception &e) { + test_try_failure(e); + } + + // Test Hub connection + test_try("GVOClient hub connection and disconnection"); + try { + for (int i = 0; i < 3; ++i) { + GVOClient client; + client.connect(); + if (client.is_connected()) { + break; + } + std::cout << client << std::endl; + sleep(1); + } + test_try_failure(); + //test_try_success(); + } + catch (std::exception &e) { + test_try_success(); + //test_try_failure(e); + } + + // Return + return; +} + + +/***********************************************************************//** * @brief Test VO client class **************************************************************************/ void TestGVO::test_GVOClient(void) diff --git a/test/test_GVO.hpp b/test/test_GVO.hpp index e6fe93a..f6b8fc7 100644 --- a/test/test_GVO.hpp +++ b/test/test_GVO.hpp @@ -46,6 +46,7 @@ public: // Methods virtual void set(void); virtual TestGVO* clone(void) const; + void test_GVOHub(void); void test_GVOClient(void); private: