]> git.stg.codes - stg.git/blobdiff - stglibs/sgcp.lib/proto.cpp
Experimental implementation of SGCP using Boost.Asio.
[stg.git] / stglibs / sgcp.lib / proto.cpp
index 96b6285b05e2de64e76e84bc3cf77ef889e9b46e..8e3b1eb673ceee16abd27a4eba291ee0e6fc43de 100644 (file)
@@ -7,57 +7,95 @@
 
 using STG::SGCP::Proto;
 
-Proto::Error::Error(const std::string& message)
-    : runtime_error(message)
-{}
-
-Proto::Error::Error()
-    : runtime_error(strerror(errno))
-{}
-
 Proto::Proto(TransportType transport, const std::string& key)
-    : m_transport(TransportProto::create(transport, key))
+    : m_impl(new Impl(transport, key))
 {
 }
 
 Proto::~Proto()
 {
-    delete m_transport;
 }
 
-void Proto::connect(const std::string& address, uint16_t port)
+ConnectionPtr Proto::connect(const std::string& address, uint16_t port)
 {
-    try {
-        m_transport->connect(address, port);
-    } catch (const TransportProto::Error& ex) {
-        throw Error(ex.what());
-    }
+    m_impl->connect(adress, port);
 }
 
-void Proto::writeAllBuf(const void* buf, size_t size)
+void Proto::bind(const std::string& address, uint16_t port, AcceptHandler handler)
 {
-    const char* pos = static_cast<const char*>(buf);
-    while (size > 0) {
-        ssize_t res = m_transport->write(pos, size);
-        if (res < 0)
-            throw Error();
-        if (res == 0)
-            return;
-        size -= res;
-        pos += res;
-    }
+    m_impl->bind(address, port, handler);
+}
+
+void Proto::run()
+{
+    m_impl->run();
+}
+
+bool Proto::stop()
+{
+    return m_impl->stop();
+}
+
+class Proto::Impl
+{
+    public:
+        Impl(TransportType transport, const std::string& key);
+        ~Impl();
+
+        Connection& connect(const std::string& address, uint16_t port);
+        void bind(const std::string& address, uint16_t port, AcceptHandler handler);
+
+        void run();
+        bool stop();
+
+    private:
+        ba::io_service m_ios;
+        boost::scoped_ptr<Transport> m_transport;
+        std::vector<ConnectionPtr> m_conns;
+        bool m_running;
+        bool m_stopped;
+};
+
+Proto::Impl::Impl(TransportType transport, const std::string& key)
+    : m_transport(makeTransport(transport, key)),
+      m_running(false),
+      m_stopped(true)
+{
+}
+
+Proto::Impl::~Impl()
+{
+    stop();
+}
+
+ConnectionPtr Proto::Impl::connect(const std::string& address, uint16_t port)
+{
+    return m_transport->connect(address, port);
+}
+
+void Proto::Impl::bind(const std::string& address, uint16_t port, AcceptHandler handler)
+{
+    m_transport->bind(address, port, handler);
+}
+
+void Proto::Impl::run()
+{
+    m_stopped = false;
+    m_running = true;
+    while (m_running)
+        m_ios.run_once();
+    m_stopped = true;
 }
 
-void Proto::readAllBuf(void* buf, size_t size)
+bool Proto::Impl::stop()
 {
-    char* pos = static_cast<char*>(buf);
-    while (size > 0) {
-        ssize_t res = m_transport->read(pos, size);
-        if (res < 0)
-            throw Error();
-        if (res == 0)
-            return;
-        size -= res;
-        pos += res;
+    for (size_t i = 0; i < m_conns.size(); ++i)
+        m_conns[i]->stop();
+    m_ios.stop();
+    for (size_t i = 0; i < 10 && !m_ios.stopped(); ++i) {
+        timspec ts;
+        ts.tv_sec = 0;
+        ts.tv_nsec = 10000000; // 10 msec
     }
+    return m_ios.stopped();
 }