First work on Pipe class
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 7 Nov 2005 12:32:01 +0000 (12:32 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 7 Nov 2005 12:32:01 +0000 (12:32 +0000)
src/Makefile.am
src/pipe.cpp [new file with mode: 0644]
src/pipe.hpp [new file with mode: 0644]
src/test_pipe.cpp [new file with mode: 0644]

index 637659d..65192b0 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am,v 1.32 2005-10-31 22:44:55 adam Exp $
+## $Id: Makefile.am,v 1.33 2005-11-07 12:32:01 adam Exp $
 
 MAINTAINERCLEANFILES = Makefile.in config.in config.hpp
 
@@ -22,6 +22,7 @@ libyp2_la_SOURCES = \
        filter_virt_db.cpp filter_virt_db.hpp \
        filter_z3950_client.cpp filter_z3950_client.hpp \
        filter_backend_test.cpp filter_backend_test.hpp \
+       pipe.cpp pipe.hpp \
        util.cpp util.hpp
 
 # Rules for programs..
@@ -38,6 +39,7 @@ ex_router_flexml_SOURCES =  ex_router_flexml.cpp
 
 check_PROGRAMS = \
        test_package1 \
+       test_pipe \
        test_filter1 test_filter2 \
        test_session1 test_session2 \
        test_thread_pool_observer \
@@ -54,6 +56,7 @@ check_PROGRAMS = \
 TESTS=$(check_PROGRAMS)
 
 test_package1_SOURCES=test_package1.cpp
+test_pipe_SOURCES=test_pipe.cpp
 test_filter1_SOURCES=test_filter1.cpp
 test_filter2_SOURCES=test_filter2.cpp
 test_session1_SOURCES=test_session1.cpp
@@ -72,6 +75,8 @@ test_router_flexml_SOURCES = test_router_flexml.cpp
 
 TESTLDADD = $(LDADD) -lboost_unit_test_framework
 
+test_package1_LDADD = $(TESTLDADD)
+test_pipe_LDADD = $(TESTLDADD)
 test_filter1_LDADD = $(TESTLDADD)
 test_filter2_LDADD = $(TESTLDADD)
 test_session1_LDADD = $(TESTLDADD)
@@ -79,7 +84,6 @@ test_session2_LDADD = $(TESTLDADD)
 test_boost_threads_LDADD = $(TESTLDADD)
 test_boost_time_LDADD = $(TESTLDADD)
 test_thread_pool_observer_LDADD = $(TESTLDADD)
-test_package1_LDADD = $(TESTLDADD)
 test_filter_factory_LDADD = $(TESTLDADD)
 test_filter_frontend_net_LDADD = $(TESTLDADD)
 test_filter_log_LDADD = $(TESTLDADD)
diff --git a/src/pipe.cpp b/src/pipe.cpp
new file mode 100644 (file)
index 0000000..f0306f4
--- /dev/null
@@ -0,0 +1,127 @@
+
+/* $Id: pipe.cpp,v 1.1 2005-11-07 12:32:01 adam Exp $
+   Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+#include "config.hpp"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef WIN32
+#include <winsock.h>
+#else
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#endif
+
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+
+#include <stdio.h>
+
+#include <deque>
+
+#include <yaz++/socket-observer.h>
+#include <yaz/log.h>
+
+#include "pipe.hpp"
+
+namespace yp2 {
+    class Pipe::Rep : public boost::noncopyable {
+        friend class Pipe;
+        Rep();
+        int m_fd[2];
+        int m_socket;
+    };
+}
+
+using namespace yp2;
+
+Pipe::Rep::Rep()
+{
+    m_fd[0] = m_fd[1] = -1;
+    m_socket = -1;
+}
+
+Pipe::Pipe(int port_to_use) : m_p(new Rep)
+{
+    if (port_to_use)
+    {
+        m_p->m_socket = socket(AF_INET, SOCK_STREAM, 0);
+        if (m_p->m_socket < 0)
+            throw Pipe::Error("could not create socket");
+
+        m_p->m_fd[1] = socket(AF_INET, SOCK_STREAM, 0);
+        if (m_p->m_fd[1] < 0)
+            throw Pipe::Error("could not create socket");
+        
+        struct sockaddr_in add;
+        add.sin_family = AF_INET;
+        add.sin_port = htons(port_to_use);
+        add.sin_addr.s_addr = INADDR_ANY;
+        struct sockaddr *addr = ( struct sockaddr *) &add;
+        
+        if (bind(m_p->m_socket, addr, sizeof(struct sockaddr_in)))
+            throw Pipe::Error("could not bind on socket");
+        
+        if (listen(m_p->m_socket, 3) < 0)
+            throw Pipe::Error("could not listen on socket");
+
+        struct sockaddr caddr;
+        socklen_t caddr_len = sizeof(caddr);
+        m_p->m_fd[0] = accept(m_p->m_socket, &caddr, &caddr_len);
+        if (m_p->m_fd[0] < 0)
+            throw Pipe::Error("could not accept on socket");
+        
+        if (connect(m_p->m_fd[1], addr, sizeof(addr)) < 0)
+            throw Pipe::Error("could not connect to socket");
+    }
+    else
+    {
+        m_p->m_socket = 0;
+        pipe(m_p->m_fd);
+    }
+}
+
+Pipe::~Pipe()
+{
+    if (m_p->m_fd[0] != -1)
+        close(m_p->m_fd[0]);
+    if (m_p->m_fd[1] != -1)
+        close(m_p->m_fd[1]);
+    if (m_p->m_socket != -1)
+        close(m_p->m_socket);
+}
+
+int &Pipe::read_fd() const
+{
+    return m_p->m_fd[0];
+}
+
+int &Pipe::write_fd() const
+{
+    return m_p->m_fd[1];
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
diff --git a/src/pipe.hpp b/src/pipe.hpp
new file mode 100644 (file)
index 0000000..f5b2378
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id: pipe.hpp,v 1.1 2005-11-07 12:32:01 adam Exp $
+   Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#ifndef YP2_PIPE_HPP
+#define YP2_PIPE_HPP
+
+#include <boost/scoped_ptr.hpp>
+
+#include <yaz/yconfig.h>
+
+namespace yp2 {
+    class Pipe {
+        class Error : public std::runtime_error {
+        public:
+            Error(const std::string msg) 
+                : std::runtime_error("Pipe error: " + msg) {};
+        };
+        class Rep;
+    public:
+        Pipe(int port_to_use);
+        ~Pipe();
+        int &read_fd() const;
+        int &write_fd() const;
+    private:
+        boost::scoped_ptr<Rep> m_p;
+    };
+}
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
diff --git a/src/test_pipe.cpp b/src/test_pipe.cpp
new file mode 100644 (file)
index 0000000..e4f09c8
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id: test_pipe.cpp,v 1.1 2005-11-07 12:32:01 adam Exp $
+   Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#include "config.hpp"
+
+#include <yaz++/socket-manager.h>
+
+#include <iostream>
+#include <stdexcept>
+
+#include "util.hpp"
+#include "pipe.hpp"
+
+#define BOOST_AUTO_TEST_MAIN
+#include <boost/test/auto_unit_test.hpp>
+
+using namespace boost::unit_test;
+
+class My_Timer_Thread : public yazpp_1::ISocketObserver {
+private:
+    yazpp_1::ISocketObservable *m_obs;
+    yp2::Pipe m_pipe;
+    bool m_timeout;
+public:
+    My_Timer_Thread(yazpp_1::ISocketObservable *obs, int duration);
+    void socketNotify(int event);
+    bool timeout() { return m_timeout; };
+};
+
+
+My_Timer_Thread::My_Timer_Thread(yazpp_1::ISocketObservable *obs,
+                                int duration) : 
+    m_obs(obs), m_pipe(0), m_timeout(false)
+{
+    obs->addObserver(m_pipe.read_fd(), this);
+    obs->maskObserver(this, yazpp_1::SOCKET_OBSERVE_READ);
+    obs->timeoutObserver(this, duration);
+}
+
+void My_Timer_Thread::socketNotify(int event)
+{
+    m_timeout = true;
+    m_obs->deleteObserver(this);
+}
+
+BOOST_AUTO_TEST_CASE( test_pipe_1 )
+{
+    yazpp_1::SocketManager mySocketManager;
+    
+    yp2::Pipe pipe(0);
+
+    My_Timer_Thread t(&mySocketManager, 0);
+
+    while (mySocketManager.processEvent() > 0)
+        if (t.timeout())
+            break;
+    BOOST_CHECK (t.timeout());
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */