changeset 16232:643e714689a3 draft

(svn r20933) -Codechange: move some more client related methods and such to network_client.cpp
author rubidium <rubidium@openttd.org>
date Fri, 15 Oct 2010 19:33:08 +0000
parents 121789f99a9a
children d75dbd5a0157
files src/network/core/tcp.cpp src/network/core/tcp.h src/network/network.cpp src/network/network_client.cpp src/network/network_client.h src/network/network_content.cpp src/network/network_internal.h
diffstat 7 files changed, 161 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- a/src/network/core/tcp.cpp
+++ b/src/network/core/tcp.cpp
@@ -214,4 +214,31 @@
 	return this->packet_queue == NULL;
 }
 
+/**
+ * Check whether this socket can send or receive something.
+ * @return \c true when there is something to receive.
+ * @note Sets #writeable if more data can be sent.
+ */
+bool NetworkTCPSocketHandler::CanSendReceive()
+{
+	fd_set read_fd, write_fd;
+	struct timeval tv;
+
+	FD_ZERO(&read_fd);
+	FD_ZERO(&write_fd);
+
+	FD_SET(this->sock, &read_fd);
+	FD_SET(this->sock, &write_fd);
+
+	tv.tv_sec = tv.tv_usec = 0; // don't block at all.
+#if !defined(__MORPHOS__) && !defined(__AMIGA__)
+	select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
+#else
+	WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
+#endif
+
+	this->writable = !!FD_ISSET(this->sock, &write_fd);
+	return FD_ISSET(this->sock, &read_fd);
+}
+
 #endif /* ENABLE_NETWORK */
--- a/src/network/core/tcp.h
+++ b/src/network/core/tcp.h
@@ -41,6 +41,8 @@
 
 	Packet *Recv_Packet();
 
+	bool CanSendReceive();
+
 	NetworkTCPSocketHandler(SOCKET s = INVALID_SOCKET);
 	~NetworkTCPSocketHandler();
 };
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -240,7 +240,7 @@
 
 /* There was a non-recoverable error, drop back to the main menu with a nice
  *  error */
-static void NetworkError(StringID error_string)
+void NetworkError(StringID error_string)
 {
 	_switch_mode = SM_MENU;
 	extern StringID _switch_mode_errorstr;
@@ -253,40 +253,6 @@
 	NetworkError(STR_NETWORK_ERROR_SERVER_START);
 }
 
-static void NetworkClientError(NetworkRecvStatus res, NetworkClientSocket *cs)
-{
-	/* First, send a CLIENT_ERROR to the server, so he knows we are
-	 *  disconnection (and why!) */
-	NetworkErrorCode errorno;
-
-	/* We just want to close the connection.. */
-	if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
-		cs->NetworkSocketHandler::CloseConnection();
-		cs->CloseConnection(res);
-		_networking = false;
-
-		DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-		return;
-	}
-
-	switch (res) {
-		case NETWORK_RECV_STATUS_DESYNC:          errorno = NETWORK_ERROR_DESYNC; break;
-		case NETWORK_RECV_STATUS_SAVEGAME:        errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
-		case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
-		default:                                  errorno = NETWORK_ERROR_GENERAL; break;
-	}
-
-	/* This means we fucked up and the server closed the connection */
-	if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
-			res != NETWORK_RECV_STATUS_SERVER_BANNED) {
-		MyClient::SendError(errorno);
-	}
-
-	_switch_mode = SM_MENU;
-	cs->CloseConnection(res);
-	_networking = false;
-}
-
 /**
  * Retrieve the string id of an internal error number
  * @param err NetworkErrorCode
@@ -838,6 +804,9 @@
  */
 static bool NetworkReceive()
 {
+	if (!_network_server) {
+		return ClientNetworkGameSocketHandler::Receive();
+	}
 	NetworkClientSocket *cs;
 	fd_set read_fd, write_fd;
 	struct timeval tv;
@@ -872,22 +841,7 @@
 	FOR_ALL_CLIENT_SOCKETS(cs) {
 		cs->writable = !!FD_ISSET(cs->sock, &write_fd);
 		if (FD_ISSET(cs->sock, &read_fd)) {
-			if (_network_server) {
-				cs->Recv_Packets();
-			} else {
-				NetworkRecvStatus res;
-
-				/* The client already was quiting! */
-				if (cs->HasClientQuit()) return false;
-
-				res = cs->Recv_Packets();
-				if (res != NETWORK_RECV_STATUS_OKAY) {
-					/* The client made an error of which we can not recover
-					 *   close the client and drop back to main menu */
-					NetworkClientError(res, cs);
-					return false;
-				}
-			}
+			cs->Recv_Packets();
 		}
 	}
 	return _networking;
@@ -896,6 +850,11 @@
 /* This sends all buffered commands (if possible) */
 static void NetworkSend()
 {
+	if (!_network_server) {
+		ClientNetworkGameSocketHandler::Send();
+		return;
+	}
+
 	NetworkClientSocket *cs;
 	FOR_ALL_CLIENT_SOCKETS(cs) {
 		if (cs->writable) {
@@ -909,47 +868,6 @@
 	}
 }
 
-static bool NetworkDoClientLoop()
-{
-	_frame_counter++;
-
-	NetworkExecuteLocalCommandQueue();
-
-	StateGameLoop();
-
-	/* Check if we are in sync! */
-	if (_sync_frame != 0) {
-		if (_sync_frame == _frame_counter) {
-#ifdef NETWORK_SEND_DOUBLE_SEED
-			if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
-#else
-			if (_sync_seed_1 != _random.state[0]) {
-#endif
-				NetworkError(STR_NETWORK_ERROR_DESYNC);
-				DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract);
-				DEBUG(net, 0, "Sync error detected!");
-				NetworkClientError(NETWORK_RECV_STATUS_DESYNC, NetworkClientSocket::Get(0));
-				return false;
-			}
-
-			/* If this is the first time we have a sync-frame, we
-			 *   need to let the server know that we are ready and at the same
-			 *   frame as he is.. so we can start playing! */
-			if (_network_first_time) {
-				_network_first_time = false;
-				MyClient::SendAck();
-			}
-
-			_sync_frame = 0;
-		} else if (_sync_frame < _frame_counter) {
-			DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
-			_sync_frame = 0;
-		}
-	}
-
-	return true;
-}
-
 /* We have to do some UDP checking */
 void NetworkUDPGameLoop()
 {
@@ -1107,11 +1025,11 @@
 		/* Make sure we are at the frame were the server is (quick-frames) */
 		if (_frame_counter_server > _frame_counter) {
 			while (_frame_counter_server > _frame_counter) {
-				if (!NetworkDoClientLoop()) break;
+				if (!ClientNetworkGameSocketHandler::GameLoop()) break;
 			}
 		} else {
 			/* Else, keep on going till _frame_counter_max */
-			if (_frame_counter_max > _frame_counter) NetworkDoClientLoop();
+			if (_frame_counter_max > _frame_counter) ClientNetworkGameSocketHandler::GameLoop();
 		}
 	}
 
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -25,6 +25,8 @@
 #include "../company_func.h"
 #include "../company_base.h"
 #include "../company_gui.h"
+#include "../core/random_func.hpp"
+#include "../date_func.h"
 #include "../rev.h"
 #include "network.h"
 #include "network_base.h"
@@ -73,6 +75,117 @@
 	return status;
 }
 
+/**
+ * Handle an error coming from the client side.
+ * @param res The "error" that happened.
+ */
+void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
+{
+	/* First, send a CLIENT_ERROR to the server, so he knows we are
+	 *  disconnection (and why!) */
+	NetworkErrorCode errorno;
+
+	/* We just want to close the connection.. */
+	if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
+		this->NetworkSocketHandler::CloseConnection();
+		this->CloseConnection(res);
+		_networking = false;
+
+		DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
+		return;
+	}
+
+	switch (res) {
+		case NETWORK_RECV_STATUS_DESYNC:          errorno = NETWORK_ERROR_DESYNC; break;
+		case NETWORK_RECV_STATUS_SAVEGAME:        errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
+		case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
+		default:                                  errorno = NETWORK_ERROR_GENERAL; break;
+	}
+
+	/* This means we fucked up and the server closed the connection */
+	if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
+			res != NETWORK_RECV_STATUS_SERVER_BANNED) {
+		SendError(errorno);
+	}
+
+	_switch_mode = SM_MENU;
+	this->CloseConnection(res);
+	_networking = false;
+}
+
+
+/**
+ * Check whether we received/can send some data from/to the server and
+ * when that's the case handle it appropriately.
+ * @return true when everything went okay.
+ */
+/*static */ bool ClientNetworkGameSocketHandler::Receive()
+{
+	if (my_client->CanSendReceive()) {
+		NetworkRecvStatus res = my_client->Recv_Packets();
+		if (res != NETWORK_RECV_STATUS_OKAY) {
+			/* The client made an error of which we can not recover
+				*   close the client and drop back to main menu */
+			my_client->ClientError(res);
+			return false;
+		}
+	}
+	return _networking;
+}
+
+/** Send the packets of this socket handler. */
+/*static */ void ClientNetworkGameSocketHandler::Send()
+{
+	my_client->Send_Packets();
+}
+
+/**
+ * Actual game loop for the client.
+ * @return Whether everything went okay, or not.
+ */
+/* static */ bool ClientNetworkGameSocketHandler::GameLoop()
+{
+	_frame_counter++;
+
+	NetworkExecuteLocalCommandQueue();
+
+	extern void StateGameLoop();
+	StateGameLoop();
+
+	/* Check if we are in sync! */
+	if (_sync_frame != 0) {
+		if (_sync_frame == _frame_counter) {
+#ifdef NETWORK_SEND_DOUBLE_SEED
+			if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
+#else
+			if (_sync_seed_1 != _random.state[0]) {
+#endif
+				NetworkError(STR_NETWORK_ERROR_DESYNC);
+				DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract);
+				DEBUG(net, 0, "Sync error detected!");
+				my_client->ClientError(NETWORK_RECV_STATUS_DESYNC);
+				return false;
+			}
+
+			/* If this is the first time we have a sync-frame, we
+			 *   need to let the server know that we are ready and at the same
+			 *   frame as he is.. so we can start playing! */
+			if (_network_first_time) {
+				_network_first_time = false;
+				SendAck();
+			}
+
+			_sync_frame = 0;
+		} else if (_sync_frame < _frame_counter) {
+			DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
+			_sync_frame = 0;
+		}
+	}
+
+	return true;
+}
+
+
 /** Our client's connection. */
 ClientNetworkGameSocketHandler * ClientNetworkGameSocketHandler::my_client = NULL;
 
--- a/src/network/network_client.h
+++ b/src/network/network_client.h
@@ -54,6 +54,7 @@
 	~ClientNetworkGameSocketHandler();
 
 	NetworkRecvStatus CloseConnection(NetworkRecvStatus status);
+	void ClientError(NetworkRecvStatus res);
 
 	static NetworkRecvStatus SendCompanyInformationQuery();
 
@@ -71,6 +72,10 @@
 	static NetworkRecvStatus SendSetName(const char *name);
 	static NetworkRecvStatus SendRCon(const char *password, const char *command);
 	static NetworkRecvStatus SendMove(CompanyID company, const char *password);
+
+	static void Send();
+	static bool Receive();
+	static bool GameLoop();
 };
 
 typedef ClientNetworkGameSocketHandler MyClient;
--- a/src/network/network_content.cpp
+++ b/src/network/network_content.cpp
@@ -737,27 +737,11 @@
 		return;
 	}
 
-	fd_set read_fd, write_fd;
-	struct timeval tv;
-
-	FD_ZERO(&read_fd);
-	FD_ZERO(&write_fd);
-
-	FD_SET(this->sock, &read_fd);
-	FD_SET(this->sock, &write_fd);
-
-	tv.tv_sec = tv.tv_usec = 0; // don't block at all.
-#if !defined(__MORPHOS__) && !defined(__AMIGA__)
-	select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
-#else
-	WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
-#endif
-	if (FD_ISSET(this->sock, &read_fd)) {
+	if (this->CanSendReceive()) {
 		this->Recv_Packets();
 		this->lastActivity = _realtime_tick;
 	}
 
-	this->writable = !!FD_ISSET(this->sock, &write_fd);
 	this->Send_Packets();
 }
 
--- a/src/network/network_internal.h
+++ b/src/network/network_internal.h
@@ -166,6 +166,7 @@
 void NetworkSyncCommandQueue(NetworkClientSocket *cs);
 
 /* from network.c */
+void NetworkError(StringID error_string);
 void NetworkTextMessage(NetworkAction action, ConsoleColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0);
 void NetworkGetClientName(char *clientname, size_t size, const NetworkClientSocket *cs);
 uint NetworkCalculateLag(const NetworkClientSocket *cs);