dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_init_listener.cpp
diff --git a/dol/src/dol/visitor/hdsd/scd/scd_init_listener.cpp b/dol/src/dol/visitor/hdsd/scd/scd_init_listener.cpp
new file mode 100644 (file)
index 0000000..700df8b
--- /dev/null
@@ -0,0 +1,126 @@
+#include "scd_init_listener.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_in_connector.h"
+
+
+scd_init_listener::scd_init_listener(scd_simulator &sim, uint16_t port):
+    _sim(sim), _host(""), _port(port), _handler(false) {}
+
+
+scd_init_listener::scd_init_listener(scd_simulator &sim,
+        const std::string &host, uint16_t port):
+    _sim(sim), _host(host), _port(port), _handler(false) {}
+
+
+scd_init_listener::~scd_init_listener()
+{
+    cleanup(true);
+    close();
+}
+
+
+void scd_init_listener::listen()
+{
+    if (!_socket.is_valid())
+    {
+        // create listening socket
+        if (!_socket.create())
+            throw scd_exception("creating listening socket failed");
+        if (!_socket.bind(_host, _port))
+            throw scd_exception("binding listening socket failed");
+        if (!_socket.listen())
+            throw scd_exception("listening to socket failed");
+
+        // register socket
+        if (!_handler)
+        {
+            _sim.get_poller().register_handler(*this,
+                    SOCK_EV_READ | SOCK_EV_CLOSE);
+            _handler = true;
+        }
+
+        scd_debug("socket listening");
+    }
+    else
+        scd_warn("socket is already listening");
+
+} // listen()
+
+
+void scd_init_listener::close()
+{
+    if (_handler)
+    {
+        _sim.get_poller().remove_handler(*this);
+        _handler = false;
+    }
+
+    if (_socket.is_valid())
+    {
+        _socket.close();
+        scd_debug("listener socket closed");
+    }
+
+} // close()
+
+
+void scd_init_listener::cleanup(bool hard)
+{
+    std::list<scd_in_connector*>::iterator iter;
+
+    for( iter=_connectors.begin(); iter!=_connectors.end();)
+    {
+        if ( hard || !(*iter)->is_connecting() )
+        {
+            delete *iter;
+            iter = _connectors.erase(iter);
+        }
+        else
+            iter++;
+    }
+} // cleanup()
+
+
+void scd_init_listener::handle_sock_ev(sock_ev events)
+{
+    if (events & SOCK_EV_READ)
+    {
+        scd_debug("incomming connection");
+
+        scd_socket* newconn = new scd_socket();
+
+        if (_socket.accept(*newconn))
+        {
+            /* create a new connector that handles the connection
+             * and store it in the list of connectors */
+            scd_in_connector* connector;
+            connector = new scd_in_connector(_sim, newconn);
+            _connectors.push_back(connector);
+        }
+        else
+        {
+            // connection could not be accepted
+            scd_debug("accepting connection failed");
+            delete newconn;
+        }
+    }
+    
+    if (events & SOCK_EV_CLOSE)
+    {
+        throw scd_exception("init_listener: experienced an error");
+    }
+
+    if (!_socket.is_valid())
+    {
+        throw scd_exception("init_listener: unexpectedly closed");
+    }
+
+} // sock_ev_handler()
+
+
+const scd_socket& scd_init_listener::get_sock()
+{
+    return _socket;
+}