--- /dev/null
+#include "scd_cont_slave_wrapper.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+scd_cont_slave_wrapper::scd_cont_slave_wrapper(scd_simulator& sim,
+ const std::string& name):
+ _sim(sim), scd_cont_fsm(name), _name(name), _is_connected(false),
+ _st_init(sim, *this), _st_busy(sim, *this), _st_idle(sim, *this),
+ _st_done(sim, *this), _st_time_req(sim, *this), _st_time_ack(sim, *this),
+ _st_term_req(sim, *this), _st_term_ack(sim, *this),
+ _st_terminate(sim, *this), _st_terminated(sim, *this), _st_fail(sim, *this),
+ _st_failed(sim, *this)
+{
+ // set initial state
+ set_state(_st_init);
+}
+
+
+scd_cont_slave_wrapper::~scd_cont_slave_wrapper()
+{
+ if (_socket != NULL)
+ delete _socket;
+}
+
+
+const std::string& scd_cont_slave_wrapper::get_name() const { return _name; }
+
+
+void scd_cont_slave_wrapper::connect(scd_socket* sock)
+{
+ if (!_is_connected)
+ {
+ _socket = sock;
+ _writer.set_socket(*_socket);
+ _reader.set_socket(*_socket);
+ _is_connected = true;
+ scd_info("slave \"" + _name + "\" connected");
+ static_cast<scd_stsw_base*>(_state)->set_connected();
+ }
+ else
+ {
+ scd_warn("slave " + _name + " has already been connected");
+ delete sock;
+ }
+} // connect()
+
+
+void scd_cont_slave_wrapper::send_command(scd_command* cmd)
+{
+ // register write event if not registered
+ if (!_writer.is_writing() && _is_connected && _socket->is_valid())
+ _sim.get_poller().set_ev(*this, SOCK_EV_WRITE | SOCK_EV_READ
+ | SOCK_EV_CLOSE);
+
+ // queue command to be written
+ _writer.queue_command(cmd);
+}
+
+
+bool scd_cont_slave_wrapper::is_sending() const
+{
+ return _writer.is_writing() && _is_connected && _socket->is_valid();
+}
+
+
+void scd_cont_slave_wrapper::close()
+{
+ if (_is_connected)
+ _socket->close();
+}
+
+
+void scd_cont_slave_wrapper::handle_sock_ev(sock_ev events)
+{
+ scd_stsw_base& state = *static_cast<scd_stsw_base*>(_state);
+
+ if (events & SOCK_EV_CLOSE)
+ {
+ _socket->close();
+ scd_error("connection to slave \"" + _name + "\" lost");
+ state.set_failed();
+ return;
+ }
+
+ if (events & SOCK_EV_READ)
+ {
+ _reader.read();
+
+ if (!_socket->is_valid())
+ {
+ // connection closed
+ scd_error("connection to slave \"" + _name + "\" lost");
+ state.set_failed();
+ return;
+ }
+
+ if (!_reader.is_reading() && !_reader.has_command())
+ {
+ // received an illegal command
+ scd_error("received illegal command");
+ state.set_fail();
+ return;
+ }
+
+ if (_reader.has_command())
+ {
+ scd_command* cmd = _reader.get_command();
+ _process_cmd(*cmd);
+ delete cmd;
+ }
+
+ } // end read event
+
+ if (events & SOCK_EV_WRITE)
+ {
+ _writer.write();
+
+ if (!_writer.is_writing())
+ {
+ // done sending commands
+ _sim.get_poller().set_ev(*this, SOCK_EV_READ | SOCK_EV_CLOSE);
+ }
+
+ if (!_socket->is_valid())
+ {
+ scd_error("connection to slave \"" + _name + "\" lost");
+ state.set_failed();
+ return;
+ }
+ } // end write event
+
+
+} // handle_sock_ev()
+
+
+const scd_socket& scd_cont_slave_wrapper::get_sock() { return *_socket; }
+
+
+void scd_cont_slave_wrapper::_process_cmd(const scd_command& cmd)
+{
+ if (cmd.get_type() != SCD_CM_CONTROL)
+ {
+ scd_warn("received non-control command");
+ return;
+ }
+
+ scd_stsw_base* state = static_cast<scd_stsw_base*>(_state);
+
+ switch(cmd.get_subtype())
+ {
+ case SCD_CM_BUSY:
+ state->set_busy();
+ break;
+ case SCD_CM_IDLE:
+ state->set_idle(cmd.get_time());
+ break;
+ case SCD_CM_DONE:
+ state->set_done();
+ break;
+ case SCD_CM_TIME_NACK:
+ state->recv_time_nack();
+ break;
+ case SCD_CM_TIME_ACK:
+ state->recv_time_ack();
+ break;
+ case SCD_CM_TERM_NACK:
+ state->recv_term_nack();
+ break;
+ case SCD_CM_TERM_ACK:
+ state->recv_term_ack();
+ break;
+ case SCD_CM_FAILED:
+ scd_error("slave \"" + _name + "\" failed");
+ state->set_failed();
+ break;
+ default:
+ scd_warn("received unknown command");
+ break;
+ }
+} // _process_cmd()