@ -0,0 +1,70 @@ | |||
#ifndef __BETACORE_CLIENT_HPP__ | |||
#define __BETACORE_CLIENT_HPP__ | |||
#include <string> | |||
#include <iostream> | |||
#include <functional> | |||
#include <sstream> | |||
#include <vector> | |||
#include <thread> | |||
#include <map> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <sys/types.h> | |||
#include <netdb.h> | |||
#include <netinet/in.h> | |||
#include <unistd.h> | |||
#include "common.hpp" | |||
namespace betacore | |||
{ | |||
class Client | |||
{ | |||
private: | |||
bool _online = false; | |||
bool _running = false; | |||
char key = 'Z'; | |||
int _port; | |||
std::string _url; | |||
MODE _mode; | |||
int _client_socket; | |||
std::function<void(SHAPE &S, MODE &M)> _update; | |||
struct sockaddr_in _server_address; | |||
struct hostent *_server; | |||
std::map<std::string, std::string> lookup; | |||
std::vector<std::string> explode(std::string &message); | |||
std::string encode(const SHAPE &shape); | |||
std::string crypt(const std::string &shape); | |||
std::string raw(const SHAPE &shape); | |||
SHAPE parse(const std::string &message); | |||
SHAPE decode(const std::string &message); | |||
/** | |||
* Function for Thread for getting information from server | |||
*/ | |||
void listener(); | |||
/** | |||
* Function for Thread for sending to server | |||
*/ | |||
void sender(); | |||
void start(); | |||
void stop(); | |||
public: | |||
Client( | |||
MODE mode, | |||
int port, | |||
std::string url, | |||
std::function<void(SHAPE &S, MODE &M)> &update); | |||
~Client(); | |||
void kill(); | |||
bool running(); | |||
void send(bool encrypt, SHAPE shape); | |||
}; | |||
} // namespace betacore | |||
#endif |
@ -0,0 +1,91 @@ | |||
#ifndef __BETACORE_COMMON_HPP__ | |||
#define __BETACORE_COMMON_HPP__ | |||
#define BUFFER_LENGTH 1024 | |||
#include <string> | |||
namespace betacore | |||
{ | |||
enum SHAPE | |||
{ | |||
NONE, | |||
TRIANGLE, | |||
CIRCLE, | |||
SQUARE, | |||
PENTAGON, | |||
UNKOWN | |||
}; | |||
enum MODE | |||
{ | |||
ALICE, | |||
BOB, | |||
EVE, | |||
END | |||
}; | |||
class Parser | |||
{ | |||
public: | |||
static std::string mode(MODE &mode) | |||
{ | |||
switch (mode) | |||
{ | |||
case ALICE: | |||
return "ALICE"; | |||
case BOB: | |||
return "BOB"; | |||
case EVE: | |||
return "EVE"; | |||
default: | |||
return "END"; | |||
} | |||
} | |||
static MODE mode(const std::string &mode) | |||
{ | |||
if (mode == "ALICE") | |||
return ALICE; | |||
if (mode == "BOB") | |||
return BOB; | |||
return END; | |||
} | |||
static SHAPE shape(const std::string &shape) | |||
{ | |||
if (shape == "TRIANGLE") | |||
return TRIANGLE; | |||
if (shape == "CIRCLE") | |||
return CIRCLE; | |||
if (shape == "SQUARE") | |||
return SQUARE; | |||
if (shape == "PENTAGON") | |||
return PENTAGON; | |||
return UNKOWN; | |||
} | |||
static std::string shape(const SHAPE &shape) | |||
{ | |||
std::string message; | |||
switch (shape) | |||
{ | |||
case TRIANGLE: | |||
message = "TRIANGLE"; | |||
break; | |||
case CIRCLE: | |||
message = "CIRCLE"; | |||
break; | |||
case SQUARE: | |||
message = "SQUARE"; | |||
break; | |||
case PENTAGON: | |||
message = "PENTAGON"; | |||
break; | |||
default: | |||
message = "UNKOWN"; | |||
break; | |||
} | |||
return message; | |||
} | |||
}; | |||
} // namespace betacore | |||
#endif |
@ -0,0 +1,51 @@ | |||
#ifndef __BETACORE_SERVER_HPP__ | |||
#define __BETACORE_SERVER_HPP__ | |||
#include <vector> | |||
#include <algorithm> | |||
#include <iostream> | |||
#include <sys/types.h> | |||
#include <sys/socket.h> | |||
#include <sys/poll.h> | |||
#include <netinet/in.h> | |||
#include <signal.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <thread> | |||
#include <utility> | |||
#include <functional> | |||
#include "common.hpp" | |||
namespace betacore | |||
{ | |||
class Server | |||
{ | |||
private: | |||
fd_set rset; | |||
bool online = false; | |||
bool server_running= false; | |||
int port; | |||
int server_socket; | |||
std::vector<int> clients; | |||
struct sockaddr_in server_address; | |||
void start(); | |||
void shutdown(); | |||
void listener(); | |||
void read_socket(int client); | |||
void forward_message(int client,char buffer[BUFFER_LENGTH] ); | |||
public: | |||
Server(int port); | |||
void off(); | |||
bool running(); | |||
}; | |||
} // namespace betacore | |||
#endif |
@ -0,0 +1,2 @@ | |||
sudo apt-get install libsdl2-dev | |||
sudo apt-get install freeglut3-dev |
@ -1,14 +1,25 @@ | |||
OUTPUT_DIR= bin | |||
COMPILER = g++ | |||
COMPILER_FLAGS=-w | |||
COMPILER_FLAGS=-w -std=c++11 | |||
SOURCE_DIR = source/ | |||
INCLUDES_DIR =-I includes/ | |||
LINKER_FLAGS =-lSDL2 -lGL -lGLU | |||
LINKER_FLAGS =-lSDL2 -lGL -lGLU -lpthread | |||
LIBRARY_FLAGS= -std=c++11 -c -fPIC -shared | |||
SERVER_LIB=$(OUTPUT_DIR)/server.so | |||
CLIENT_LIB=$(OUTPUT_DIR)/client.so | |||
all: game | driver | |||
all: game | |||
game: $(SOURCE_DIR)game.cpp | make_dir | |||
$(COMPILER) $(INCLUDES_DIR) $(SOURCE_DIR)game.cpp $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OUTPUT_DIR)/game | |||
driver: client_driver | server_driver | |||
client_lib: $(SOURCE_DIR)client.cpp | make_dir | |||
$(COMPILER) $(LIBRARY_FLAGS) $(INCLUDES_DIR) $(SOURCE_DIR)client.cpp -lpqxx -o $(CLIENT_LIB) | |||
client_driver: $(SOURCE_DIR)client_driver.cpp | client_lib | |||
$(COMPILER) $(INCLUDES_DIR) $(CLIENT_LIB) $(SOURCE_DIR)client_driver.cpp $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OUTPUT_DIR)/client.out | |||
game: $(SOURCE_DIR)game.cpp | client_lib | |||
$(COMPILER) $(INCLUDES_DIR) $(SOURCE_DIR)game.cpp $(CLIENT_LIB) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OUTPUT_DIR)/game.out | |||
server_lib: $(SOURCE_DIR)server.cpp | make_dir | |||
$(COMPILER) $(LIBRARY_FLAGS) $(INCLUDES_DIR) $(SOURCE_DIR)server.cpp -lpqxx -o $(SERVER_LIB) | |||
server_driver: $(SOURCE_DIR)server_driver.cpp | server_lib | |||
$(COMPILER) $(INCLUDES_DIR) $(SERVER_LIB) $(SOURCE_DIR)server_driver.cpp $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OUTPUT_DIR)/server.out | |||
make_dir: | |||
mkdir -p $(OUTPUT_DIR) |
@ -1,2 +1,2 @@ | |||
export SDL_VIDEO_X11_VISUALID= | |||
./bin/game | |||
./bin/game.out 1 4444 localhost |
@ -0,0 +1,203 @@ | |||
#include "../includes/client.hpp" | |||
namespace betacore | |||
{ | |||
Client::Client( | |||
MODE mode, | |||
int port, | |||
std::string url, | |||
std::function<void(SHAPE &S, MODE &M)> &update) : _mode(mode), | |||
_port(port), | |||
_url(url), | |||
_update(update) | |||
{ | |||
lookup["TRIANGLE"] = "APPLE"; | |||
lookup["CIRCLE"] = "ORANGE"; | |||
lookup["SQUARE"] = "BANANA"; | |||
lookup["PENTAGON"] = "PINEAPPLE"; | |||
lookup["APPLE"] = "TRIANGLE"; | |||
lookup["ORANGE"] = "CIRCLE"; | |||
lookup["BANANA"] = "SQUARE"; | |||
lookup["PINEAPPLE"] = "PENTAGON"; | |||
this->start(); | |||
} | |||
Client::~Client(){ | |||
this->_running= false; | |||
this->_online=false; | |||
} | |||
void Client::start() | |||
{ | |||
std::cout | |||
<< "Start" | |||
<< "\nConnecting to: " << _url << ":" << _port | |||
<< std::endl; | |||
//Create a socket point | |||
this->_client_socket = socket(AF_INET, SOCK_STREAM, 0); | |||
_server = gethostbyname(_url.c_str()); | |||
if (_client_socket < 0) | |||
{ | |||
std::cout << "ERROR opening socket" << std::endl; | |||
return; | |||
} | |||
std::cout | |||
<< "Socket Open" | |||
<< std::endl; | |||
bzero((char *)&_server_address, sizeof(_server_address)); | |||
_server_address.sin_family = AF_INET; | |||
bcopy( | |||
(char *)_server->h_addr, | |||
(char *)&_server_address.sin_addr.s_addr, | |||
_server->h_length); | |||
_server_address.sin_port = htons(_port); | |||
// Now connect to the server | |||
if (connect( | |||
_client_socket, | |||
(struct sockaddr *)&_server_address, | |||
sizeof(_server_address)) < 0) | |||
{ | |||
std::cout << "ERROR connecting" << std::endl; | |||
return; | |||
} | |||
this->_online = true; | |||
this->_running = true; | |||
std::thread listen_thread([this] { this->listener(); }); | |||
listen_thread.detach(); | |||
std::cout | |||
<< "Client Connected" | |||
<< std::endl; | |||
} | |||
void Client::stop() | |||
{ | |||
std::cout | |||
<< "Stop" | |||
<< std::endl; | |||
} | |||
void Client::kill() | |||
{ | |||
std::cout | |||
<< "Kill" | |||
<< std::endl; | |||
this->_online = false; | |||
} | |||
bool Client::running() | |||
{ | |||
return this->_running; | |||
} | |||
std::vector<std::string> Client::explode(std::string &message){ | |||
std::stringstream stream(message); | |||
std::string tmp; | |||
std::vector<std::string> words; | |||
while (std::getline(stream, tmp, ':')) | |||
words.push_back(tmp); | |||
return words; | |||
} | |||
SHAPE Client::parse(const std::string &message) | |||
{ | |||
SHAPE result = decode(message); | |||
if (result != UNKOWN) | |||
return result; | |||
if (_mode == EVE) | |||
return UNKOWN; | |||
return decode(crypt(message)); | |||
} | |||
SHAPE Client::decode(const std::string &shape) | |||
{ | |||
if (shape == "TRIANGLE") | |||
return TRIANGLE; | |||
if (shape == "CIRCLE") | |||
return CIRCLE; | |||
if (shape == "SQUARE") | |||
return SQUARE; | |||
if (shape == "PENTAGON") | |||
return PENTAGON; | |||
return UNKOWN; | |||
} | |||
std::string Client::crypt(const std::string &message) | |||
{ | |||
// std::string output = std::string(message); | |||
// for (int i = 0; i < message.size(); i++) | |||
// output.at(i) = message[i] ^ key; | |||
std::cout << "Crypt::" << message << " : " << lookup[message] << std::endl; | |||
return lookup[message]; | |||
} | |||
std::string Client::encode(const SHAPE &shape) | |||
{ | |||
std::string message; | |||
switch (shape) | |||
{ | |||
case TRIANGLE: | |||
message = "TRIANGLE"; | |||
break; | |||
case CIRCLE: | |||
message = "CIRCLE"; | |||
break; | |||
case SQUARE: | |||
message = "SQUARE"; | |||
break; | |||
case PENTAGON: | |||
message = "PENTAGON"; | |||
break; | |||
default: | |||
message = "UNKOWN"; | |||
break; | |||
} | |||
return message; | |||
} | |||
void Client::send(bool encrypt, SHAPE shape) | |||
{ | |||
std::string message = "SHAPE:"; | |||
message += encrypt ? crypt(encode(shape)) : encode(shape); | |||
message += ":"; | |||
message += Parser::mode(this->_mode); | |||
std::cout << "Sending Message: " << message << "\n" | |||
<< std::endl; | |||
char buffer[BUFFER_LENGTH]; | |||
bzero(buffer, BUFFER_LENGTH); | |||
strcpy(buffer, message.c_str()); | |||
buffer[BUFFER_LENGTH - 1] = '\0'; | |||
int x = write(this->_client_socket, buffer, strlen(buffer)); | |||
if (x < 0) | |||
{ | |||
std::cout << "Failed send to server" << std::endl; | |||
} | |||
} | |||
void Client::listener() | |||
{ | |||
std::cout << "listener" << std::endl; | |||
char buffer[BUFFER_LENGTH]; | |||
while (_online) | |||
{ | |||
// Now read server response | |||
bzero(buffer, BUFFER_LENGTH); | |||
std::cout << "Wating For message" << std::endl; | |||
if (read(_client_socket, buffer, BUFFER_LENGTH - 1) < 0) | |||
{ | |||
std::cout << "ERROR reading from socket" << std::endl; | |||
} | |||
std::string message(buffer); | |||
std::cout << "Got Message: " << message << std::endl; | |||
auto parts = explode(message); | |||
if(parts.size() < 3) | |||
return; | |||
SHAPE shape = parse(parts.at(1)); | |||
MODE mode = Parser::mode(parts.at(2)); | |||
_update(shape,mode); | |||
} | |||
} | |||
} // namespace betacore |
@ -0,0 +1,31 @@ | |||
#include "client.hpp" | |||
#include <iostream> | |||
void test(betacore::SHAPE &s, betacore::MODE &m) | |||
{ | |||
std::cout | |||
<< "Got Shape::" | |||
<< betacore::Parser::shape(s) | |||
<< "\tFrom" | |||
<< betacore::Parser::mode(m) | |||
<< std::endl; | |||
} | |||
int main(int argc, char *argv[]) | |||
{ | |||
std::function<void(betacore::SHAPE & s, betacore::MODE & m)> fn = test; | |||
betacore::Client client(betacore::ALICE, 4444, "localhost", fn); | |||
client.send(false, betacore::TRIANGLE); | |||
client.send(true, betacore::TRIANGLE); | |||
//s.off(); | |||
//while(client.running()){} | |||
std::string a; | |||
while (client.running()) | |||
{ | |||
std::cin >> a; | |||
client.send(false, betacore::TRIANGLE); | |||
if (a == "q") | |||
client.kill(); | |||
} | |||
return 0; | |||
} |
@ -0,0 +1,137 @@ | |||
#include "../includes/server.hpp" | |||
namespace betacore | |||
{ | |||
Server::Server(int port) | |||
{ | |||
this->port = port; | |||
std::cout << "And so it begins..." << std::endl; | |||
this->start(); | |||
} | |||
void Server::start() | |||
{ | |||
this->server_socket = socket(AF_INET, SOCK_STREAM, 0); | |||
if (this->server_socket < 0) | |||
{ | |||
std::cout << "ERROR on opening socket" << std::endl; | |||
return; | |||
} | |||
std::cout << "Socket Connected" << std::endl; | |||
bzero((char *)&server_address, sizeof(server_address)); | |||
server_address.sin_family = AF_INET; | |||
server_address.sin_addr.s_addr = INADDR_ANY; | |||
server_address.sin_port = htons(this->port); | |||
if (bind( | |||
server_socket, | |||
(struct sockaddr *)&server_address, | |||
sizeof(server_address)) < 0) | |||
{ | |||
std::cout << "ERROR on binding " << std::endl; | |||
return; | |||
} | |||
std::cout << "Bound" << std::endl; | |||
online = true; | |||
server_running = true; | |||
std::cout << "Server is online" << std::endl; | |||
signal(SIGPIPE, SIG_IGN); // Prevents issue with sig kill on client | |||
std::thread listen_thread([this] { this->listener(); }); | |||
listen_thread.detach(); | |||
} | |||
void Server::listener() | |||
{ | |||
std::cout << "Listener " << online << std::endl; | |||
struct sockaddr_in client_address; | |||
listen(this->server_socket, 10); | |||
while (online) | |||
{ | |||
socklen_t client_socket_length = sizeof(client_address); | |||
int client_number = | |||
accept(server_socket, (struct sockaddr *)&client_address, &client_socket_length); | |||
this->clients.push_back(client_number); | |||
std::cout << "New Conenction" << std::endl; | |||
if (client_number < 0) | |||
{ | |||
std::cout << "ERROR on accept" << std::endl; | |||
continue; | |||
} | |||
std::thread socket_thread([this, client_number] { this->read_socket(client_number); }); | |||
socket_thread.detach(); | |||
} | |||
this->shutdown(); | |||
} | |||
void Server::read_socket(int client) | |||
{ | |||
std::cout | |||
<< "Ready To Read " | |||
<< client | |||
<< std::endl; | |||
int n; | |||
char buffer[BUFFER_LENGTH]; | |||
while (online && | |||
std::find(clients.begin(), clients.end(), client) != clients.end()) | |||
{ | |||
bzero(buffer, BUFFER_LENGTH); | |||
n = read(client, buffer, BUFFER_LENGTH - 1); | |||
if (n < 0) | |||
{ | |||
std::cout << "ERROR reading from socket" << std::endl; | |||
break; | |||
} | |||
this->forward_message(client, buffer); | |||
} | |||
std::cout << "Closing Connection for " << client << std::endl; | |||
clients.erase( | |||
std::remove(clients.begin(), clients.end(), client), clients.end()); | |||
close(client); | |||
} | |||
void Server::forward_message(int client, char buffer[BUFFER_LENGTH]) | |||
{ | |||
std::cout << "forward message form " << client << std::endl; | |||
int n; | |||
int error = 0; | |||
for (int c : clients) | |||
{ | |||
if (c == client) | |||
continue; | |||
std::cout | |||
<< "forward message form " | |||
<< client | |||
<< "to " | |||
<< c | |||
<< std::endl; | |||
n = write(c, buffer, strlen(buffer)); | |||
if (n < 0) | |||
{ | |||
std::cout << "ERROR Writing socket to " << c << std::endl; | |||
} | |||
} | |||
} | |||
void Server::shutdown() | |||
{ | |||
std::cout << "Server is shuting down" << std::endl; | |||
std::cout << "Closing server socket" << std::endl; | |||
close(this->server_socket); | |||
server_running = false; | |||
} | |||
void Server::off() | |||
{ | |||
this->online = false; | |||
} | |||
bool Server::running() | |||
{ | |||
return this->server_running; | |||
} | |||
} // namespace betacore |
@ -0,0 +1,8 @@ | |||
#include "server.hpp" | |||
int main(int argc, char * argv[]){ | |||
betacore::Server s(4444); | |||
//s.off(); | |||
while(s.running()){} | |||
return 0; | |||
} |
@ -0,0 +1 @@ | |||
https://stackoverflow.com/questions/10673585/start-thread-with-member-function |