change proto2 network code to use CL_NetSession
authorterom
Sat, 08 Nov 2008 18:02:58 +0000
changeset 21 32c6cc55256a
parent 20 f6dc5967c49c
child 22 b70d30e1b0fe
change proto2 network code to use CL_NetSession
src/proto2/Application.cc
src/proto2/Engine.cc
src/proto2/Engine.hh
src/proto2/Network.hh
src/proto2/NetworkClient.cc
src/proto2/NetworkClient.hh
src/proto2/NetworkConfig.hh
src/proto2/NetworkServer.cc
src/proto2/NetworkServer.hh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Application.cc	Sat Nov 08 18:02:58 2008 +0000
@@ -0,0 +1,115 @@
+
+#include "Engine.hh"
+
+#include <stdexcept>
+#include <cassert>
+
+#include <ClanLib/core.h>
+#include <ClanLib/application.h>
+
+class ArgumentError : public std::exception {
+	private:
+		const char *message;
+	
+	public:
+		ArgumentError (const std::string &message) : message(message.c_str()) { }
+
+		virtual const char* what() const throw() {
+			return message;
+		}
+};
+
+class Main : public CL_ClanApplication {
+	private:
+		// arguments
+		CL_CommandLine args;
+
+		std::string arg_port;
+		bool arg_dedicated;
+		std::string arg_connect;
+
+		void parse_args (int argc, char **argv) {
+			// set up the options
+			args.add_option('p', "port", "PORT", "set network port used", true);
+			args.add_option('D', "dedicated", "", "act as a network server", true);
+			args.add_option('c', "connect", "SERVERHOST", "act as a network client", true);
+
+			// set defaults
+			arg_port = NETWORK_PORT_STR;
+			arg_dedicated = false;
+			arg_connect = "";
+			
+			try {
+				// parse args
+				args.parse_args(argc, argv);
+			} catch (CL_Error &e) {
+				throw ArgumentError(e.message);
+			}
+
+			while (args.next()) {
+				switch (args.get_key()) {
+					case 'p':
+						arg_port = args.get_argument();
+						break;
+
+					case 'D':
+						arg_dedicated = true;
+						break;
+
+					case 'c':
+						arg_connect = args.get_argument();
+						break;
+
+					case CL_CommandLine::REST_ARG:
+						throw ArgumentError(args.get_argument());
+
+					default:
+						throw ArgumentError(std::string(1, (char) args.get_key()));
+
+				}
+			}
+			
+			// check for valid combinations of arugments
+			if (arg_dedicated && !arg_connect.empty())
+				throw ArgumentError("-D and -c are mutually exclusive");
+			
+			if (!arg_dedicated && arg_connect.empty())
+				throw ArgumentError("nothing to do");
+		}
+
+	public:
+		virtual int main (int argc, char **argv) {
+			// initialize core
+			CL_SetupCore setup_core;
+			
+			try {
+				// parse arugments
+				parse_args(argc, argv);
+				
+				// run engine based on args
+				if (arg_dedicated) {
+					Engine::runNetworkServer(arg_port);
+
+				} else if (!arg_connect.empty()) {
+					Engine::runNetworkClient(arg_connect, arg_port);
+				
+				} else
+					assert(false);
+				
+				// succesful return
+				return 0;
+			
+			} catch (ArgumentError &e) {
+				std::cerr << e.what() << std::endl;
+				args.print_help();
+
+				// XXX: handle --help
+
+			} catch (std::exception &e) {
+				std::cerr << e.what() << std::endl;
+
+				return 1;
+			}
+		}
+} app;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Engine.cc	Sat Nov 08 18:02:58 2008 +0000
@@ -0,0 +1,68 @@
+
+#include "Engine.hh"
+#include "GameState.hh"
+#include "NetworkServer.hh"
+#include "NetworkClient.hh"
+
+Engine::Engine (void) : is_running(true) {
+
+}
+
+void Engine::runNetworkServer (const std::string &listen_port) {
+	// the engine
+	Engine engine;
+	
+	// setup network
+	CL_SetupNetwork setup_network;
+
+	try {
+		// create the server
+		engine.net_server = new NetworkServer(engine.game_state, listen_port);
+
+		// run the main loop
+		engine.main_loop();
+	
+	} catch (CL_Error &e) {
+		std::cerr << "NetworkServer::main: CL_Error:" << e.message << std::endl;
+
+		throw;
+	}
+}
+
+void Engine::runNetworkClient (const std::string &connect_host, const std::string &connect_port) {
+	// the engine
+	Engine engine;
+	
+	// setup network
+	CL_SetupNetwork setup_network;
+
+	// connect_to
+	CL_IPAddress connect_addr(connect_host, connect_port);
+
+	try {
+		// create the server
+		engine.net_client = new NetworkClient(engine.game_state, connect_addr);
+
+		// run the main loop
+		engine.main_loop();
+	
+	} catch (CL_Error &e) {
+		std::cerr << "NetworkServer::main: CL_Error:" << e.message << std::endl;
+
+		throw;
+	}
+
+}
+
+void Engine::main_loop (void) {
+	while (is_running) {
+		// this does.... magical things
+		CL_System::keep_alive();
+
+		// if I can't find some better way to do this in ClanLib by next thursday, then it f*%!ing sucks
+		// ideally, we should be able to have a main loop that does timed waits on I/O, fufilling some set of timers
+		// but as far as I can tell, ClanLib doesn't have anything like that
+		CL_System::sleep(100);
+
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/Engine.hh	Sat Nov 08 18:02:58 2008 +0000
@@ -0,0 +1,27 @@
+
+#include "NetworkServer.hh"
+#include "NetworkClient.hh"
+
+class Engine {
+	private:
+		// game state
+		GameState game_state;
+		
+		// network server/client
+		NetworkServer *net_server;
+		NetworkClient *net_client;
+
+		// to exit the mainloop
+		bool is_running;
+		
+		// default constructor
+		Engine (void);
+
+	public:
+		static void runNetworkServer (const std::string &listen_port);
+		static void runNetworkClient (const std::string &connect_host, const std::string &connect_port);
+	
+	private:
+		void main_loop (void);
+
+};
--- a/src/proto2/Network.hh	Fri Nov 07 21:40:32 2008 +0000
+++ b/src/proto2/Network.hh	Sat Nov 08 18:02:58 2008 +0000
@@ -1,25 +1,21 @@
 #ifndef NETWORK_HH
 #define NETWORK_HH
 
+#include "NetworkConfig.hh"
+#include "GameState.hh"
+
 #include <ClanLib/network.h>
 
-#include "NetworkConfig.hh"
-
-class NetworkBase {
+class NetworkCore {
 	protected:
-		CL_Socket socket;
+		GameState &state;
 
-		NetworkBase () : 
-				socket(CL_Socket::udp)
-		{
-				socket.set_nonblocking(true);
-		}
+		CL_SlotContainer slots;
 
-		NetworkBase (CL_Socket socket) :
-				socket(socket)
-		{
-				socket.set_nonblocking(true);
-		}
+		CL_NetSession netsession;
+		
+		// constructor
+		NetworkCore (GameState &state) : state(state), netsession(NETWORK_APP_NAME) { }
 };
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto2/NetworkClient.cc	Sat Nov 08 18:02:58 2008 +0000
@@ -0,0 +1,9 @@
+
+#include "NetworkClient.hh"
+
+
+NetworkClient::NetworkClient (GameState &state, const CL_IPAddress &connect_to) : 
+	NetworkCore(state), server(netsession.connect(connect_to)) {
+	
+	// connect slots
+}
--- a/src/proto2/NetworkClient.hh	Fri Nov 07 21:40:32 2008 +0000
+++ b/src/proto2/NetworkClient.hh	Sat Nov 08 18:02:58 2008 +0000
@@ -1,12 +1,15 @@
 #ifndef NETWORKCLIENT_HH
 #define NETWORKCLIENT_HH
 
-class NetworkClient {
+#include "Network.hh"
+#include "GameState.hh"
+
+class NetworkClient : public NetworkCore {
 	private:
-		GameState *state;
-	
+		CL_NetComputer server;
+
 	public:
-		NetworkClient (GameState *state);
+		NetworkClient (GameState &state, const CL_IPAddress &connect_to);
 };
 
 #endif
--- a/src/proto2/NetworkConfig.hh	Fri Nov 07 21:40:32 2008 +0000
+++ b/src/proto2/NetworkConfig.hh	Sat Nov 08 18:02:58 2008 +0000
@@ -1,6 +1,8 @@
 #ifndef NETWORK_CONFIG_HH
 #define NETWORK_CONFIG_HH
 
+// socket-related includes
+// copied from clanlib code, so should be relatively OS-safe
 #ifndef WIN32
         #include <sys/socket.h>
         #include <netinet/in.h>
@@ -14,6 +16,9 @@
         typedef int socklen_t;
 #endif
 
+#include <string>
+
+const std::string NETWORK_APP_NAME = "KisnaGlista";
 const std::string NETWORK_PORT_STR = "9338";
 const uint16_t NETWORK_PACKET_MAX = 1280;
 
--- a/src/proto2/NetworkServer.cc	Fri Nov 07 21:40:32 2008 +0000
+++ b/src/proto2/NetworkServer.cc	Sat Nov 08 18:02:58 2008 +0000
@@ -4,82 +4,26 @@
 #include <iostream>
 #include <cassert>
 
-NetworkServer::NetworkServer (GameState *state, const CL_IPAddress &listen_ip) : NetworkBase(), state(state) {
-	socket.bind(listen_ip);
+NetworkServer::NetworkServer (GameState &state, const std::string &listen_port) : 
+	NetworkCore(state) {
 	
-	// add socket to listener
-	listener.add_trigger(socket.get_read_trigger());
-
-	// bind slot for recv
-	slot_on_recv = socket.sig_read_triggered().connect(this, &NetworkServer::_onRecv);
+	// connect slots
+	slots.connect(netsession.sig_computer_connected(), this, &NetworkServer::on_connect);
+	slots.connect(netsession.sig_computer_disconnected(), this, &NetworkServer::on_disconnect);
+	
+	// and then we listen
+	netsession.start_listen(listen_port);
 }
 
-NetworkServer *NetworkServer::newServer (void) {
-	GameState *state = new GameState(/* XXX */);
-	CL_IPAddress listen_ip(NETWORK_PORT_STR);
-	
-	return new NetworkServer(state, listen_ip);
-}		
-
-void NetworkServer::run (void) {
-	bool isRunning = true;
-
-	while (isRunning) {
-		/* XXX: all I need to do? */
-		listener.wait();
-		CL_System::keep_alive();
-		listener.reset_all();
-	}
+void NetworkServer::on_connect (CL_NetComputer &computer) {
+	std::cout << "NetworkServer.on_connect: " << computer.get_address().get_address() << std::endl;
 }
 
-void NetworkServer::_onRecv (void) {
-    NetworkPacket pkt;
-
-    pkt.recvFromSocket(socket);
-
-	std::cout << pkt.src.get_address() << ":" << pkt.src.get_port() << " <- ";
-    
-    enum packet_type type = pkt.read_pkt_type();
-
-    switch (type) {
-        case PKT_HELLO: 
-        {
-            pkt_Hello hello(pkt);
-
-            std::cout << "\tPKT_HELLO: " << hello.player_id << std::endl;
-        } break;
-
-        default:
-        {
-            std::cout << "\t???:" << type << std::endl;
-
-        } break;
-    }    
+void NetworkServer::on_disconnect (CL_NetComputer &computer) {
+	std::cout << "NetworkServer.on_disconnect: " << computer.get_address().get_address() << std::endl;
 }
 		
 NetworkServerClient::NetworkServerClient (NetworkServer &server) : server(server) {
 	
 }
-		
-void runNetworkServer (void) {
-	NetworkServer *server = NULL;
-	
-	try {
-		server = NetworkServer::newServer();
-		server->run();
-	} catch (CL_Error &e) {
-		std::cerr << "runNetworkServer: CL_Error: " << e.message << std::endl;
-	}
-}
 
-int main (int argc, char **argv) {
-	// setup ClanLib components
-	CL_SetupCore setup_core;
-	CL_SetupNetwork setup_network;
-	
-	// create the gamestate and run the server
-	runNetworkServer();
-
-	return 0;
-}
-
--- a/src/proto2/NetworkServer.hh	Fri Nov 07 21:40:32 2008 +0000
+++ b/src/proto2/NetworkServer.hh	Sat Nov 08 18:02:58 2008 +0000
@@ -11,25 +11,13 @@
 // forward-declare
 class NetworkServerClient;
 
-class NetworkServer : public NetworkBase {
-	private:
-		GameState *state;
-
-		std::map<CL_IPAddress, NetworkServerClient> client_sockets;
-
-		CL_EventListener listener;
-		
-		CL_Slot slot_on_recv;
-
-		NetworkServer (GameState *state, const CL_IPAddress &listen_ip);
-
+class NetworkServer : public NetworkCore {
 	public:
-		static NetworkServer *newServer (void);
-
-		void run (void);
+		NetworkServer (GameState &state, const std::string &listen_port);
 
 	private:
-		void _onRecv (void);
+		void on_connect (CL_NetComputer &computer);
+		void on_disconnect (CL_NetComputer &computer);
 };
 
 class NetworkServerClient {
@@ -40,6 +28,4 @@
 		NetworkServerClient (NetworkServer &server);
 };
 
-void runNetworkServer (void);
-
 #endif