42 m_interface(nullptr) |
43 m_interface(nullptr) |
43 { |
44 { |
44 if (not m_socket.set_blocking(false)) |
45 if (not m_socket.set_blocking(false)) |
45 { |
46 { |
46 fprintf(stderr, "unable to set socket as non-blocking: %s\n", |
47 fprintf(stderr, "unable to set socket as non-blocking: %s\n", |
47 m_socket.error_string().chars()); |
48 m_socket.error_string().data()); |
48 exit(EXIT_FAILURE); |
49 exit(EXIT_FAILURE); |
49 } |
50 } |
50 } |
51 } |
51 |
52 |
52 // ------------------------------------------------------------------------------------------------- |
53 // ------------------------------------------------------------------------------------------------- |
175 m_interface->print("Previous messages:\n"); |
176 m_interface->print("Previous messages:\n"); |
176 |
177 |
177 for (int i = stream.readByte(); i > 0; --i) |
178 for (int i = stream.readByte(); i > 0; --i) |
178 { |
179 { |
179 String message = stream.readString(); |
180 String message = stream.readString(); |
180 message.normalize(); |
181 normalize(message); |
181 m_interface->printText("--- %s\n", message.chars()); |
182 m_interface->printText("--- %s\n", message.data()); |
182 } |
183 } |
183 |
184 |
184 m_interface->print("End of previous messages.\n"); |
185 m_interface->print("End of previous messages.\n"); |
185 break; |
186 break; |
186 |
187 |
190 |
191 |
191 case SVRC_TOOMANYTABCOMPLETES: |
192 case SVRC_TOOMANYTABCOMPLETES: |
192 { |
193 { |
193 unsigned int numCompletions = stream.readShort(); |
194 unsigned int numCompletions = stream.readShort(); |
194 m_interface->print("%d completions for '%s'.\n", |
195 m_interface->print("%d completions for '%s'.\n", |
195 int(numCompletions), m_lastTabComplete.chars()); |
196 int(numCompletions), m_lastTabComplete.data()); |
196 } |
197 } |
197 break; |
198 break; |
198 |
199 |
199 case SVRC_TABCOMPLETE: |
200 case SVRC_TABCOMPLETE: |
200 { |
201 { |
208 { |
209 { |
209 m_interface->tabComplete(m_lastTabComplete, completes[0]); |
210 m_interface->tabComplete(m_lastTabComplete, completes[0]); |
210 } |
211 } |
211 else if (completes.size() > 0) |
212 else if (completes.size() > 0) |
212 { |
213 { |
213 m_interface->print("Completions for '%s':\n", m_lastTabComplete.chars()); |
214 m_interface->print("Completions for '%s':\n", m_lastTabComplete.data()); |
214 |
215 |
215 for (int i : range(0, static_cast<int>(completes.size()), 8)) |
216 for (int i : range(0, static_cast<int>(completes.size()), 8)) |
216 { |
217 { |
217 const int end = min(i + 8, static_cast<int>(completes.size())); |
218 const int end = min(i + 8, static_cast<int>(completes.size())); |
218 StringList splices = splice(completes, i, end); |
219 StringList splices = splice(completes, i, end); |
219 m_interface->print("- %s\n", join_string_list(splices, ", ").chars()); |
220 m_interface->print("- %s\n", join_string_list(splices, ", ").data()); |
220 } |
221 } |
221 } |
222 } |
222 } |
223 } |
223 break; |
224 break; |
224 } |
225 } |
225 } |
226 } |
226 } |
227 } |
227 catch (std::exception& e) |
228 catch (std::exception& e) |
228 { |
229 { |
229 m_interface->printWarning("Couldn't process packet: %s\n", e.what()); |
230 m_interface->printWarning("Couldn't process packet: %s\n", e.what()); |
230 m_interface->printWarning("Packet contents was: %s\n", quote(message).chars()); |
231 m_interface->printWarning("Packet contents was: %s\n", quote(message).data()); |
231 m_interface->printWarning("Stream position in payload was: %d\n", stream.position()); |
232 m_interface->printWarning("Stream position in payload was: %d\n", stream.position()); |
232 } |
233 } |
233 } |
234 } |
234 |
235 |
235 void RCONSession::processServerUpdates(Bytestream& packet) |
236 void RCONSession::processServerUpdates(Bytestream& packet) |
274 |
275 |
275 // ------------------------------------------------------------------------------------------------- |
276 // ------------------------------------------------------------------------------------------------- |
276 // |
277 // |
277 void RCONSession::sendHello() |
278 void RCONSession::sendHello() |
278 { |
279 { |
279 m_interface->print("Connecting to %s...\n", m_address.to_string(IPAddress::WITH_PORT).chars()); |
280 m_interface->print("Connecting to %s...\n", m_address.to_string(IPAddress::WITH_PORT).data()); |
280 send({CLRC_BEGINCONNECTION, RCON_PROTOCOL_VERSION}); |
281 send({CLRC_BEGINCONNECTION, RCON_PROTOCOL_VERSION}); |
281 bumpLastPing(); |
282 bumpLastPing(); |
282 } |
283 } |
283 |
284 |
284 // ------------------------------------------------------------------------------------------------- |
285 // ------------------------------------------------------------------------------------------------- |
287 { |
288 { |
288 m_interface->print("Authenticating...\n"); |
289 m_interface->print("Authenticating...\n"); |
289 ByteArray message; |
290 ByteArray message; |
290 Bytestream stream(message); |
291 Bytestream stream(message); |
291 stream.writeByte(CLRC_PASSWORD); |
292 stream.writeByte(CLRC_PASSWORD); |
292 stream.writeString((m_salt + m_password).md5()); |
293 stream.writeString(md5((m_salt + m_password).data())); |
293 send(message); |
294 send(message); |
294 bumpLastPing(); |
295 bumpLastPing(); |
295 } |
296 } |
296 |
297 |
297 // ------------------------------------------------------------------------------------------------- |
298 // ------------------------------------------------------------------------------------------------- |
320 // ------------------------------------------------------------------------------------------------- |
321 // ------------------------------------------------------------------------------------------------- |
321 // Returns true if the message was successfully sent. |
322 // Returns true if the message was successfully sent. |
322 // |
323 // |
323 bool RCONSession::sendCommand(const String& commandString) |
324 bool RCONSession::sendCommand(const String& commandString) |
324 { |
325 { |
325 if (m_state != RCON_CONNECTED or commandString.isEmpty()) |
326 if (m_state != RCON_CONNECTED or commandString.empty()) |
326 return false; |
327 return false; |
327 |
328 |
328 ByteArray message; |
329 ByteArray message; |
329 Bytestream stream(message); |
330 Bytestream stream(message); |
330 stream.writeByte(CLRC_COMMAND); |
331 stream.writeByte(CLRC_COMMAND); |