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