+#include "scd_chan_man.h"
+
+#include "scd_logging.h"
+
+
+scd_chan_man::scd_chan_man(scd_simulator &sim):
+ _sim(sim), _is_ready(false) {}
+
+
+scd_chan_man::~scd_chan_man()
+{
+ std::list<scd_out_connector*>::iterator coit;
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (coit = _connectors.begin(); coit != _connectors.end(); coit++)
+ delete *coit;
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ delete *chit;
+}
+
+
+void scd_chan_man::register_channel(const std::string &name, sc_prim_channel& mchan)
+{
+ if ( _get_channel(name) != NULL )
+ {
+ scd_warn("channel \"" + name + "\" already registered, ignoring...");
+ }
+ else
+ {
+ scd_chan_wrapper* wrap = new scd_chan_wrapper(_sim, name, mchan);
+ _channels.push_back(wrap);
+ }
+
+} // register_channel() - master
+
+
+void scd_chan_man::register_channel(const std::string &name,
+ sc_prim_channel& schan, const std::string &host, const uint16_t port)
+{
+ if ( _get_channel(name) != NULL )
+ {
+ scd_warn("channel \"" + name + "\" already registered, ignoring...");
+ }
+ else
+ {
+ // register channel
+ scd_chan_wrapper* wrap = new scd_chan_wrapper(_sim, name, schan);
+ _channels.push_back(wrap);
+
+ // create connector
+ scd_out_connector* conn = new scd_out_connector(_sim, SCD_CM_CHANNEL,
+ name);
+ conn->connect_to(host, port);
+ _connectors.push_back(conn);
+ }
+
+} // register_channel() - slave
+
+
+void scd_chan_man::init_process()
+{
+ if (_is_ready)
+ return;
+
+ std::list<scd_out_connector*>::iterator coit;
+
+ // check all connectors
+ for (coit = _connectors.begin(); coit != _connectors.end();)
+ {
+ scd_out_connector& conn = **coit;
+
+ // retry to connect if necessary
+ conn.process();
+
+ if (!conn.is_connecting() && !conn.has_connection())
+ {
+ // an error occured
+ scd_error("failed to connect channel \""
+ + conn.get_name() + "\"");
+
+ delete *coit;
+ coit = _connectors.erase(coit);
+
+ _sim.get_cont_man().set_fail();
+ return;
+ }
+ else if (!conn.is_connecting() && conn.has_connection())
+ {
+ // channel is connected
+ scd_chan_wrapper& chan = *_get_channel(conn.get_name());
+
+ if (chan.is_initialized())
+ {
+ scd_error("channel \""
+ + conn.get_name() + "\" already connected");
+
+ delete *coit;
+ coit = _connectors.erase(coit);
+
+ _sim.get_cont_man().set_fail();
+ return;
+ }
+ else
+ {
+ scd_info("connected channel \"" + conn.get_name() + "\"");
+ chan.connect(conn.get_connection());
+
+ delete *coit;
+ coit = _connectors.erase(coit);
+ }
+ } // end channel connected
+ else
+ {
+ // still trying to connect
+ coit++;
+ }
+ // end this connector
+ } // end check all connectors
+
+ // check if everything is initiated
+ _check_ready();
+
+} // init_process()
+
+
+void scd_chan_man::connect_channel(const scd_command &c, scd_socket* sock)
+{
+ std::string name = c.get_string();
+
+ scd_chan_wrapper* chan = _get_channel(name);
+
+ if (chan == NULL)
+ {
+ scd_warn("unknown channel \"" + name + "\" supplied by peer");
+ delete sock;
+ }
+ else if (chan->is_initialized())
+ {
+ scd_warn("channel \"" + name + "\" supplied by peer already connected");
+ }
+ else
+ {
+ scd_info("connected channel \"" + name + "\"");
+ chan->connect(sock);
+ }
+
+} // connect()
+
+
+bool scd_chan_man::ready() const { return _is_ready; }
+
+
+void scd_chan_man::process()
+{
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ (*chit)->process();
+
+} // process()
+
+
+void scd_chan_man::close()
+{
+ std::list<scd_out_connector*>::iterator coit;
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (coit = _connectors.begin(); coit != _connectors.end(); coit++)
+ (*coit)->close();
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ (*chit)->close();
+
+} // close()
+
+
+bool scd_chan_man::_check_ready()
+{
+ if (_is_ready)
+ return true;
+
+ if (_connectors.empty())
+ {
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ // check all channels
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ {
+ if ( !(*chit)->is_initialized() )
+ return false;
+ }
+
+ // all channels initiated
+ _is_ready = true;
+ return true;
+ }
+ else
+ return false;
+
+} // _check_ready()
+
+
+scd_chan_wrapper* scd_chan_man::_get_channel(const std::string& name)
+{
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ {
+ if ( (*chit)->get_name() == name )
+ return *chit;
+ }
+
+ return NULL;
+
+} // _get_channel()