+#include <msp/core/refptr.h>
#include <msp/net/inet.h>
+#include <msp/net/resolve.h>
+#include "libr2c2/aicontrol.h"
+#include "libr2c2/catalogue.h"
#include "libr2c2/driver.h"
#include "libr2c2/route.h"
#include "libr2c2/train.h"
+#include "libr2c2/trainrouter.h"
+#include "libr2c2/trainstatus.h"
#include "libr2c2/vehicletype.h"
#include "server.h"
for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
train_added(*i->second);
- listen_sock.listen(Net::InetAddr(0, 8315), 4);
+ RefPtr<Net::SockAddr> addr = Net::resolve("*", "8315", Net::INET);
+ listen_sock.listen(*addr, 4);
listen_sock.signal_data_available.connect(sigc::mem_fun(this, &Server::incoming_connection));
}
+Server::~Server()
+{ }
+
void Server::use_event_dispatcher(IO::EventDispatcher &ed)
{
event_disp = &ed;
send(pkt);
}
-void Server::emergency(const string &msg)
+void Server::emergency(Block *, const string &msg)
{
EmergencyPacket pkt;
pkt.message = msg;
{
train.signal_control_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_control_changed), sigc::ref(train)));
train.signal_function_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_function_changed), sigc::ref(train)));
- train.signal_route_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_route_changed), sigc::ref(train)));
- train.signal_status_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
+ train.signal_ai_event.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_ai_event), sigc::ref(train)));
TrainInfoPacket pkt;
pkt.address = train.get_address();
- pkt.loco_type = train.get_locomotive_type().get_article_number().str();
+ pkt.loco_type = layout.get_catalogue().get_name(&train.get_locomotive_type());
pkt.name = train.get_name();
send(pkt);
- TrainStatus *status = new TrainStatus(train);
- status->set_tag("server:status");
- status->signal_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
+ if(!train.get_ai_of_type<TrainStatus>())
+ new TrainStatus(train);
}
void Server::train_control_changed(const Train &train, const string &control, float value)
send(pkt);
}
-void Server::train_route_changed(const Train &train, const Route *route)
-{
- TrainRoutePacket pkt;
- pkt.address = train.get_address();
- if(route)
- pkt.route = route->get_name();
- send(pkt);
-}
-
-void Server::train_status_changed(const Train &train, const string &status)
+void Server::train_ai_event(const Train &train, TrainAI &ai, const TrainAI::Message &ev)
{
- TrainStatusPacket pkt;
- pkt.address = train.get_address();
- pkt.status = status;
- send(pkt);
+ if(ev.type=="route-changed")
+ {
+ TrainRoutePacket pkt;
+ pkt.address = train.get_address();
+ if(const Route *route = ev.value.value<const Route *>())
+ pkt.route = route->get_name();
+ send(pkt);
+ }
+ else if(ev.type=="status-changed")
+ {
+ TrainStatusPacket pkt;
+ pkt.address = train.get_address();
+ pkt.status = ev.value.value<std::string>();
+ send(pkt);
+ }
+ else if(ev.type=="target-speed-changed" || ev.type=="reverse-changed")
+ {
+ AIControl *control = dynamic_cast<AIControl *>(&ai);
+ if(control)
+ {
+ TrainAIControlPacket pkt;
+ pkt.address = train.get_address();
+ pkt.target_speed = control->get_target_speed();
+ pkt.reverse = control->get_reverse();
+ send(pkt);
+ }
+ }
}
template<typename P>
{
for(vector<Connection *>::const_iterator i=connections.begin(); i!=connections.end(); ++i)
if(!(*i)->stale && (*i)->comm.is_handshake_done())
- {
- try
- {
- (*i)->comm.send(pkt);
- }
- catch(...)
- {
- (*i)->stale = true;
- }
- }
+ (*i)->comm.send(pkt);
}
Server::Connection::Connection(Server &s, Net::StreamSocket *o):
server(s),
socket(o),
- comm(*socket, server.proto, *this)
+ comm(*socket, server.proto, *this),
+ stale(false)
{
socket->signal_end_of_file.connect(sigc::mem_fun(this, &Connection::end_of_file));
comm.signal_handshake_done.connect(sigc::mem_fun(this, &Connection::handshake_done));
+ comm.signal_error.connect(sigc::mem_fun(this, &Connection::comm_error));
comm.initiate_handshake();
}
comm.send(pkt);
}
- const set<Route *> &routes = server.layout.get_routes();
+ const set<Route *> &routes = server.layout.get_all<Route>();
for(set<Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i)
if(!(*i)->is_temporary())
{
comm.send(pkt);
}
+ const Catalogue &cat = server.layout.get_catalogue();
const map<unsigned, Train *> &trains = server.layout.get_trains();
for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
{
{
TrainInfoPacket pkt;
pkt.address = train.get_address();
- pkt.loco_type = train.get_locomotive_type().get_article_number().str();
+ pkt.loco_type = cat.get_name(&train.get_locomotive_type());
pkt.name = train.get_name();
comm.send(pkt);
}
+ if(AIControl *control = train.get_ai_of_type<AIControl>())
+ {
+ TrainAIControlPacket pkt;
+ pkt.address = train.get_address();
+ pkt.target_speed = control->get_target_speed();
+ pkt.reverse = control->get_reverse();
+ comm.send(pkt);
+ }
for(unsigned j=0;; ++j)
{
const char *name = train.get_controller().enumerate_controls(j);
pkt.functions = train.get_functions();
comm.send(pkt);
}
- if(TrainStatus *status = dynamic_cast<TrainStatus *>(train.get_tagged_ai("server:status")))
+ if(TrainStatus *status = train.get_ai_of_type<TrainStatus>())
{
TrainStatusPacket pkt;
pkt.address = train.get_address();
pkt.status = status->get_status();
comm.send(pkt);
}
- if(train.get_route())
+ if(TrainRouter *router = train.get_ai_of_type<TrainRouter>())
{
TrainRoutePacket pkt;
pkt.address = train.get_address();
- pkt.route = train.get_route()->get_name();
+ pkt.route = router->get_route()->get_name();
comm.send(pkt);
}
}
void Server::Connection::end_of_file()
{
- socket->close();
stale = true;
}
}
}
+void Server::Connection::receive(const TrainAIControlPacket &pkt)
+{
+ try
+ {
+ Train &train = server.layout.get_train(pkt.address);
+ train.ai_message(TrainAI::Message("set-target-speed", pkt.target_speed));
+ train.ai_message(TrainAI::Message("set-reverse", static_cast<bool>(pkt.reverse)));
+ }
+ catch(const exception &e)
+ {
+ error(e.what());
+ }
+}
+
void Server::Connection::receive(const TrainRoutePacket &pkt)
{
try
{
Train &train = server.layout.get_train(pkt.address);
if(pkt.route.empty())
- train.set_route(0);
+ train.ai_message(TrainAI::Message("clear-route"));
else
{
Route &route = server.layout.get_route(pkt.route);
- train.set_route(&route);
+ train.ai_message(TrainAI::Message("set-route", &route));
}
}
catch(const exception &e)
}
}
+void Server::Connection::comm_error(const exception &)
+{
+ stale = true;
+}
+
void Server::Connection::error(const string &msg)
{
ErrorPacket pkt;