@ -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 | OUTPUT_DIR= bin | ||||
COMPILER = g++ | COMPILER = g++ | ||||
COMPILER_FLAGS=-w | |||||
COMPILER_FLAGS=-w -std=c++11 | |||||
SOURCE_DIR = source/ | SOURCE_DIR = source/ | ||||
INCLUDES_DIR =-I includes/ | 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: | make_dir: | ||||
mkdir -p $(OUTPUT_DIR) | mkdir -p $(OUTPUT_DIR) |
@ -1,2 +1,2 @@ | |||||
export SDL_VIDEO_X11_VISUALID= | 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 |