From 48216daa641008e0de21c5522d6e958a38b02093 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Wed, 18 Jan 2012 23:48:36 +0800 Subject: [PATCH] Began implementation of networking Slightly confused about the client/server thing Server is going to run red Client is going to run blue Need to get them to talk nicely? Doesn't work at the moment - server can't bind socket, client segfaults (NULL pointer). Blergh. --- judge/manager/Makefile | 4 +- judge/manager/game.cpp | 31 ++++++-- judge/manager/game.h | 3 +- judge/manager/main.cpp | 44 +++++++++++- judge/manager/network_controller.cpp | 102 +++++++++++++++++++++++++++ judge/manager/network_controller.h | 53 ++++++++++++++ 6 files changed, 226 insertions(+), 11 deletions(-) create mode 100644 judge/manager/network_controller.cpp create mode 100644 judge/manager/network_controller.h diff --git a/judge/manager/Makefile b/judge/manager/Makefile index 6a35950..199a3af 100644 --- a/judge/manager/Makefile +++ b/judge/manager/Makefile @@ -4,8 +4,10 @@ #LIBRARIES = -lSDL -lGL -lpthread #Use this to build without graphics LIBRARIES = -lpthread +#Use this on Mac OSX (Thanks spartan) +#LIBRARIES = -I/opt/local/include/ -L/opt/local/lib/ -lSDL -framework OpenGL -lpthread CPP = g++ -Wall -pedantic -g -OBJ = main.o controller.o ai_controller.o human_controller.o program.o thread_util.o stratego.o graphics.o game.o +OBJ = main.o controller.o network_controller.o ai_controller.o human_controller.o program.o thread_util.o stratego.o graphics.o game.o BIN = stratego diff --git a/judge/manager/game.cpp b/judge/manager/game.cpp index 8d3eef0..92dc71a 100644 --- a/judge/manager/game.cpp +++ b/judge/manager/game.cpp @@ -7,7 +7,7 @@ using namespace std; Game* Game::theGame = NULL; bool Game::gameCreated = false; -Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime) +Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime, bool server, bool client) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime) { gameCreated = false; if (gameCreated) @@ -25,16 +25,33 @@ Game::Game(const char * redPath, const char * bluePath, const bool enableGraphic Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32); #endif //BUILD_GRAPHICS - if (strcmp(redPath, "human") == 0) - red = new Human_Controller(Piece::RED, graphicsEnabled); + + if (client) + { + red = new Client(Piece::RED, "server", redPath); //TODO: Retrieve server address + } else - red = new AI_Controller(Piece::RED, redPath, timeoutTime); + { + assert(redPath != NULL); + if (strcmp(redPath, "human") == 0) + red = new Human_Controller(Piece::RED, graphicsEnabled); + else + red = new AI_Controller(Piece::RED, redPath, timeoutTime); + } - if (strcmp(bluePath, "human") == 0) - blue = new Human_Controller(Piece::BLUE, graphicsEnabled); + if (server) + { + blue = new Server(Piece::BLUE, "client"); + } else - blue = new AI_Controller(Piece::BLUE, bluePath, timeoutTime); + { + assert(bluePath != NULL); + if (strcmp(bluePath, "human") == 0) + blue = new Human_Controller(Piece::BLUE, graphicsEnabled); + else + blue = new AI_Controller(Piece::BLUE, bluePath, timeoutTime); + } } diff --git a/judge/manager/game.h b/judge/manager/game.h index 2ed35f6..cc79e65 100644 --- a/judge/manager/game.h +++ b/judge/manager/game.h @@ -4,6 +4,7 @@ #include "stratego.h" #include "ai_controller.h" #include "human_controller.h" +#include "network_controller.h" #include @@ -14,7 +15,7 @@ class Game { public: - Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false, double newTimeoutTime = 2.0); + Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false, double newTimeoutTime = 2.0, bool server=false, bool client=false); Game(const char * fromFile, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false, double newTimeoutTime = 2.0); virtual ~Game(); diff --git a/judge/manager/main.cpp b/judge/manager/main.cpp index ce4cd20..83b3c63 100644 --- a/judge/manager/main.cpp +++ b/judge/manager/main.cpp @@ -64,6 +64,7 @@ Piece::Colour SetupGame(int argc, char ** argv) { char * red = NULL; char * blue = NULL; double stallTime = 0.0; bool graphics = false; bool allowIllegal = false; FILE * log = NULL; Piece::Colour reveal = Piece::BOTH; char * inputFile = NULL; int maxTurns = 5000; bool printBoard = false; double timeoutTime = 2.0; + bool server = false; bool client = false; for (int ii=1; ii < argc; ++ii) { if (argv[ii][0] == '-') @@ -184,6 +185,26 @@ Piece::Colour SetupGame(int argc, char ** argv) system("less manual.txt"); exit(EXIT_SUCCESS); } + else if (strcmp(argv[ii]+2, "server") == 0) + { + if (client == true) + { + fprintf(stderr, "ARGUMENT_ERROR - Can't be both a server and a client!\n"); + exit(EXIT_FAILURE); + } + server = true; + + } + else if (strcmp(argv[ii]+2, "client") == 0) + { + if (server == true) + { + fprintf(stderr, "ARGUMENT_ERROR - Can't be both a server and a client!\n"); + exit(EXIT_FAILURE); + } + client = true; + + } else { fprintf(stderr, "ARGUMENT_ERROR - Unrecognised switch \"%s\"...\n", argv[ii]); @@ -211,15 +232,34 @@ Piece::Colour SetupGame(int argc, char ** argv) if (inputFile == NULL) { - if (red == NULL || blue == NULL) //Not enough arguments + if (server) + { + if (red != NULL && blue != NULL) + { + fprintf(stderr, "ARGUMENT_ERROR - When using the --server switch, only supply ONE (1) player.\n"); + exit(EXIT_FAILURE); + } + } + else if (red == NULL || blue == NULL) //Not enough players { fprintf(stderr, "ARGUMENT_ERROR - Did not recieve enough players (did you mean to use the -f switch?)\n"); exit(EXIT_FAILURE); } - Game::theGame = new Game(red,blue, graphics, stallTime, allowIllegal,log, reveal,maxTurns, printBoard, timeoutTime); + + if (client) + { + blue = red; red = NULL; + } + + Game::theGame = new Game(red,blue, graphics, stallTime, allowIllegal,log, reveal,maxTurns, printBoard, timeoutTime, server, client); } else { + if (server || client) + { + fprintf(stderr, "ARGUMENT_ERROR - The -f switch is incompatable with the --server or --client switches!\n"); + exit(EXIT_FAILURE); + } Game::theGame = new Game(inputFile, graphics, stallTime, allowIllegal,log, reveal,maxTurns, printBoard, timeoutTime); } diff --git a/judge/manager/network_controller.cpp b/judge/manager/network_controller.cpp new file mode 100644 index 0000000..aed27b7 --- /dev/null +++ b/judge/manager/network_controller.cpp @@ -0,0 +1,102 @@ +#include "network_controller.h" + +NetworkController::NetworkController(const Piece::Colour & newColour, const char * newName) : Controller(newColour, newName), sfd(-1) +{ + struct protoent * tcp = getprotobyname("tcp"); + + sfd = socket(PF_INET, SOCK_STREAM, tcp->p_proto); + if (sfd == -1) + { + fprintf(stderr, "NetworkController::NetworkController - couldn't create a TCP socket!"); + return; + } +} + +NetworkController::~NetworkController() +{ + if (Valid()) + { + if (shutdown(sfd, SHUT_RDWR) == -1) + { + fprintf(stderr, "NetworkController::~NetworkController - Can't shutdown socket %d!", sfd); + close(sfd); + sfd = -1; + } + } + close(sfd); +} + +Server::Server(const Piece::Colour & newColour, const char * newName) : NetworkController(newColour, newName) +{ + struct sockaddr_in ipa; + ipa.sin_family = AF_INET; + ipa.sin_port = htons(NetworkController::port); + ipa.sin_addr.s_addr = INADDR_ANY; + memset(&ipa,0, sizeof ipa); + + if (bind(sfd, (struct sockaddr*)&sfd, sizeof sfd) == -1) + { + fprintf(stderr, "Server::Server - Couldn't bind to socket! Abort\n"); + close(sfd); + sfd = -1; + return; + } + + //Listen for at most 1 connection + if (listen(sfd, 1) == -1) + { + fprintf(stderr, "Server::Server - listening failed.\n"); + close(sfd); + sfd = -1; + return; + } + + //Accept the connection + sfd = accept(sfd, NULL, NULL); + if (sfd < 0) + { + fprintf(stderr, "Server::Server - couldn't accept connection.\n"); + close(sfd); + sfd = -1; + return; + } + + //We are now ready to play! +} + + +Client::Client(const Piece::Colour & newColour, const char * newName, const char * server) : NetworkController(newColour, newName) +{ + struct sockaddr_in ipa; + ipa.sin_family = AF_INET; + ipa.sin_port = htons(NetworkController::port); + int Res = inet_pton(AF_INET, server, &ipa.sin_addr); + + if (Res < 0) + { + fprintf(stderr, "Client::Client - First parameter is not a valid address family!\n"); + close(sfd); + sfd = -1; + return; + } + else if (Res == 0) + { + fprintf(stderr, "Client::Client - Second parameter does not contain a valid IP Address!\n"); + close(sfd); + sfd = -1; + return; + } + + if (connect(sfd, (struct sockaddr*)&sfd, sizeof sfd) == -1) + { + fprintf(stderr, "Client::Client - Connection to server at \"%s\" failed.\n", server); + close(sfd); + sfd = -1; + return; + } + + //We are now ready to play! +} +//EOF + + diff --git a/judge/manager/network_controller.h b/judge/manager/network_controller.h new file mode 100644 index 0000000..cf80a80 --- /dev/null +++ b/judge/manager/network_controller.h @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#include "controller.h" + +#ifndef NETWORK_CONTROLLER_H +#define NETWORK_CONTROLLER_H + + +class NetworkController : public Controller +{ + public: + NetworkController(const Piece::Colour & newColour, const char * newName = "no-name"); + virtual ~NetworkController(); + + virtual bool Valid() {return sfd != -1;} + + virtual void Message(const char * string) {fprintf(stderr, "NetworkController unimplemented!\n"); assert(false);} + virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]) {fprintf(stderr, "NetworkController unimplemented!\n"); assert(false);} + virtual MovementResult QueryMove(std::string & buffer) {fprintf(stderr, "NetworkController unimplemented!\n"); assert(false);} + + protected: + int sfd; int cfd; + static const int port = 666; +}; + +class Server : public NetworkController +{ + public: + Server(const Piece::Colour & newColour, const char * newName = "no-name"); + virtual ~Server() {} +}; + +class Client : public NetworkController +{ + public: + Client(const Piece::Colour & newColour, const char * newName = "no-name", const char * server="127.0.0.1"); + virtual ~Client() {} +}; + +#endif //NETWORK_CONTROLLER_H + +//EOF -- 2.20.1