]> git.stg.codes - stg.git/blobdiff - stglibs/sgcp.lib/tcp.cpp
Experimental implementation of SGCP using Boost.Asio.
[stg.git] / stglibs / sgcp.lib / tcp.cpp
index 414d5ec84322c37153f0a29ad86087f10b53ef22..5d6c6cbc2b6b21be33f5df3e1ea330a653cb58cb 100644 (file)
@@ -12,8 +12,9 @@
 
 using STG::SGCP::TCPProto;
 
-TCPProto::TCPProto()
-    : m_sock(socket(AF_INET, SOCK_STREAM, 0))
+TCPProto::TCPProto(ba::io_service& ios)
+    : m_ios(ios),
+      m_acceptor(m_ios)
 {
 }
 
@@ -22,31 +23,34 @@ TCPProto::~TCPProto()
     close(m_sock);
 }
 
-void TCPProto::connect(const std::string& address, uint16_t port)
+ConnectionPtr TCPProto::connect(const std::string& address, uint16_t port)
 {
-    std::vector<in_addr> addrs = resolve(address);
-
-    for (size_t i = 0; i < addrs.size(); ++i) {
-        sockaddr_in addr;
-        addr.sin_family = AF_INET;
-        addr.sin_port = hton(port);
-        addr.sin_addr = addrs[i];
-
-        if (::connect(m_sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)) == 0)
-            return;
-
-        close(m_sock);
-        m_sock = socket(AF_INET, SOCK_STREAM, 0);
-    }
-    throw Error("No more addresses to connect to.");
+    bs::error_code ec;
+    ConnectionPtr conn = boost::make_shared(m_ios);
+    conn.socket().connect(ba::local::stream_protocol::enpoint(address, port), ec);
+    if (ec)
+        throw Error(ec.message());
+    conn->start();
+    return conn;
 }
 
-ssize_t TCPProto::write(const void* buf, size_t size)
+void TCPProto::bind(const std::string& address, uint16_t port, Proto::AcceptHandler handler)
 {
-    return ::write(m_sock, buf, size);
+    bs::error_code ec;
+    m_acceptor.bind(address, ec);
+    if (ec)
+        throw Error(ec.message());
+
+    TCPConn* conn = new TCPConn(m_ios);
+    m_acceptor.async_accept(conn->socket(), conn->endpoint(), boost::bind(&TCPProto::m_handleAccept, this, conn, handler, boost::_1);
 }
 
-ssize_t TCPProto::read(void* buf, size_t size)
+void TCPProto::m_handleAccept(TCPConn* conn, Proto::AcceptHandler handler, const boost::system::error_code& ec)
 {
-    return ::read(m_sock, buf, size);
+    if (ec) {
+        delete conn;
+        handler(NULL, "", ec.message());
+        return;
+    }
+    handler(conn, conn->enpoint().address(), "");
 }