sources/network/rconsession.cpp

changeset 72
1b9c53e0c846
parent 71
4f7c2c944637
child 73
07dda51a7a8e
equal deleted inserted replaced
71:4f7c2c944637 72:1b9c53e0c846
1 #include "rconsession.h" 1 #include "rconsession.h"
2 #include "../interface.h" 2 #include "../interface.h"
3 3
4 // ------------------------------------------------------------------------------------------------- 4 // -------------------------------------------------------------------------------------------------
5 // 5 //
6 RCONSession::RCONSession() : 6 RCONSession::RCONSession (Interface* iface) :
7 m_state (RCON_DISCONNECTED), 7 m_state (RCON_DISCONNECTED),
8 m_lastPing (0), 8 m_lastPing (0),
9 m_numAdmins (0) 9 m_numAdmins (0),
10 m_interface (iface)
10 { 11 {
11 if (not m_socket.set_blocking (false)) 12 if (not m_socket.set_blocking (false))
12 { 13 {
13 print_to (stderr, "unable to set socket as non-blocking: %s\n", 14 print_to (stderr, "unable to set socket as non-blocking: %s\n",
14 m_socket.error_string().chars()); 15 m_socket.error_string().chars());
20 // 21 //
21 RCONSession::~RCONSession() {} 22 RCONSession::~RCONSession() {}
22 23
23 // ------------------------------------------------------------------------------------------------- 24 // -------------------------------------------------------------------------------------------------
24 // 25 //
25 METHOD 26 void RCONSession::connect (IPAddress address)
26 RCONSession::connect (IPAddress address) -> void
27 { 27 {
28 m_address = address; 28 m_address = address;
29 m_state = RCON_CONNECTING; 29 m_state = RCON_CONNECTING;
30 Interface::update_statusbar(); 30 m_interface->update_statusbar();
31 send_hello(); 31 send_hello();
32 } 32 }
33 33
34 // ------------------------------------------------------------------------------------------------- 34 // -------------------------------------------------------------------------------------------------
35 // 35 //
36 METHOD 36 void RCONSession::disconnect()
37 RCONSession::disconnect() -> void
38 { 37 {
39 if (m_state > RCON_CONNECTING) 38 if (m_state > RCON_CONNECTING)
40 { 39 {
41 // Say goodbye to remote 40 // Say goodbye to remote
42 Bytestream packet; 41 Bytestream packet;
43 packet.write_byte (CLRC_DISCONNECT); 42 packet.write_byte (CLRC_DISCONNECT);
44 this->send (packet); 43 this->send (packet);
45 print ("Disconnected from %1\n", m_address.to_string (IP_WITH_PORT)); 44 m_interface->print ("Disconnected from %1\n", m_address.to_string (IP_WITH_PORT));
46 Interface::update_statusbar(); 45 m_interface->update_statusbar();
47 } 46 }
48 47
49 m_state = RCON_DISCONNECTED; 48 m_state = RCON_DISCONNECTED;
50 } 49 }
51 50
52 // ------------------------------------------------------------------------------------------------- 51 // -------------------------------------------------------------------------------------------------
53 // 52 //
54 METHOD 53 void RCONSession::send (const Bytestream& packet)
55 RCONSession::send (const Bytestream& packet) -> void
56 { 54 {
57 m_socket.send (m_address, packet); 55 m_socket.send (m_address, packet);
58 } 56 }
59 57
60 // ------------------------------------------------------------------------------------------------- 58 // -------------------------------------------------------------------------------------------------
61 // 59 //
62 METHOD 60 void RCONSession::tick()
63 RCONSession::tick() -> void
64 { 61 {
65 if (m_state == RCON_DISCONNECTED) 62 if (m_state == RCON_DISCONNECTED)
66 return; 63 return;
67 64
68 time_t now; 65 time_t now;
91 handle_packet (datagram.data, datagram.from); 88 handle_packet (datagram.data, datagram.from);
92 } 89 }
93 90
94 // ------------------------------------------------------------------------------------------------- 91 // -------------------------------------------------------------------------------------------------
95 // 92 //
96 METHOD 93 void RCONSession::handle_packet (Bytestream& packet, const IPAddress& from)
97 RCONSession::handle_packet (Bytestream& packet, const IPAddress& from) -> void
98 { 94 {
99 if (from != m_address) 95 if (from != m_address)
100 return; 96 return;
101 97
102 try 98 try
106 int header = packet.read_byte(); 102 int header = packet.read_byte();
107 103
108 switch (ServerResponse (header)) 104 switch (ServerResponse (header))
109 { 105 {
110 case SVRC_OLDPROTOCOL: 106 case SVRC_OLDPROTOCOL:
111 print_error ("Your RCON client is using outdated protocol.\n"); 107 m_interface->print_error ("Your RCON client is using outdated protocol.\n");
112 m_state = RCON_DISCONNECTED; 108 m_state = RCON_DISCONNECTED;
113 break; 109 break;
114 110
115 case SVRC_BANNED: 111 case SVRC_BANNED:
116 print_error ("You have been banned from the server.\n"); 112 m_interface->print_error ("You have been banned from the server.\n");
117 m_state = RCON_DISCONNECTED; 113 m_state = RCON_DISCONNECTED;
118 break; 114 break;
119 115
120 case SVRC_SALT: 116 case SVRC_SALT:
121 m_salt = packet.read_string(); 117 m_salt = packet.read_string();
122 m_state = RCON_AUTHENTICATING; 118 m_state = RCON_AUTHENTICATING;
123 send_password(); 119 send_password();
124 break; 120 break;
125 121
126 case SVRC_INVALIDPASSWORD: 122 case SVRC_INVALIDPASSWORD:
127 print_error ("Login failed.\n"); 123 m_interface->print_error ("Login failed.\n");
128 m_state = RCON_DISCONNECTED; 124 m_state = RCON_DISCONNECTED;
129 break; 125 break;
130 126
131 case SVRC_MESSAGE: 127 case SVRC_MESSAGE:
132 { 128 {
133 String message = packet.read_string(); 129 String message = packet.read_string();
134 message.normalize(); 130 message.normalize();
135 print ("%1\n", message); 131 m_interface->print ("%1\n", message);
136 } 132 }
137 break; 133 break;
138 134
139 case SVRC_LOGGEDIN: 135 case SVRC_LOGGEDIN:
140 print ("Login successful!\n"); 136 m_interface->print ("Login successful!\n");
141 m_serverProtocol = packet.read_byte(); 137 m_serverProtocol = packet.read_byte();
142 m_hostname = packet.read_string(); 138 m_hostname = packet.read_string();
143 Interface::set_title (m_hostname); 139 m_interface->set_title (m_hostname);
144 m_state = RCON_CONNECTED; 140 m_state = RCON_CONNECTED;
145 141
146 for (int i = packet.read_byte(); i > 0; --i) 142 for (int i = packet.read_byte(); i > 0; --i)
147 process_server_updates (packet); 143 process_server_updates (packet);
148 144
149 print ("Previous messages:\n"); 145 m_interface->print ("Previous messages:\n");
150 146
151 for (int i = packet.read_byte(); i > 0; --i) 147 for (int i = packet.read_byte(); i > 0; --i)
152 { 148 {
153 String message = packet.read_string(); 149 String message = packet.read_string();
154 message.normalize(); 150 message.normalize();
155 print ("--- %1\n", message); 151 m_interface->print ("--- %1\n", message);
156 } 152 }
157 153
158 print ("End of previous messages.\n"); 154 m_interface->print ("End of previous messages.\n");
159 break; 155 break;
160 156
161 case SVRC_UPDATE: 157 case SVRC_UPDATE:
162 process_server_updates (packet); 158 process_server_updates (packet);
163 break; 159 break;
164 160
165 case SVRC_TOOMANYTABCOMPLETES: 161 case SVRC_TOOMANYTABCOMPLETES:
166 { 162 {
167 unsigned int numCompletions = packet.read_short(); 163 unsigned int numCompletions = packet.read_short();
168 print ("%1 completions for '%2'.\n", 164 m_interface->print ("%1 completions for '%2'.\n",
169 int (numCompletions), m_lastTabComplete); 165 int (numCompletions), m_lastTabComplete);
170 } 166 }
171 break; 167 break;
172 168
173 case SVRC_TABCOMPLETE: 169 case SVRC_TABCOMPLETE:
176 172
177 for (signed int i = packet.read_byte(); i > 0; --i) 173 for (signed int i = packet.read_byte(); i > 0; --i)
178 completes << packet.read_string(); 174 completes << packet.read_string();
179 175
180 if (completes.size() == 1) 176 if (completes.size() == 1)
181 Interface::tab_complete (m_lastTabComplete, completes[0]); 177 {
178 m_interface->tab_complete (m_lastTabComplete, completes[0]);
179 }
182 else if (not completes.is_empty()) 180 else if (not completes.is_empty())
183 { 181 {
184 print ("Completions for '%1':\n", m_lastTabComplete); 182 m_interface->print ("Completions for '%1':\n", m_lastTabComplete);
185 183
186 for (int i = 0; i < completes.size(); i += 8) 184 for (int i = 0; i < completes.size(); i += 8)
187 { 185 {
188 Range<int> spliceRange (i, min (i + 8, completes.size() - 1)); 186 Range<int> spliceRange (i, min (i + 8, completes.size() - 1));
189 StringList splice (completes.splice (spliceRange)); 187 StringList splice (completes.splice (spliceRange));
190 print ("- %1\n", splice.join (", ")); 188 m_interface->print ("- %1\n", splice.join (", "));
191 } 189 }
192 } 190 }
193 } 191 }
194 break; 192 break;
195 } 193 }
196 } 194 }
197 } 195 }
198 catch (std::exception& e) 196 catch (std::exception& e)
199 { 197 {
200 print_warning ("Couldn't process packet: %1\n", e.what()); 198 m_interface->print_warning ("Couldn't process packet: %1\n", e.what());
201 } 199 }
202 } 200 }
203 201
204 METHOD 202 void RCONSession::process_server_updates (Bytestream& packet)
205 RCONSession::process_server_updates (Bytestream& packet) -> void
206 { 203 {
207 int header = packet.read_byte(); 204 int header = packet.read_byte();
208 205
209 switch (RCONUpdateType (header)) 206 switch (RCONUpdateType (header))
210 { 207 {
213 StringList players; 210 StringList players;
214 211
215 for (int i = packet.read_byte(); i > 0; --i) 212 for (int i = packet.read_byte(); i > 0; --i)
216 players.append (packet.read_string()); 213 players.append (packet.read_string());
217 214
218 Interface::set_player_names (players); 215 m_interface->set_player_names (players);
219 } 216 }
220 break; 217 break;
221 218
222 case SVRCU_ADMINCOUNT: 219 case SVRCU_ADMINCOUNT:
223 m_numAdmins = packet.read_byte(); 220 m_numAdmins = packet.read_byte();
224 Interface::update_statusbar(); 221 m_interface->update_statusbar();
225 break; 222 break;
226 223
227 case SVRCU_MAP: 224 case SVRCU_MAP:
228 m_level = packet.read_string(); 225 m_level = packet.read_string();
229 Interface::update_statusbar(); 226 m_interface->update_statusbar();
230 break; 227 break;
231 228
232 default: 229 default:
233 print_warning ("Unknown server update type: %d\n", header); 230 m_interface->print_warning ("Unknown server update type: %d\n", header);
234 break; 231 break;
235 } 232 }
236 } 233 }
237 234
238 // ------------------------------------------------------------------------------------------------- 235 // -------------------------------------------------------------------------------------------------
239 // 236 //
240 METHOD 237 UDPSocket* RCONSession::socket()
241 RCONSession::socket() -> UDPSocket*
242 { 238 {
243 return &m_socket; 239 return &m_socket;
244 } 240 }
245 241
246 // ------------------------------------------------------------------------------------------------- 242 // -------------------------------------------------------------------------------------------------
247 // 243 //
248 METHOD 244 void RCONSession::send_hello()
249 RCONSession::send_hello() -> void 245 {
250 { 246 m_interface->print ("Connecting to %1...\n", m_address.to_string (IP_WITH_PORT));
251 print ("Connecting to %1...\n", m_address.to_string (IP_WITH_PORT));
252 Bytestream packet; 247 Bytestream packet;
253 packet.write_byte (CLRC_BEGINCONNECTION); 248 packet.write_byte (CLRC_BEGINCONNECTION);
254 packet.write_byte (RCON_PROTOCOL_VERSION); 249 packet.write_byte (RCON_PROTOCOL_VERSION);
255 send (packet); 250 send (packet);
256 bump_last_ping(); 251 bump_last_ping();
257 } 252 }
258 253
259 // ------------------------------------------------------------------------------------------------- 254 // -------------------------------------------------------------------------------------------------
260 // 255 //
261 METHOD 256 void RCONSession::send_password()
262 RCONSession::send_password() -> void 257 {
263 { 258 m_interface->print ("Authenticating...\n");
264 print ("Authenticating...\n");
265 Bytestream packet; 259 Bytestream packet;
266 packet.write_byte (CLRC_PASSWORD); 260 packet.write_byte (CLRC_PASSWORD);
267 packet.write_string ((m_salt + m_password).md5()); 261 packet.write_string ((m_salt + m_password).md5());
268 send (packet); 262 send (packet);
269 bump_last_ping(); 263 bump_last_ping();
270 } 264 }
271 265
272 // ------------------------------------------------------------------------------------------------- 266 // -------------------------------------------------------------------------------------------------
273 // 267 //
274 METHOD 268 void RCONSession::set_password (const String& password)
275 RCONSession::set_password (const String& password) -> void
276 { 269 {
277 m_password = password; 270 m_password = password;
278 } 271 }
279 272
280 // ------------------------------------------------------------------------------------------------- 273 // -------------------------------------------------------------------------------------------------
281 // 274 //
282 METHOD 275 void RCONSession::bump_last_ping()
283 RCONSession::bump_last_ping() -> void
284 { 276 {
285 time_t now; 277 time_t now;
286 time (&now); 278 time (&now);
287 m_lastPing = now; 279 m_lastPing = now;
288 } 280 }
289 281
290 // ------------------------------------------------------------------------------------------------- 282 // -------------------------------------------------------------------------------------------------
291 // 283 //
292 STATIC METHOD 284 bool RCONSession::is_active() const
293 RCONSession::get_session() -> RCONSession*
294 {
295 static RCONSession session;
296 return &session;
297 }
298
299 // -------------------------------------------------------------------------------------------------
300 //
301 METHOD
302 RCONSession::is_active() const -> bool
303 { 285 {
304 return state() != RCON_DISCONNECTED; 286 return state() != RCON_DISCONNECTED;
305 } 287 }
306 288
307 // ------------------------------------------------------------------------------------------------- 289 // -------------------------------------------------------------------------------------------------
308 // Returns true if the message was successfully sent. 290 // Returns true if the message was successfully sent.
309 // 291 //
310 METHOD 292 bool RCONSession::send_command (const String& message)
311 RCONSession::send_command (const String& message) -> bool
312 { 293 {
313 if (m_state != RCON_CONNECTED or message.is_empty()) 294 if (m_state != RCON_CONNECTED or message.is_empty())
314 return false; 295 return false;
315 296
316 Bytestream packet; 297 Bytestream packet;
321 return true; 302 return true;
322 } 303 }
323 304
324 // ------------------------------------------------------------------------------------------------- 305 // -------------------------------------------------------------------------------------------------
325 // 306 //
326 METHOD 307 RCONSessionState RCONSession::state() const
327 RCONSession::state() const -> RCONSessionState
328 { 308 {
329 return m_state; 309 return m_state;
330 } 310 }
331 311
332 // ------------------------------------------------------------------------------------------------- 312 // -------------------------------------------------------------------------------------------------
333 // 313 //
334 METHOD 314 const IPAddress& RCONSession::address() const
335 RCONSession::address() const -> const IPAddress&
336 { 315 {
337 return m_address; 316 return m_address;
338 } 317 }
339 318
340 // ------------------------------------------------------------------------------------------------- 319 // -------------------------------------------------------------------------------------------------
341 // 320 //
342 METHOD 321 int RCONSession::num_admins() const
343 RCONSession::num_admins() const -> int
344 { 322 {
345 return m_numAdmins; 323 return m_numAdmins;
346 } 324 }
347 325
348 // ------------------------------------------------------------------------------------------------- 326 // -------------------------------------------------------------------------------------------------
349 // 327 //
350 METHOD 328 const String& RCONSession::level() const
351 RCONSession::level() const -> const String&
352 { 329 {
353 return m_level; 330 return m_level;
354 } 331 }
355 332
356 // ------------------------------------------------------------------------------------------------- 333 // -------------------------------------------------------------------------------------------------
357 // 334 //
358 METHOD 335 void RCONSession::request_tab_complete (const String& part)
359 RCONSession::request_tab_complete (const String& part) -> void
360 { 336 {
361 if (m_serverProtocol >= 4) 337 if (m_serverProtocol >= 4)
362 { 338 {
363 Bytestream packet; 339 Bytestream packet;
364 packet.write_byte (CLRC_TABCOMPLETE); 340 packet.write_byte (CLRC_TABCOMPLETE);
366 send (packet); 342 send (packet);
367 bump_last_ping(); 343 bump_last_ping();
368 m_lastTabComplete = part; 344 m_lastTabComplete = part;
369 } 345 }
370 else 346 else
371 print ("Server protocol is %1, cannot tab-complete\n", m_serverProtocol); 347 m_interface->print ("Server protocol is %1, cannot tab-complete\n", m_serverProtocol);
372 } 348 }

mercurial