56 |
56 |
57 // ------------------------------------------------------------------------------------------------- |
57 // ------------------------------------------------------------------------------------------------- |
58 // |
58 // |
59 void RCONSession::connect(net::ip_address address) |
59 void RCONSession::connect(net::ip_address address) |
60 { |
60 { |
61 m_address = address; |
61 this->m_address = address; |
62 m_state = RCON_CONNECTING; |
62 this->m_state = RCON_CONNECTING; |
63 m_interface->updateStatusBar(); |
63 this->m_interface->updateStatusBar(); |
64 sendHello(); |
64 this->tick(); |
65 } |
65 } |
66 |
66 |
67 // ------------------------------------------------------------------------------------------------- |
67 // ------------------------------------------------------------------------------------------------- |
68 // |
68 // |
69 void RCONSession::disconnect() |
69 void RCONSession::disconnect() |
96 void RCONSession::tick() |
96 void RCONSession::tick() |
97 { |
97 { |
98 if (m_state == RCON_DISCONNECTED) |
98 if (m_state == RCON_DISCONNECTED) |
99 return; |
99 return; |
100 |
100 |
101 time_t now; |
101 const std::time_t now = std::time(nullptr); |
102 time(&now); |
|
103 |
102 |
104 if (m_lastPing < now) |
103 if (m_lastPing < now) |
105 { |
104 { |
106 if (m_state == RCON_CONNECTING) |
105 // This code block is reached every second |
|
106 switch (m_state) |
107 { |
107 { |
108 sendHello(); |
108 case RCON_CONNECTING: |
|
109 m_interface->print("Connecting to %s...\n", net::ip_address_to_string(m_address).data()); |
|
110 this->send({CLRC_BEGINCONNECTION, RCON_PROTOCOL_VERSION}); |
|
111 break; |
|
112 case RCON_AUTHENTICATING: |
|
113 m_interface->print("Authenticating...\n"); |
|
114 { |
|
115 std::vector<unsigned char> message; |
|
116 Bytestream stream(message); |
|
117 stream.writeByte(CLRC_PASSWORD); |
|
118 stream.writeString(md5((m_salt + m_password).data())); |
|
119 this->send(message); |
|
120 } |
|
121 break; |
|
122 case RCON_CONNECTED: |
|
123 if (this->m_lastPing + 5 < now) |
|
124 { |
|
125 this->send({CLRC_PONG}); |
|
126 } |
|
127 break; |
|
128 case RCON_DISCONNECTED: |
|
129 break; |
109 } |
130 } |
110 else if (m_state == RCON_AUTHENTICATING) |
131 this->m_lastPing = now; |
111 { |
|
112 sendPassword(); |
|
113 } |
|
114 else if (m_state == RCON_CONNECTED and m_lastPing + 5 < now) |
|
115 { |
|
116 send({CLRC_PONG}); |
|
117 bumpLastPing(); |
|
118 } |
|
119 } |
132 } |
120 |
133 |
121 // Check for new packets in our socket |
134 // Check for new packets in our socket |
122 std::stringstream errors; |
135 std::stringstream errors; |
123 for (net::Datagram datagram; m_socket.read(datagram, errors);) |
136 for (net::Datagram datagram; m_socket.read(datagram, errors);) |
158 break; |
171 break; |
159 |
172 |
160 case SVRC_SALT: |
173 case SVRC_SALT: |
161 m_salt = stream.readString(); |
174 m_salt = stream.readString(); |
162 m_state = RCON_AUTHENTICATING; |
175 m_state = RCON_AUTHENTICATING; |
163 sendPassword(); |
|
164 break; |
176 break; |
165 |
177 |
166 case SVRC_INVALIDPASSWORD: |
178 case SVRC_INVALIDPASSWORD: |
167 m_interface->printError("Login failed.\n"); |
179 m_interface->printError("Login failed.\n"); |
168 m_state = RCON_DISCONNECTED; |
180 m_state = RCON_DISCONNECTED; |
286 return &m_socket; |
298 return &m_socket; |
287 } |
299 } |
288 |
300 |
289 // ------------------------------------------------------------------------------------------------- |
301 // ------------------------------------------------------------------------------------------------- |
290 // |
302 // |
291 void RCONSession::sendHello() |
|
292 { |
|
293 m_interface->print("Connecting to %s...\n", net::ip_address_to_string(m_address).data()); |
|
294 send({CLRC_BEGINCONNECTION, RCON_PROTOCOL_VERSION}); |
|
295 bumpLastPing(); |
|
296 } |
|
297 |
|
298 // ------------------------------------------------------------------------------------------------- |
|
299 // |
|
300 void RCONSession::sendPassword() |
|
301 { |
|
302 m_interface->print("Authenticating...\n"); |
|
303 std::vector<unsigned char> message; |
|
304 Bytestream stream(message); |
|
305 stream.writeByte(CLRC_PASSWORD); |
|
306 stream.writeString(md5((m_salt + m_password).data())); |
|
307 send(message); |
|
308 bumpLastPing(); |
|
309 } |
|
310 |
|
311 // ------------------------------------------------------------------------------------------------- |
|
312 // |
|
313 void RCONSession::setPassword(const std::string& password) |
303 void RCONSession::setPassword(const std::string& password) |
314 { |
304 { |
315 m_password = password; |
305 m_password = password; |
316 } |
306 } |
317 |
307 |
342 std::vector<unsigned char> message; |
332 std::vector<unsigned char> message; |
343 Bytestream stream(message); |
333 Bytestream stream(message); |
344 stream.writeByte(CLRC_COMMAND); |
334 stream.writeByte(CLRC_COMMAND); |
345 stream.writeString(commandString); |
335 stream.writeString(commandString); |
346 send(message); |
336 send(message); |
347 bumpLastPing(); |
|
348 return true; |
337 return true; |
349 } |
338 } |
350 |
339 |
351 // ------------------------------------------------------------------------------------------------- |
340 // ------------------------------------------------------------------------------------------------- |
352 // |
341 // |
385 std::vector<unsigned char> message; |
374 std::vector<unsigned char> message; |
386 Bytestream stream(message); |
375 Bytestream stream(message); |
387 stream.writeByte(CLRC_TABCOMPLETE); |
376 stream.writeByte(CLRC_TABCOMPLETE); |
388 stream.writeString(part); |
377 stream.writeString(part); |
389 send(message); |
378 send(message); |
390 bumpLastPing(); |
|
391 m_lastTabComplete = part; |
379 m_lastTabComplete = part; |
392 } |
380 } |
393 else |
381 else |
394 { |
382 { |
395 m_interface->print("This server does not support tab-completion\n"); |
383 m_interface->print("This server does not support tab-completion\n"); |