]> git.tdb.fi Git - r2c2.git/blob - source/network/server.cpp
Adapt to mspnet API changes
[r2c2.git] / source / network / server.cpp
1 #include <msp/core/refptr.h>
2 #include <msp/net/inet.h>
3 #include <msp/net/resolve.h>
4 #include "libr2c2/driver.h"
5 #include "libr2c2/route.h"
6 #include "libr2c2/train.h"
7 #include "libr2c2/vehicletype.h"
8 #include "server.h"
9
10 using namespace std;
11 using namespace Msp;
12
13 namespace R2C2 {
14
15 Server::Server(Layout &l):
16         layout(l),
17         listen_sock(Net::INET),
18         event_disp(0)
19 {
20         layout.get_driver().signal_power.connect(sigc::hide(sigc::mem_fun(this, &Server::driver_state_changed)));
21         layout.get_driver().signal_halt.connect(sigc::hide(sigc::mem_fun(this, &Server::driver_state_changed)));
22         layout.signal_emergency.connect(sigc::mem_fun(this, &Server::emergency));
23
24         layout.signal_train_added.connect(sigc::mem_fun(this, &Server::train_added));
25
26         const map<unsigned, Train *> &trains = layout.get_trains();
27         for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
28                 train_added(*i->second);
29
30         RefPtr<Net::SockAddr> addr = Net::resolve("*", "8315", Net::INET);
31         listen_sock.listen(*addr, 4);
32         listen_sock.signal_data_available.connect(sigc::mem_fun(this, &Server::incoming_connection));
33 }
34
35 void Server::use_event_dispatcher(IO::EventDispatcher &ed)
36 {
37         event_disp = &ed;
38         event_disp->add(listen_sock);
39 }
40
41 void Server::incoming_connection()
42 {
43         Net::StreamSocket *sock = listen_sock.accept();
44         if(event_disp)
45                 event_disp->add(*sock);
46         connections.push_back(new Connection(*this, sock));
47 }
48
49 void Server::driver_state_changed()
50 {
51         DriverStatePacket pkt;
52         pkt.power = layout.get_driver().get_power();
53         pkt.halt = layout.get_driver().is_halted();
54         send(pkt);
55 }
56
57 void Server::emergency(const string &msg)
58 {
59         EmergencyPacket pkt;
60         pkt.message = msg;
61         send(pkt);
62 }
63
64 void Server::train_added(Train &train)
65 {
66         train.signal_control_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_control_changed), sigc::ref(train)));
67         train.signal_function_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_function_changed), sigc::ref(train)));
68         train.signal_route_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_route_changed), sigc::ref(train)));
69         train.signal_status_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
70
71         TrainInfoPacket pkt;
72         pkt.address = train.get_address();
73         pkt.loco_type = train.get_locomotive_type().get_article_number().str();
74         pkt.name = train.get_name();
75         send(pkt);
76
77         TrainStatus *status = new TrainStatus(train);
78         status->set_tag("server:status");
79         status->signal_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
80 }
81
82 void Server::train_control_changed(const Train &train, const string &control, float value)
83 {
84         TrainControlPacket pkt;
85         pkt.address = train.get_address();
86         pkt.control = control;
87         pkt.value = value;
88         send(pkt);
89 }
90
91 void Server::train_function_changed(const Train &train, unsigned, bool)
92 {
93         TrainFunctionPacket pkt;
94         pkt.address = train.get_address();
95         pkt.functions = train.get_functions();
96         send(pkt);
97 }
98
99 void Server::train_route_changed(const Train &train, const Route *route)
100 {
101         TrainRoutePacket pkt;
102         pkt.address = train.get_address();
103         if(route)
104                 pkt.route = route->get_name();
105         send(pkt);
106 }
107
108 void Server::train_status_changed(const Train &train, const string &status)
109 {
110         TrainStatusPacket pkt;
111         pkt.address = train.get_address();
112         pkt.status = status;
113         send(pkt);
114 }
115
116 template<typename P>
117 void Server::send(const P &pkt)
118 {
119         for(vector<Connection *>::const_iterator i=connections.begin(); i!=connections.end(); ++i)
120                 if(!(*i)->stale && (*i)->comm.is_handshake_done())
121                 {
122                         try
123                         {
124                                 (*i)->comm.send(pkt);
125                         }
126                         catch(...)
127                         {
128                                 (*i)->stale = true;
129                         }
130                 }
131 }
132
133
134 Server::Connection::Connection(Server &s, Net::StreamSocket *o):
135         server(s),
136         socket(o),
137         comm(*socket, server.proto, *this)
138 {
139         socket->signal_end_of_file.connect(sigc::mem_fun(this, &Connection::end_of_file));
140         comm.signal_handshake_done.connect(sigc::mem_fun(this, &Connection::handshake_done));
141         comm.initiate_handshake();
142 }
143
144 Server::Connection::~Connection()
145 {
146         delete socket;
147 }
148
149 void Server::Connection::handshake_done()
150 {
151         {
152                 DriverStatePacket pkt;
153                 pkt.power = server.layout.get_driver().get_power();
154                 pkt.halt = server.layout.get_driver().is_halted();
155                 comm.send(pkt);
156         }
157
158         const set<Route *> &routes = server.layout.get_routes();
159         for(set<Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i)
160                 if(!(*i)->is_temporary())
161                 {
162                         RouteInfoPacket pkt;
163                         pkt.name = (*i)->get_name();
164                         comm.send(pkt);
165                 }
166
167         const map<unsigned, Train *> &trains = server.layout.get_trains();
168         for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
169         {
170                 const Train &train = *i->second;
171
172                 {
173                         TrainInfoPacket pkt;
174                         pkt.address = train.get_address();
175                         pkt.loco_type = train.get_locomotive_type().get_article_number().str();
176                         pkt.name = train.get_name();
177                         comm.send(pkt);
178                 }
179                 for(unsigned j=0;; ++j)
180                 {
181                         const char *name = train.get_controller().enumerate_controls(j);
182                         if(!name)
183                                 break;
184
185                         TrainControlPacket pkt;
186                         pkt.address = train.get_address();
187                         pkt.control = name;
188                         pkt.value = train.get_control(name);
189                         comm.send(pkt);
190                 }
191                 {
192                         TrainFunctionPacket pkt;
193                         pkt.address = train.get_address();
194                         pkt.functions = train.get_functions();
195                         comm.send(pkt);
196                 }
197                 if(TrainStatus *status = dynamic_cast<TrainStatus *>(train.get_tagged_ai("server:status")))
198                 {
199                         TrainStatusPacket pkt;
200                         pkt.address = train.get_address();
201                         pkt.status = status->get_status();
202                         comm.send(pkt);
203                 }
204                 if(train.get_route())
205                 {
206                         TrainRoutePacket pkt;
207                         pkt.address = train.get_address();
208                         pkt.route = train.get_route()->get_name();
209                         comm.send(pkt);
210                 }
211         }
212 }
213
214 void Server::Connection::end_of_file()
215 {
216         stale = true;
217 }
218
219 void Server::Connection::receive(const DriverStatePacket &pkt)
220 {
221         Driver &driver = server.layout.get_driver();
222         if(pkt.power!=driver.get_power())
223                 driver.set_power(pkt.power);
224         if(pkt.halt!=driver.is_halted())
225                 driver.halt(pkt.halt);
226 }
227
228 void Server::Connection::receive(const TrainControlPacket &pkt)
229 {
230         try
231         {
232                 Train &train = server.layout.get_train(pkt.address);
233                 train.set_control(pkt.control, pkt.value);
234         }
235         catch(const exception &e)
236         {
237                 error(e.what());
238         }
239 }
240
241 void Server::Connection::receive(const TrainFunctionPacket &pkt)
242 {
243         try
244         {
245                 Train &train = server.layout.get_train(pkt.address);
246                 for(unsigned i=0; i<9; ++i)
247                         if(((pkt.functions^train.get_functions())>>i)&1)
248                                 train.set_function(i, (pkt.functions>>i)&1);
249         }
250         catch(const exception &e)
251         {
252                 error(e.what());
253         }
254 }
255
256 void Server::Connection::receive(const TrainRoutePacket &pkt)
257 {
258         try
259         {
260                 Train &train = server.layout.get_train(pkt.address);
261                 if(pkt.route.empty())
262                         train.set_route(0);
263                 else
264                 {
265                         Route &route = server.layout.get_route(pkt.route);
266                         train.set_route(&route);
267                 }
268         }
269         catch(const exception &e)
270         {
271                 error(e.what());
272         }
273 }
274
275 void Server::Connection::error(const string &msg)
276 {
277         ErrorPacket pkt;
278         pkt.message = msg;
279         comm.send(pkt);
280 }
281
282 } // namespace R2C2