]> git.tdb.fi Git - r2c2.git/blob - source/network/server.cpp
Store routes in a map by name rather than a set
[r2c2.git] / source / network / server.cpp
1 /* $Id$
2
3 This file is part of the MSP Märklin suite
4 Copyright © 2009  Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
6 */
7
8 #include <msp/net/inet.h>
9 #include "libmarklin/control.h"
10 #include "libmarklin/layout.h"
11 #include "libmarklin/locomotive.h"
12 #include "libmarklin/locotype.h"
13 #include "libmarklin/route.h"
14 #include "server.h"
15
16 using namespace std;
17 using namespace Msp;
18
19 namespace Marklin {
20
21 Server::Server(TrafficManager &tm):
22         trfc_mgr(tm),
23         listen_sock(Net::INET),
24         event_disp(0)
25 {
26         const list<Train *> &trains = trfc_mgr.get_trains();
27         for(list<Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
28                 train_added(**i);
29
30         listen_sock.listen(Net::InetAddr(0, 8315), 4);
31         listen_sock.signal_data_available.connect(sigc::mem_fun(this, &Server::incoming_connection));
32 }
33
34 void Server::use_event_dispatcher(IO::EventDispatcher &ed)
35 {
36         event_disp = &ed;
37         event_disp->add(listen_sock);
38 }
39
40 void Server::incoming_connection()
41 {
42         Net::StreamSocket *sock = listen_sock.accept();
43         if(event_disp)
44                 event_disp->add(*sock);
45         connections.push_back(new Connection(*this, sock));
46 }
47
48 void Server::train_added(Train &train)
49 {
50         Locomotive &loco = train.get_locomotive();
51         train.signal_target_speed_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_speed_changed), sigc::ref(train)));
52         loco.signal_reverse_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_reverse_changed), sigc::ref(train)));
53         loco.signal_function_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_function_changed), sigc::ref(train)));
54         train.signal_route_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_route_changed), sigc::ref(train)));
55         train.signal_status_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
56
57         TrainInfoPacket pkt;
58         pkt.address = loco.get_address();
59         pkt.loco_type = loco.get_type().get_article_number();
60         pkt.name = train.get_name();
61         send(pkt);
62 }
63
64 void Server::train_speed_changed(const Train &train, unsigned speed)
65 {
66         TrainSpeedPacket pkt;
67         pkt.address = train.get_locomotive().get_address();
68         pkt.speed = speed;
69         pkt.reverse = train.get_locomotive().get_reverse();
70         send(pkt);
71 }
72
73 void Server::train_reverse_changed(const Train &train, bool reverse)
74 {
75         TrainSpeedPacket pkt;
76         pkt.address = train.get_locomotive().get_address();
77         pkt.speed = train.get_target_speed();
78         pkt.reverse = reverse;
79         send(pkt);
80 }
81
82 void Server::train_function_changed(const Train &train, unsigned, bool)
83 {
84         TrainFunctionPacket pkt;
85         pkt.address = train.get_locomotive().get_address();
86         pkt.functions = train.get_locomotive().get_functions();
87         send(pkt);
88 }
89
90 void Server::train_route_changed(const Train &train, const Route *route)
91 {
92         TrainRoutePacket pkt;
93         pkt.address = train.get_locomotive().get_address();
94         if(route)
95                 pkt.route = route->get_name();
96         send(pkt);
97 }
98
99 void Server::train_status_changed(const Train &train, const string &status)
100 {
101         TrainStatusPacket pkt;
102         pkt.address = train.get_locomotive().get_address();
103         pkt.status = status;
104         send(pkt);
105 }
106
107 template<typename P>
108 void Server::send(const P &pkt)
109 {
110         for(vector<Connection *>::const_iterator i=connections.begin(); i!=connections.end(); ++i)
111                 if(!(*i)->stale)
112                         (*i)->comm.send(pkt);
113 }
114
115
116 Server::Connection::Connection(Server &s, Net::StreamSocket *o):
117         server(s),
118         socket(o),
119         comm(*socket, server.proto, *this)
120 {
121         socket->signal_end_of_file.connect(sigc::mem_fun(this, &Connection::end_of_file));
122         comm.signal_handshake_done.connect(sigc::mem_fun(this, &Connection::handshake_done));
123         comm.initiate_handshake();
124 }
125
126 Server::Connection::~Connection()
127 {
128         delete socket;
129 }
130
131 void Server::Connection::handshake_done()
132 {
133         const map<string, Route *> &routes = server.trfc_mgr.get_layout().get_routes();
134         for(map<string, Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i)
135         {
136                 RouteInfoPacket pkt;
137                 pkt.name = i->first;
138                 comm.send(pkt);
139         }
140
141         const list<Train *> &trains = server.trfc_mgr.get_trains();
142         for(list<Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
143         {
144                 Locomotive &loco = (*i)->get_locomotive();
145
146                 {
147                         TrainInfoPacket pkt;
148                         pkt.address = loco.get_address();
149                         pkt.loco_type = loco.get_type().get_article_number();
150                         pkt.name = (*i)->get_name();
151                         comm.send(pkt);
152                 }
153                 {
154                         TrainSpeedPacket pkt;
155                         pkt.address = loco.get_address();
156                         pkt.speed = (*i)->get_target_speed();
157                         pkt.reverse = loco.get_reverse();
158                         comm.send(pkt);
159                 }
160                 {
161                         TrainFunctionPacket pkt;
162                         pkt.address = loco.get_address();
163                         pkt.functions = loco.get_functions();
164                         comm.send(pkt);
165                 }
166                 {
167                         TrainStatusPacket pkt;
168                         pkt.address = loco.get_address();
169                         pkt.status = (*i)->get_status();
170                         comm.send(pkt);
171                 }
172                 if((*i)->get_route())
173                 {
174                         TrainRoutePacket pkt;
175                         pkt.address = loco.get_address();
176                         pkt.route = (*i)->get_route()->get_name();
177                         comm.send(pkt);
178                 }
179         }
180 }
181
182 void Server::Connection::end_of_file()
183 {
184         socket->close();
185         stale = true;
186 }
187
188 void Server::Connection::receive(const TrainSpeedPacket &pkt)
189 {
190         try
191         {
192                 Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address);
193                 Train &train = server.trfc_mgr.get_train_by_locomotive(loco);
194                 if(pkt.reverse!=loco.get_reverse())
195                         train.set_reverse(pkt.reverse);
196                 else
197                         train.set_speed(pkt.speed);
198         }
199         catch(const Exception &e)
200         {
201                 error(e.what());
202         }
203 }
204
205 void Server::Connection::receive(const TrainFunctionPacket &pkt)
206 {
207         try
208         {
209                 Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address);
210                 for(unsigned i=0; i<9; ++i)
211                         if(((pkt.functions^loco.get_functions())>>i)&1)
212                                 loco.set_function(i, (pkt.functions>>i)&1);
213         }
214         catch(const Exception &e)
215         {
216                 error(e.what());
217         }
218 }
219
220 void Server::Connection::receive(const TrainRoutePacket &pkt)
221 {
222         try
223         {
224                 Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address);
225                 Train &train = server.trfc_mgr.get_train_by_locomotive(loco);
226                 if(pkt.route.empty())
227                         train.set_route(0);
228                 else
229                 {
230                         Route &route = server.trfc_mgr.get_layout().get_route(pkt.route);
231                         train.set_route(&route);
232                 }
233         }
234         catch(const Exception &e)
235         {
236                 error(e.what());
237         }
238 }
239
240 void Server::Connection::error(const string &msg)
241 {
242         ErrorPacket pkt;
243         pkt.message = msg;
244         comm.send(pkt);
245 }
246
247 } // namespace Marklin