sources/network/rconsession.cpp

branch
protocol5
changeset 195
be953e1621d9
parent 176
060a13878ca0
parent 191
2e6cbacafdc7
child 199
927f4b8ef6f7
--- a/sources/network/rconsession.cpp	Wed Jan 27 12:41:50 2021 +0200
+++ b/sources/network/rconsession.cpp	Wed Jan 27 19:48:41 2021 +0200
@@ -1,5 +1,5 @@
 /*
-	Copyright 2014 - 2016 Teemu Piippo
+	Copyright 2014 - 2021 Teemu Piippo
 	All rights reserved.
 
 	Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
 #include <time.h>
 #include "rconsession.h"
 #include "../interface.h"
+#include "../md5.h"
 BEGIN_ZFC_NAMESPACE
 
 // -------------------------------------------------------------------------------------------------
@@ -41,10 +42,10 @@
 	m_adminCount(0),
 	m_interface(nullptr)
 {
-	if (not m_socket.set_blocking(false))
+	std::stringstream errors;
+	if (not m_socket.set_blocking(false, errors))
 	{
-		fprintf(stderr, "unable to set socket as non-blocking: %s\n",
-			m_socket.error_string().chars());
+		fprintf(stderr, "unable to set socket as non-blocking: %s\n", errors.str().data());
 		exit(EXIT_FAILURE);
 	}
 }
@@ -55,7 +56,7 @@
 
 // -------------------------------------------------------------------------------------------------
 //
-void RCONSession::connect(IPAddress address)
+void RCONSession::connect(net::ip_address address)
 {
 	m_address = address;
 	m_state = RCON_CONNECTING;
@@ -79,9 +80,15 @@
 
 // -------------------------------------------------------------------------------------------------
 //
-void RCONSession::send(const ByteArray& packet)
+bool RCONSession::send(const std::vector<unsigned char>& packet)
 {
-	m_socket.send(m_address, packet);
+	std::stringstream errors;
+	const bool result = m_socket.send(m_address, packet, errors);
+	if (not result)
+	{
+		this->m_interface->printError("Network error: %s\n", errors.str().data());
+	}
+	return result;
 }
 
 // -------------------------------------------------------------------------------------------------
@@ -112,8 +119,14 @@
 	}
 
 	// Check for new packets in our socket
-	for (Datagram datagram; m_socket.read(datagram);)
+	std::stringstream errors;
+	for (net::Datagram datagram; m_socket.read(datagram, errors);)
 	{
+		if (errors.tellp() > 0)
+		{
+			m_interface->printError("Network error: %s\n", errors.str().data());
+			errors = {};
+		}
 		// Only process packets that originate from the game server.
 		if (datagram.address == m_address)
 			handlePacket(datagram.message);
@@ -122,7 +135,7 @@
 
 // -------------------------------------------------------------------------------------------------
 //
-void RCONSession::handlePacket(ByteArray& message)
+void RCONSession::handlePacket(std::vector<unsigned char>& message)
 {
 	Bytestream stream(message);
 
@@ -157,9 +170,9 @@
 
 			case SVRC_MESSAGE:
 				{
-					String message = stream.readString();
-					message.normalize();
-					m_interface->printText("%s\n", message.chars());
+					std::string message = stream.readString();
+					normalize(message);
+					m_interface->printText("%s\n", message.data());
 				}
 				break;
 
@@ -177,9 +190,9 @@
 
 				for (int i = stream.readByte(); i > 0; --i)
 				{
-					String message = stream.readString();
-					message.normalize();
-					m_interface->printText("--- %s\n", message.chars());
+					std::string message = stream.readString();
+					normalize(message);
+					m_interface->printText("--- %s\n", message.data());
 				}
 
 				m_interface->print("End of previous messages.\n");
@@ -197,55 +210,55 @@
 				{
 					unsigned int numCompletions = stream.readShort();
 					m_interface->print("%d completions for '%s'.\n",
-						int(numCompletions), m_lastTabComplete.chars());
+						int(numCompletions), m_lastTabComplete.data());
 				}
 				break;
 
 			case SVRC_TABCOMPLETE:
 				{
-					StringList completes;
+					std::vector<std::string> completes;
 					completes.resize(stream.readByte());
 
-					for (String& completion : completes)
+					for (std::string& completion : completes)
 						completion = stream.readString();
 
 					if (completes.size() == 1)
 					{
 						m_interface->tabComplete(m_lastTabComplete, completes[0]);
 					}
-					else if (not completes.is_empty())
+					else if (completes.size() > 0)
 					{
-						m_interface->print("Completions for '%s':\n", m_lastTabComplete.chars());
+						m_interface->print("Completions for '%s':\n", m_lastTabComplete.data());
 
-						for (int i : range(0, completes.size(), 8))
+						for (std::size_t i = 0; i < completes.size(); i += 8)
 						{
-							Range<int> spliceRange(i, min(i + 8, completes.size()));
-							StringList splice(completes.splice(spliceRange));
-							m_interface->print("- %s\n", splice.join(", ").chars());
+							const int end = min(i + 8, completes.size());
+							std::vector<std::string> splices = splice(completes, i, end);
+							m_interface->print("- %s\n", join_string_list(splices, ", ").data());
 						}
 					}
 				}
 				break;
 
 			case SVRC_WATCHINGCVAR:
-				m_interface->print ("You are now watching %s\n", stream.readString().chars());
-				m_interface->print ("Its value is: %s\n", stream.readString().chars());
+				m_interface->print ("You are now watching %s\n", stream.readString().data());
+				m_interface->print ("Its value is: %s\n", stream.readString().data());
 				break;
 
 			case SVRC_ALREADYWATCHINGCVAR:
-				m_interface->print ("You are already watching %s\n", stream.readString().chars());
+				m_interface->print ("You are already watching %s\n", stream.readString().data());
 				break;
 
 			case SVRC_WATCHCVARNOTFOUND:
-				m_interface->print ("CVar %s not found\n", stream.readString().chars());
+				m_interface->print ("CVar %s not found\n", stream.readString().data());
 				break;
 
 			case SVRC_CVARCHANGED:
 				{
 					String name = stream.readString();
 					String value = stream.readString();
-					m_interface->print ("The value of CVar %s", name.chars());
-					m_interface->print (" is now %s\n", value.chars());
+					m_interface->print ("The value of CVar %s", name.data());
+					m_interface->print (" is now %s\n", value.data());
 
 					// If sv_hostname changes, update the titlebar
 					if (name == "sv_hostname")
@@ -257,7 +270,7 @@
 				break;
 
 			case SVRC_YOUREDISCONNECTED:
-				m_interface->print ("You have been disconnected: %s\n", stream.readString().chars());
+				m_interface->print ("You have been disconnected: %s\n", stream.readString().data());
 				m_interface->disconnected();
 				break;
 			}
@@ -266,7 +279,7 @@
 	catch (std::exception& e)
 	{
 		m_interface->printWarning("Couldn't process packet: %s\n", e.what());
-		m_interface->printWarning("Packet contents was: %s\n", message.quote().chars());
+		m_interface->printWarning("Packet contents was: %s\n", quote(message).data());
 		m_interface->printWarning("Stream position in payload was: %d\n", stream.position());
 	}
 }
@@ -279,10 +292,10 @@
 	{
 	case SVRCU_PLAYERDATA:
 		{
-			StringList players;
+			std::vector<std::string> players;
 
 			for (int i = packet.readByte(); i > 0; --i)
-				players.append(packet.readString());
+				players.push_back(packet.readString());
 
 			m_interface->setPlayerNames(players);
 		}
@@ -306,7 +319,7 @@
 
 // -------------------------------------------------------------------------------------------------
 //
-UDPSocket* RCONSession::getSocket()
+net::UDPSocket* RCONSession::getSocket()
 {
 	return &m_socket;
 }
@@ -315,7 +328,7 @@
 //
 void RCONSession::sendHello()
 {
-	m_interface->print("Connecting to %s...\n", m_address.to_string(IPAddress::WITH_PORT).chars());
+	m_interface->print("Connecting to %s...\n", net::ip_address_to_string(m_address).data());
 	send({CLRC_BEGINCONNECTION, RCON_PROTOCOL_VERSION});
 	bumpLastPing();
 }
@@ -325,17 +338,17 @@
 void RCONSession::sendPassword()
 {
 	m_interface->print("Authenticating...\n");
-	ByteArray message;
+	std::vector<unsigned char> message;
 	Bytestream stream(message);
 	stream.writeByte(CLRC_PASSWORD);
-	stream.writeString((m_salt + m_password).md5());
+	stream.writeString(md5((m_salt + m_password).data()));
 	send(message);
 	bumpLastPing();
 }
 
 // -------------------------------------------------------------------------------------------------
 //
-void RCONSession::setPassword(const String& password)
+void RCONSession::setPassword(const std::string& password)
 {
 	m_password = password;
 }
@@ -359,12 +372,12 @@
 // -------------------------------------------------------------------------------------------------
 // Returns true if the message was successfully sent.
 //
-bool RCONSession::sendCommand(const String& commandString)
+bool RCONSession::sendCommand(const std::string& commandString)
 {
-	if (m_state != RCON_CONNECTED or commandString.isEmpty())
+	if (m_state != RCON_CONNECTED or commandString.empty())
 		return false;
 
-	ByteArray message;
+	std::vector<unsigned char> message;
 	Bytestream stream(message);
 	stream.writeByte(CLRC_COMMAND);
 	stream.writeString(commandString);
@@ -382,7 +395,7 @@
 
 // -------------------------------------------------------------------------------------------------
 //
-const IPAddress& RCONSession::address() const
+const net::ip_address& RCONSession::address() const
 {
 	return m_address;
 }
@@ -396,18 +409,18 @@
 
 // -------------------------------------------------------------------------------------------------
 //
-const String& RCONSession::getLevel() const
+const std::string& RCONSession::getLevel() const
 {
 	return m_level;
 }
 
 // -------------------------------------------------------------------------------------------------
 //
-void RCONSession::requestTabCompletion(const String& part)
+void RCONSession::requestTabCompletion(const std::string& part)
 {
 	if (m_serverProtocol >= 4)
 	{
-		ByteArray message;
+		std::vector<unsigned char> message;
 		Bytestream stream(message);
 		stream.writeByte(CLRC_TABCOMPLETE);
 		stream.writeString(part);
@@ -417,7 +430,7 @@
 	}
 	else
 	{
-		m_interface->print("This server does not support tab-completion\n", m_serverProtocol);
+		m_interface->print("This server does not support tab-completion\n");
 	}
 }
 
@@ -432,22 +445,22 @@
 //
 void RCONSession::requestWatch(const String& cvar)
 {
-	StringList cvars;
-	cvars.append(cvar);
+	const std::vector<std::string> cvars{{cvar}};
 	requestWatch(cvars);
 }
 
 // -------------------------------------------------------------------------------------------------
 //
-void RCONSession::requestWatch(const StringList& cvars)
+void RCONSession::requestWatch(const std::vector<std::string>& cvars)
 {
-	ByteArray message;
+	std::vector<unsigned char> message;
 	Bytestream stream(message);
 	stream.writeByte(CLRC_WATCHCVAR);
-
-	for (const String& cvar : cvars)
-		stream.writeString(cvar.normalized());
-
+	for (String cvar : cvars)
+	{
+		normalize(cvar);
+		stream.writeString(cvar);
+	}
 	stream.writeString("");
 	send(message);
 }

mercurial