X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fhdsd%2Fscd%2Fscd_out_connector.cpp;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fhdsd%2Fscd%2Fscd_out_connector.cpp;h=999a4239e063fffd12983edf8ef8680ba9db7b7b;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/hdsd/scd/scd_out_connector.cpp b/dol/src/dol/visitor/hdsd/scd/scd_out_connector.cpp new file mode 100644 index 0000000..999a423 --- /dev/null +++ b/dol/src/dol/visitor/hdsd/scd/scd_out_connector.cpp @@ -0,0 +1,185 @@ +#include "scd_out_connector.h" + +#include + +#include "scd_logging.h" +#include "scd_exception.h" +#include "scd_command.h" + + +scd_out_connector::scd_out_connector(scd_simulator& sim, uint16_t type, + const std::string& name): + _sim(sim), _name(name), + _is_connecting(true), _is_connected(false), _has_connection(false) +{ + // create socket + _socket = new scd_socket; + _socket->create(); + + // prepare register command (do not send yet) + scd_command* cmd = new scd_command(SCD_CM_REGISTER, type, name); + _writer = new scd_command_writer(); + _writer->set_socket(*_socket); + _writer->queue_command(cmd); +} + + +scd_out_connector::~scd_out_connector() +{ + close(); + delete _writer; +} + + +void scd_out_connector::connect_to(const std::string& host, uint16_t port) +{ + _host = host; + _port = port; + + // register the handler to check if a connection attempt succeeded + _sim.get_poller().register_handler(*this, SOCK_EV_WRITE); + + // start connection attempt + _conn_attempt(); + +} // connect_to() + + +bool scd_out_connector::is_connecting() { return _is_connecting; } + + +bool scd_out_connector::has_connection() { return _has_connection; } + + +scd_socket* scd_out_connector::get_connection() +{ + if (_has_connection) + { + _has_connection = false; + return _socket; + } + else + return NULL; +} + + +void scd_out_connector::process() +{ + if (_is_connecting && !_is_connected) + { + struct timeval now; + gettimeofday(&now, NULL); + + // check if an attempt had timed out (i.e. because of "drop" FW policy) + if ( _socket->is_connecting() && + (now.tv_sec - _last_con.tv_sec >= SCD_CON_TIMEOUT) ) + { + // close and reopen the socket + scd_debug("connecting to " + _host + " timed out"); + _sim.get_poller().remove_handler(*this); + _socket->close(); + _socket->create(); + _sim.get_poller().register_handler(*this, 0); + } + + // check if it is time to try again + if ( !_socket->is_connecting() && + (now.tv_sec - _last_con.tv_sec >= SCD_CON_RETRY) ) + { + scd_debug("reconnecting to " + _host); + _conn_attempt(); + _sim.get_poller().set_ev(*this, SOCK_EV_WRITE); + } + } // still trying to tcp-connect + +} // process() + + +void scd_out_connector::close() +{ + if (_is_connecting) + { + _sim.get_poller().remove_handler(*this); + } + + if (_is_connecting || _has_connection) + { + _socket->close(); + delete _socket; + + _is_connecting = false; + _has_connection = false; + } + + _is_connected = false; + +} // close() + + +const std::string& scd_out_connector::get_name() const { return _name; } + + +void scd_out_connector::handle_sock_ev(sock_ev events) +{ + if (events & SOCK_EV_CLOSE) + { + // the close event is only polled if _is_connected is true + scd_error("outgoing connection closed"); + close(); + return; + } // end close event + else if (events & SOCK_EV_WRITE) + { + if (!_is_connected) + { + if (_socket->connected_event()) + { + // connection established + scd_debug("ougoing connection established to " + _host); + _is_connected = true; + _sim.get_poller().set_ev(*this, SOCK_EV_WRITE | SOCK_EV_CLOSE); + } + else + { + // connection attempt failed + _sim.get_poller().set_ev(*this, 0); + return; + } + } + + assert( _is_connected || !_socket->is_connecting()); + + _writer->write(); + if (!_writer->is_writing()) + { + // done sending the command + _is_connecting = false; + _has_connection = true; + _sim.get_poller().remove_handler(*this); + } + + if (!_socket->is_valid()) + { + close(); + } + } // end write event + +} // handle_sock_ev() + + +const scd_socket& scd_out_connector::get_sock() { return *_socket; } + + +void scd_out_connector::_conn_attempt() +{ + if (_socket->connect(_host, _port)) + { + gettimeofday(&_last_con, NULL); + } + else + { + scd_error("unable to connect to " + _host); + close(); + } + +} // _conn_attempt()