get_sockets_set added for external select() calls. Boost test case added to check...
authorCamilo Roca <camilo.roca@intra2net.com>
Wed, 10 Jul 2013 08:52:56 +0000 (10:52 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Wed, 10 Jul 2013 09:31:50 +0000 (11:31 +0200)
src/socket_handler.hxx
src/socket_server.cpp
src/socket_server.hxx
test/CMakeLists.txt
test/getsocket.cpp [new file with mode: 0644]

index c3522d8..b6776ec 100644 (file)
@@ -70,6 +70,9 @@ class socket_handler
         socket_type_value get_type()
             { return socket_type; }
 
+        int get_socket()
+            { return sock; }
+
         bool is_closed();
 
         void set_recv_buffer_size(unsigned int new_recv_buffer_size);
index 18bb722..1d18fd2 100644 (file)
@@ -165,6 +165,7 @@ void socket_server::start_listening()
     /* clear & insert server sock into the fd_tab to prepare select */
     FD_ZERO(&connection_set);
     FD_SET (sock, &connection_set);
+    sockets_set.insert(sock);
 }
 
 /// handle a new connection from a client
@@ -190,6 +191,7 @@ void socket_server::new_connection()
     }
 
     FD_SET (newsock, &connection_set);
+    sockets_set.insert(newsock);
 
     socket_server_connection *nc=new socket_server_connection(newsock, get_type(), get_default_timeout());
     nc->set_socket_options(newsock);
@@ -287,6 +289,7 @@ bool socket_server::fill_connection_buffers()
 void socket_server::remove_connection_socket(int sock)
 {
     FD_CLR(sock, &connection_set);
+    sockets_set.erase(sock);
 }
 
 /**
index ae30833..74d8e07 100644 (file)
@@ -24,6 +24,7 @@ on this file might be covered by the GNU General Public License.
 
 #include <sys/types.h>
 #include <string>
+#include <set>
 
 #include "server.hxx"
 #include "socket_handler.hxx"
@@ -48,6 +49,7 @@ class socket_server : public socket_handler, public server
     private:
         fd_set connection_set;
         std::string unix_path;
+        std::set<int> sockets_set;
 
         void start_listening();
 
@@ -67,6 +69,8 @@ class socket_server : public socket_handler, public server
         ~socket_server();
 
         bool fill_buffer(long long usec_timeout=-1,long long* usec_timeout_remaining=NULL);
+        std::set<int> get_sockets_set()
+            { return sockets_set; };
 };
 
 /** @brief Socket based connection
index 66f7e7a..8037493 100644 (file)
@@ -11,6 +11,7 @@ set(test_SOURCES
     simplecmd.cpp
     timeout.cpp
     wrapper.cpp
+    getsocket.cpp
     test_fixtures.hxx
 )
 include_directories(BEFORE
diff --git a/test/getsocket.cpp b/test/getsocket.cpp
new file mode 100644 (file)
index 0000000..96964cb
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+Copyright (C) 2004 by Intra2net AG
+
+The software in this package is distributed under the GNU General
+Public License version 2 (with a special exception described below).
+
+A copy of GNU General Public License (GPL) is included in this distribution,
+in the file COPYING.GPL.
+
+As a special exception, if other files instantiate templates or use macros
+or inline functions from this file, or you compile this file and link it
+with other works to produce a work based on this file, this file
+does not by itself cause the resulting work to be covered
+by the GNU General Public License.
+
+However the source code for this file must still be made available
+in accordance with section (3) of the GNU General Public License.
+
+This exception does not invalidate any other reasons why a work based
+on this file might be covered by the GNU General Public License.
+*/
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+#include <set>
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/serialization/serialization.hpp>
+
+#include <container.hxx>
+#include <socket_client.hxx>
+#include <socket_server.hxx>
+#include <command_client.hxx>
+#include <command_server.hxx>
+
+#include "test_fixtures.hxx"
+
+using namespace std;
+
+set<int> SocketSet;
+
+bool check_sockets(const int& test_socket)
+{
+    bool ret = false;
+    set<int>::iterator it;
+    for (it = SocketSet.begin(); it != SocketSet.end(); it++)
+    {
+        if (test_socket == *it)
+        {
+            ret = true;
+            break;
+        }
+    }
+    return ret;
+}
+
+class checkfunc_res : public libt2n::result
+{
+    private:
+        bool res;
+
+        friend class boost::serialization::access;
+        template<class Archive>
+        void serialize(Archive & ar, const unsigned int version)
+        {
+            ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
+            ar & BOOST_SERIALIZATION_NVP(res);
+        }
+
+    public:
+        checkfunc_res()
+            { }
+
+        checkfunc_res(const bool& value)
+        {
+            res=value;
+        }
+
+        bool get_data()
+        {
+            return res;
+        }
+};
+
+
+class checkfunc_cmd : public libt2n::command
+{
+    private:
+        int param;
+
+        friend class boost::serialization::access;
+        template<class Archive>
+        void serialize(Archive & ar, const unsigned int version)
+        {
+            ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
+            ar & BOOST_SERIALIZATION_NVP(param);
+        }
+
+    public:
+        checkfunc_cmd()
+            {}
+
+        checkfunc_cmd(const int& value)
+        {
+            param=value;
+        }
+
+        libt2n::result* operator()()
+        {
+            return new checkfunc_res(check_sockets(param));
+        }
+};
+
+#include <boost/serialization/export.hpp>
+
+BOOST_CLASS_EXPORT(checkfunc_cmd)
+BOOST_CLASS_EXPORT(checkfunc_res)
+
+using namespace libt2n;
+
+BOOST_FIXTURE_TEST_SUITE(test_getsocket, KillChildOnShutdownFixture)
+
+BOOST_AUTO_TEST_CASE(SocketCheck)
+{
+    switch(child_pid=fork())
+    {
+        case -1:
+        {
+            BOOST_FAIL("fork error");
+            break;
+        }
+        case 0:
+        // child
+        {
+            try
+            {
+                socket_server ss("./socket");
+                command_server cs(ss);
+
+                // max 10 sec
+                for (int i=0; i < 10; i++)
+                {
+                    SocketSet = ss.get_sockets_set();
+                    cs.handle(1000000);
+                }
+            } catch(...)
+            {
+                std::cerr << "exception in child. ignoring\n";
+            }
+
+            // don't call atexit and stuff
+            _exit(0);
+        }
+
+        default:
+        // parent
+        {
+            // wait till server is up
+            sleep(1);
+            socket_client_connection sc("./socket");
+            sc.set_logging(&cerr,debug);
+            command_client cc(&sc);
+
+            result_container rc;
+            int socket_fd = sc.get_socket();
+            // Next line causes problem
+            cc.send_command(new checkfunc_cmd(socket_fd),rc);
+
+            bool ret=dynamic_cast<checkfunc_res*>(rc.get_result())->get_data();
+
+            BOOST_CHECK(ret);
+        }
+    }
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()