sources/network/rconsession.cpp

changeset 156
ce66d7e374bf
parent 152
6be21be4bea1
child 157
42bb29924218
equal deleted inserted replaced
154:9cdd6b71f0d1 156:ce66d7e374bf
34 BEGIN_ZFC_NAMESPACE 34 BEGIN_ZFC_NAMESPACE
35 35
36 // ------------------------------------------------------------------------------------------------- 36 // -------------------------------------------------------------------------------------------------
37 // 37 //
38 RCONSession::RCONSession() : 38 RCONSession::RCONSession() :
39 m_state (RCON_DISCONNECTED), 39 m_state(RCON_DISCONNECTED),
40 m_lastPing (0), 40 m_lastPing(0),
41 m_numAdmins (0), 41 m_adminCount(0),
42 m_interface (nullptr) 42 m_interface(nullptr)
43 { 43 {
44 if (not m_socket.set_blocking (false)) 44 if (not m_socket.set_blocking(false))
45 { 45 {
46 fprintf (stderr, "unable to set socket as non-blocking: %s\n", 46 fprintf(stderr, "unable to set socket as non-blocking: %s\n",
47 m_socket.error_string().chars()); 47 m_socket.error_string().chars());
48 exit (EXIT_FAILURE); 48 exit(EXIT_FAILURE);
49 } 49 }
50 } 50 }
51 51
52 // ------------------------------------------------------------------------------------------------- 52 // -------------------------------------------------------------------------------------------------
53 // 53 //
54 RCONSession::~RCONSession() {} 54 RCONSession::~RCONSession() {}
55 55
56 // ------------------------------------------------------------------------------------------------- 56 // -------------------------------------------------------------------------------------------------
57 // 57 //
58 void RCONSession::connect (IPAddress address) 58 void RCONSession::connect(IPAddress address)
59 { 59 {
60 m_address = address; 60 m_address = address;
61 m_state = RCON_CONNECTING; 61 m_state = RCON_CONNECTING;
62 m_interface->updateStatusBar(); 62 m_interface->updateStatusBar();
63 send_hello(); 63 sendHello();
64 } 64 }
65 65
66 // ------------------------------------------------------------------------------------------------- 66 // -------------------------------------------------------------------------------------------------
67 // 67 //
68 void RCONSession::disconnect() 68 void RCONSession::disconnect()
69 { 69 {
70 if (m_state > RCON_CONNECTING) 70 if (m_state > RCON_CONNECTING)
71 { 71 {
72 // Say goodbye to remote 72 // Say goodbye to remote
73 Bytestream packet; 73 Bytestream packet;
74 packet.write_byte (CLRC_DISCONNECT); 74 packet.write_byte(CLRC_DISCONNECT);
75 this->send (packet); 75 this->send(packet);
76 m_interface->disconnected(); 76 m_interface->disconnected();
77 } 77 }
78 78
79 m_state = RCON_DISCONNECTED; 79 m_state = RCON_DISCONNECTED;
80 } 80 }
81 81
82 // ------------------------------------------------------------------------------------------------- 82 // -------------------------------------------------------------------------------------------------
83 // 83 //
84 void RCONSession::send (const Bytestream& packet) 84 void RCONSession::send(const Bytestream& packet)
85 { 85 {
86 m_socket.send (m_address, packet); 86 m_socket.send(m_address, packet);
87 } 87 }
88 88
89 // ------------------------------------------------------------------------------------------------- 89 // -------------------------------------------------------------------------------------------------
90 // 90 //
91 void RCONSession::tick() 91 void RCONSession::tick()
92 { 92 {
93 if (m_state == RCON_DISCONNECTED) 93 if (m_state == RCON_DISCONNECTED)
94 return; 94 return;
95 95
96 time_t now; 96 time_t now;
97 time (&now); 97 time(&now);
98 98
99 if (m_lastPing < now) 99 if (m_lastPing < now)
100 { 100 {
101 if (m_state == RCON_CONNECTING) 101 if (m_state == RCON_CONNECTING)
102 { 102 {
103 send_hello(); 103 sendHello();
104 } 104 }
105 else if (m_state == RCON_AUTHENTICATING) 105 else if (m_state == RCON_AUTHENTICATING)
106 { 106 {
107 send_password(); 107 sendPassword();
108 } 108 }
109 else if (m_state == RCON_CONNECTED and m_lastPing + 5 < now) 109 else if (m_state == RCON_CONNECTED and m_lastPing + 5 < now)
110 { 110 {
111 Bytestream packet; 111 Bytestream packet;
112 packet.write_byte (CLRC_PONG); 112 packet.write_byte(CLRC_PONG);
113 send (packet); 113 send(packet);
114 bump_last_ping(); 114 bumpLastPing();
115 } 115 }
116 } 116 }
117 117
118 for (Datagram datagram; m_socket.read (datagram);) 118 for (Datagram datagram; m_socket.read(datagram);)
119 handle_packet (datagram); 119 handlePacket(datagram);
120 } 120 }
121 121
122 // ------------------------------------------------------------------------------------------------- 122 // -------------------------------------------------------------------------------------------------
123 // 123 //
124 void RCONSession::handle_packet (Datagram& datagram) 124 void RCONSession::handlePacket(Datagram& datagram)
125 { 125 {
126 if (datagram.address != m_address) 126 if (datagram.address != m_address)
127 return; 127 return;
128 128
129 try 129 try
130 { 130 {
131 while (datagram.message.bytes_left() > 0) 131 while (datagram.message.bytes_left() > 0)
132 { 132 {
133 int header = datagram.message.read_byte(); 133 int header = datagram.message.read_byte();
134 134
135 switch (ServerResponse (header)) 135 switch (ServerResponse(header))
136 { 136 {
137 case SVRC_OLDPROTOCOL: 137 case SVRC_OLDPROTOCOL:
138 m_interface->printError ("Your RCON client is using outdated protocol.\n"); 138 m_interface->printError("Your RCON client is using outdated protocol.\n");
139 m_state = RCON_DISCONNECTED; 139 m_state = RCON_DISCONNECTED;
140 break; 140 break;
141 141
142 case SVRC_BANNED: 142 case SVRC_BANNED:
143 m_interface->printError ("You have been banned from the server.\n"); 143 m_interface->printError("You have been banned from the server.\n");
144 m_state = RCON_DISCONNECTED; 144 m_state = RCON_DISCONNECTED;
145 break; 145 break;
146 146
147 case SVRC_SALT: 147 case SVRC_SALT:
148 m_salt = datagram.message.read_string(); 148 m_salt = datagram.message.read_string();
149 m_state = RCON_AUTHENTICATING; 149 m_state = RCON_AUTHENTICATING;
150 send_password(); 150 sendPassword();
151 break; 151 break;
152 152
153 case SVRC_INVALIDPASSWORD: 153 case SVRC_INVALIDPASSWORD:
154 m_interface->printError ("Login failed.\n"); 154 m_interface->printError("Login failed.\n");
155 m_state = RCON_DISCONNECTED; 155 m_state = RCON_DISCONNECTED;
156 break; 156 break;
157 157
158 case SVRC_MESSAGE: 158 case SVRC_MESSAGE:
159 { 159 {
160 String message = datagram.message.read_string(); 160 String message = datagram.message.read_string();
161 message.normalize(); 161 message.normalize();
162 m_interface->printText ("%s\n", message.chars()); 162 m_interface->printText("%s\n", message.chars());
163 } 163 }
164 break; 164 break;
165 165
166 case SVRC_LOGGEDIN: 166 case SVRC_LOGGEDIN:
167 m_interface->print ("Login successful!\n"); 167 m_interface->print("Login successful!\n");
168 m_serverProtocol = datagram.message.read_byte(); 168 m_serverProtocol = datagram.message.read_byte();
169 m_hostname = datagram.message.read_string(); 169 m_hostname = datagram.message.read_string();
170 m_interface->setTitle (m_hostname); 170 m_interface->setTitle(m_hostname);
171 m_state = RCON_CONNECTED; 171 m_state = RCON_CONNECTED;
172 172
173 for (int i = datagram.message.read_byte(); i > 0; --i) 173 for (int i = datagram.message.read_byte(); i > 0; --i)
174 process_server_updates (datagram.message); 174 processServerUpdates(datagram.message);
175 175
176 m_interface->print ("Previous messages:\n"); 176 m_interface->print("Previous messages:\n");
177 177
178 for (int i = datagram.message.read_byte(); i > 0; --i) 178 for (int i = datagram.message.read_byte(); i > 0; --i)
179 { 179 {
180 String message = datagram.message.read_string(); 180 String message = datagram.message.read_string();
181 message.normalize(); 181 message.normalize();
182 m_interface->printText ("--- %s\n", message.chars()); 182 m_interface->printText("--- %s\n", message.chars());
183 } 183 }
184 184
185 m_interface->print ("End of previous messages.\n"); 185 m_interface->print("End of previous messages.\n");
186 break; 186 break;
187 187
188 case SVRC_UPDATE: 188 case SVRC_UPDATE:
189 process_server_updates (datagram.message); 189 processServerUpdates(datagram.message);
190 break; 190 break;
191 191
192 case SVRC_TOOMANYTABCOMPLETES: 192 case SVRC_TOOMANYTABCOMPLETES:
193 { 193 {
194 unsigned int numCompletions = datagram.message.read_short(); 194 unsigned int numCompletions = datagram.message.read_short();
195 m_interface->print ("%d completions for '%s'.\n", 195 m_interface->print("%d completions for '%s'.\n",
196 int (numCompletions), m_lastTabComplete.chars()); 196 int(numCompletions), m_lastTabComplete.chars());
197 } 197 }
198 break; 198 break;
199 199
200 case SVRC_TABCOMPLETE: 200 case SVRC_TABCOMPLETE:
201 { 201 {
205 for (String& completion : completes) 205 for (String& completion : completes)
206 completion = datagram.message.read_string(); 206 completion = datagram.message.read_string();
207 207
208 if (completes.size() == 1) 208 if (completes.size() == 1)
209 { 209 {
210 m_interface->tabComplete (m_lastTabComplete, completes[0]); 210 m_interface->tabComplete(m_lastTabComplete, completes[0]);
211 } 211 }
212 else if (not completes.is_empty()) 212 else if (not completes.is_empty())
213 { 213 {
214 m_interface->print ("Completions for '%s':\n", m_lastTabComplete.chars()); 214 m_interface->print("Completions for '%s':\n", m_lastTabComplete.chars());
215 215
216 for (int i : range(0, completes.size(), 8)) 216 for (int i : range(0, completes.size(), 8))
217 { 217 {
218 Range<int> spliceRange (i, min (i + 8, completes.size())); 218 Range<int> spliceRange(i, min(i + 8, completes.size()));
219 StringList splice (completes.splice (spliceRange)); 219 StringList splice(completes.splice(spliceRange));
220 m_interface->print ("- %s\n", splice.join (", ").chars()); 220 m_interface->print("- %s\n", splice.join(", ").chars());
221 } 221 }
222 } 222 }
223 } 223 }
224 break; 224 break;
225 } 225 }
226 } 226 }
227 } 227 }
228 catch (std::exception& e) 228 catch (std::exception& e)
229 { 229 {
230 m_interface->printWarning ("Couldn't process packet: %s\n", e.what()); 230 m_interface->printWarning("Couldn't process packet: %s\n", e.what());
231 } 231 }
232 } 232 }
233 233
234 void RCONSession::process_server_updates (Bytestream& packet) 234 void RCONSession::processServerUpdates(Bytestream& packet)
235 { 235 {
236 int header = packet.read_byte(); 236 int header = packet.read_byte();
237 237
238 switch (RCONUpdateType (header)) 238 switch (RCONUpdateType(header))
239 { 239 {
240 case SVRCU_PLAYERDATA: 240 case SVRCU_PLAYERDATA:
241 { 241 {
242 StringList players; 242 StringList players;
243 243
244 for (int i = packet.read_byte(); i > 0; --i) 244 for (int i = packet.read_byte(); i > 0; --i)
245 players.append (packet.read_string()); 245 players.append(packet.read_string());
246 246
247 m_interface->setPlayerNames (players); 247 m_interface->setPlayerNames(players);
248 } 248 }
249 break; 249 break;
250 250
251 case SVRCU_ADMINCOUNT: 251 case SVRCU_ADMINCOUNT:
252 m_numAdmins = packet.read_byte(); 252 m_adminCount = packet.read_byte();
253 m_interface->updateStatusBar(); 253 m_interface->updateStatusBar();
254 break; 254 break;
255 255
256 case SVRCU_MAP: 256 case SVRCU_MAP:
257 m_level = packet.read_string(); 257 m_level = packet.read_string();
258 m_interface->updateStatusBar(); 258 m_interface->updateStatusBar();
259 break; 259 break;
260 260
261 default: 261 default:
262 m_interface->printWarning ("Unknown server update type: %d\n", header); 262 m_interface->printWarning("Unknown server update type: %d\n", header);
263 break; 263 break;
264 } 264 }
265 } 265 }
266 266
267 // ------------------------------------------------------------------------------------------------- 267 // -------------------------------------------------------------------------------------------------
268 // 268 //
269 UDPSocket* RCONSession::socket() 269 UDPSocket* RCONSession::getSocket()
270 { 270 {
271 return &m_socket; 271 return &m_socket;
272 } 272 }
273 273
274 // ------------------------------------------------------------------------------------------------- 274 // -------------------------------------------------------------------------------------------------
275 // 275 //
276 void RCONSession::send_hello() 276 void RCONSession::sendHello()
277 { 277 {
278 m_interface->print ("Connecting to %s...\n", 278 m_interface->print("Connecting to %s...\n", m_address.to_string(IPAddress::WITH_PORT).chars());
279 m_address.to_string (IPAddress::WITH_PORT).chars());
280 Bytestream packet; 279 Bytestream packet;
281 packet.write_byte (CLRC_BEGINCONNECTION); 280 packet.write_byte(CLRC_BEGINCONNECTION);
282 packet.write_byte (RCON_PROTOCOL_VERSION); 281 packet.write_byte(RCON_PROTOCOL_VERSION);
283 send (packet); 282 send(packet);
284 bump_last_ping(); 283 bumpLastPing();
285 } 284 }
286 285
287 // ------------------------------------------------------------------------------------------------- 286 // -------------------------------------------------------------------------------------------------
288 // 287 //
289 void RCONSession::send_password() 288 void RCONSession::sendPassword()
290 { 289 {
291 m_interface->print ("Authenticating...\n"); 290 m_interface->print("Authenticating...\n");
292 Bytestream packet; 291 Bytestream packet;
293 packet.write_byte (CLRC_PASSWORD); 292 packet.write_byte(CLRC_PASSWORD);
294 packet.write_string ((m_salt + m_password).md5()); 293 packet.write_string((m_salt + m_password).md5());
295 send (packet); 294 send(packet);
296 bump_last_ping(); 295 bumpLastPing();
297 } 296 }
298 297
299 // ------------------------------------------------------------------------------------------------- 298 // -------------------------------------------------------------------------------------------------
300 // 299 //
301 void RCONSession::set_password (const String& password) 300 void RCONSession::setPassword(const String& password)
302 { 301 {
303 m_password = password; 302 m_password = password;
304 } 303 }
305 304
306 // ------------------------------------------------------------------------------------------------- 305 // -------------------------------------------------------------------------------------------------
307 // 306 //
308 void RCONSession::bump_last_ping() 307 void RCONSession::bumpLastPing()
309 { 308 {
310 time_t now; 309 time_t now;
311 time (&now); 310 time(&now);
312 m_lastPing = now; 311 m_lastPing = now;
313 } 312 }
314 313
315 // ------------------------------------------------------------------------------------------------- 314 // -------------------------------------------------------------------------------------------------
316 // 315 //
317 bool RCONSession::is_active() const 316 bool RCONSession::isActive() const
318 { 317 {
319 return state() != RCON_DISCONNECTED; 318 return getState() != RCON_DISCONNECTED;
320 } 319 }
321 320
322 // ------------------------------------------------------------------------------------------------- 321 // -------------------------------------------------------------------------------------------------
323 // Returns true if the message was successfully sent. 322 // Returns true if the message was successfully sent.
324 // 323 //
325 bool RCONSession::send_command (const String& message) 324 bool RCONSession::sendCommand(const String& message)
326 { 325 {
327 if (m_state != RCON_CONNECTED or message.isEmpty()) 326 if (m_state != RCON_CONNECTED or message.isEmpty())
328 return false; 327 return false;
329 328
330 Bytestream packet; 329 Bytestream packet;
331 packet.write_byte (CLRC_COMMAND); 330 packet.write_byte(CLRC_COMMAND);
332 packet.write_string (message); 331 packet.write_string(message);
333 send (packet); 332 send(packet);
334 bump_last_ping(); 333 bumpLastPing();
335 return true; 334 return true;
336 } 335 }
337 336
338 // ------------------------------------------------------------------------------------------------- 337 // -------------------------------------------------------------------------------------------------
339 // 338 //
340 RCONSessionState RCONSession::state() const 339 RCONSessionState RCONSession::getState() const
341 { 340 {
342 return m_state; 341 return m_state;
343 } 342 }
344 343
345 // ------------------------------------------------------------------------------------------------- 344 // -------------------------------------------------------------------------------------------------
349 return m_address; 348 return m_address;
350 } 349 }
351 350
352 // ------------------------------------------------------------------------------------------------- 351 // -------------------------------------------------------------------------------------------------
353 // 352 //
354 int RCONSession::num_admins() const 353 int RCONSession::getAdminCount() const
355 { 354 {
356 return m_numAdmins; 355 return m_adminCount;
357 } 356 }
358 357
359 // ------------------------------------------------------------------------------------------------- 358 // -------------------------------------------------------------------------------------------------
360 // 359 //
361 const String& RCONSession::level() const 360 const String& RCONSession::getLevel() const
362 { 361 {
363 return m_level; 362 return m_level;
364 } 363 }
365 364
366 // ------------------------------------------------------------------------------------------------- 365 // -------------------------------------------------------------------------------------------------
367 // 366 //
368 void RCONSession::request_tab_complete (const String& part) 367 void RCONSession::requestTabCompletion(const String& part)
369 { 368 {
370 if (m_serverProtocol >= 4) 369 if (m_serverProtocol >= 4)
371 { 370 {
372 Bytestream packet; 371 Bytestream packet;
373 packet.write_byte (CLRC_TABCOMPLETE); 372 packet.write_byte(CLRC_TABCOMPLETE);
374 packet.write_string (part); 373 packet.write_string(part);
375 send (packet); 374 send(packet);
376 bump_last_ping(); 375 bumpLastPing();
377 m_lastTabComplete = part; 376 m_lastTabComplete = part;
378 } 377 }
379 else 378 else
380 { 379 {
381 m_interface->print ("This server does not support tab-completion\n", m_serverProtocol); 380 m_interface->print("This server does not support tab-completion\n", m_serverProtocol);
382 } 381 }
383 } 382 }
384 383
385 // ------------------------------------------------------------------------------------------------- 384 // -------------------------------------------------------------------------------------------------
386 // 385 //
387 void RCONSession::set_interface (Interface* iface) 386 void RCONSession::setInterface(Interface* interface)
388 { 387 {
389 m_interface = iface; 388 m_interface = interface;
390 } 389 }
391 390
392 END_ZFC_NAMESPACE 391 END_ZFC_NAMESPACE

mercurial