diff options
| -rw-r--r-- | src/game.c | 32 | ||||
| -rw-r--r-- | src/global.h | 3 | ||||
| -rw-r--r-- | src/main.c | 5 | ||||
| -rw-r--r-- | src/net.c | 51 | ||||
| -rw-r--r-- | src/net.h | 36 | ||||
| -rw-r--r-- | src/net_client.c | 141 | ||||
| -rw-r--r-- | src/net_server.c | 146 |
7 files changed, 209 insertions, 205 deletions
@@ -3,6 +3,7 @@ #include "hand.h" #include <stdlib.h> #include <stdbool.h> +#include <string.h> #include <time.h> #include <unistd.h> #include <assert.h> @@ -31,7 +32,7 @@ static void init_mainstack(card *stack, const uint32_t size) } } -static void main_loop_client() +static void main_loop_client(int sock) { bool running = true; gamestate state = STATE_CLIENT_WAIT_CARDS; @@ -113,7 +114,7 @@ static void main_loop_client() } -static void main_loop_server() +static void main_loop_server(socket_list_t* sock) { bool running = true; gamestate state = STATE_SERVER_DEAL_CARDS; @@ -242,13 +243,25 @@ void start_game(const bool servermode, const char* addr, const char* port) if(server_process) // Start server and connect to localhost { - int ssock; + int server_sock; + socket_list_t client_socks; uint8_t num_opponents = 1; - ssock = server_start(port); - server_get_players(ssock, num_opponents); + server_sock = server_start(port); + server_get_players(server_sock, &client_socks, num_opponents); - main_loop_server(); + for(int i=0; i<num_opponents; i++) + { + net_recv(client_socks.sockets[i], msg_type_hello); + printf("Player connected: %s\n", data->players.players[i].player_name); + } + + for(int i=0; i<num_opponents; i++) + { + net_send(client_socks.sockets[i], msg_type_start_game, NULL); + } + + main_loop_server(&client_socks); } else // Connect to server { @@ -256,7 +269,10 @@ void start_game(const bool servermode, const char* addr, const char* port) sleep(1); // TODO make sure server process is listening sock = client_connect_server(addr, port); - client_hello(sock, "nickname1"); + + strncpy(data->nickname, "nickname", 10); + //client_hello(sock, "nickname1"); + //net_send() net_recv(sock, msg_type_start_game); net_recv(sock, msg_type_deal_cards); net_recv(sock, msg_type_init_stacks); @@ -269,7 +285,7 @@ void start_game(const bool servermode, const char* addr, const char* port) ui_display_wnd_current_state(pnoc, num_players, 2, score); ui_display_wnd_hand_cards(&data->hand, false, 0); - main_loop_client(); + main_loop_client(sock); ui_fini(); } diff --git a/src/global.h b/src/global.h index c8ad6d3..7385a0a 100644 --- a/src/global.h +++ b/src/global.h @@ -7,9 +7,12 @@ typedef struct { + char nickname[MAX_PLAYER_NAME_LENGTH+1]; player_list players; table_stacks_t table_stacks; hand_t hand; + uint8_t stack_index; + card selected_card; } data_store; typedef enum @@ -14,8 +14,6 @@ int main(int argc, char **argv) char* addr = NULL; bool servermode = false; - int opponents = 1; - if (argc < 2) { printf("usage: '%s address port' for client mode, or '%s port' for server mode\n", argv[0], argv[0]); @@ -25,12 +23,13 @@ int main(int argc, char **argv) { addr = "localhost"; port = argv[1]; + servermode = true; } else if(argc == 3) { addr = argv[1]; port = argv[2]; - + servermode = false; } start_game(servermode, addr, port); @@ -5,10 +5,10 @@ #include <assert.h> #include "net.h" -void *net_recv(int sock, msg_type_t type) +bool net_recv(int sock, const msg_type_t type) { msg_t m; - void *result; + bool result; ssize_t len = recv(sock, &m.hdr, sizeof(msg_header_t), MSG_PEEK); // just peek into packet to determine message header assert(len != -1); @@ -16,7 +16,7 @@ void *net_recv(int sock, msg_type_t type) if(m.hdr.type != type) { printf("net_recv: received message type %d instead of %d", m.hdr.type, type); - return NULL; + return false; } m.payload = malloc(m.hdr.payload_length); // Allocate space for message payload @@ -57,3 +57,48 @@ void *net_recv(int sock, msg_type_t type) return result; } + +bool net_send(int sock, const msg_type_t type, void* param) +{ + bool result = true; + uint8_t payload_len = 255; + uint8_t buf[payload_len+2]; // should be enough for all packet types + + buf[0] = type; + + switch(type) + { + case msg_type_hello: + payload_len = client_send_hello(&buf[2], payload_len); + break; + case msg_type_selected_card: + payload_len = client_send_selected_card(&buf[2], payload_len); + break; + case msg_type_selected_stack_c: + payload_len = client_send_selected_stack(&buf[2], payload_len); + break; + case msg_type_start_game: + payload_len = server_send_start_game(&buf[2], payload_len); + break; + case msg_type_selected_stack_s: + payload_len = server_send_selected_stack(&buf[2], payload_len); + break; + case msg_type_deal_cards: + payload_len = server_send_deal_cards(&buf[2], payload_len, param); + break; + case msg_type_initial_stack: + payload_len = server_send_initial_stack(&buf[2], payload_len, param); + break; + default: + printf("net_send: Unknown message type %d received\n", type); + exit(EXIT_FAILURE); + break; + } + + buf[1] = payload_len; + + send(sock, buf, payload_len+2, 0); + + return result; +} + @@ -2,6 +2,7 @@ #define OXEN_NET_H #include <stdint.h> +#include <stdbool.h> #include "player.h" #include "hand.h" #include "table_stacks.h" @@ -20,7 +21,8 @@ typedef enum msg_type_init_stacks = 0x3, msg_type_selected_card = 0x4, msg_type_selected_stack_c = 0x5, - msg_type_selected_stack_s = 0x6 + msg_type_selected_stack_s = 0x6, + msg_type_initial_stack = 0x7 } msg_type_t; // Header format @@ -37,26 +39,36 @@ typedef struct uint8_t *payload; } msg_t; +// Socket list +typedef struct +{ + uint8_t count; + int sockets[MAX_PLAYERS]; +} socket_list_t; + + // generic receive function -void* net_recv(int sock, msg_type_t wanted); +bool net_recv(int sock, msg_type_t wanted); +bool net_send(int sock, const msg_type_t type, void* param); // Server side functions int server_start(const char* port); -int* server_get_players(int serversock, const uint8_t count); -void server_start_game(int* clients, const uint8_t clientcount, const player_list* players); -void server_deal_cards(int sock, const hand_t *h); +void server_get_players(int serversock, socket_list_t* client_socks, const uint8_t count); char* server_recv_hello(const uint8_t* payload, const uint8_t payload_len); card* server_recv_selected_card(const uint8_t* payload, const uint8_t payload_len); uint8_t* server_recv_selected_stack(const uint8_t* payload, const uint8_t payload_len); -void server_send_selected_stack(int* clients, const uint8_t clientcount, const uint8_t stackindex); +uint8_t server_send_start_game(uint8_t* payload, const uint8_t payload_len); +uint8_t server_send_deal_cards(uint8_t* payload, const uint8_t payload_len, const void* param); +uint8_t server_send_selected_stack(uint8_t* payload, const uint8_t payload_len); +uint8_t server_send_initial_stacks(uint8_t* payload, const uint8_t payload_len); // Client side functions int client_connect_server(const char* host, const char* port); -void client_hello(int sock, const char* username); -void client_selected_card(int sock, const card c); -void client_send_selected_stack(int sock, const uint8_t stackindex); -void* client_recv_player_list(const uint8_t* payload, const uint8_t data_len); -hand_t *client_recv_deal_cards(const uint8_t* payload, const uint8_t payload_len); -uint8_t* client_recv_selected_stack(const uint8_t* payload, const uint8_t payload_len); +uint8_t client_send_hello(uint8_t* payload, const uint8_t payload_len); +uint8_t client_send_selected_card(uint8_t* payload, const uint8_t payload_len); +uint8_t client_send_selected_stack(uint8_t* payload, const uint8_t payload_len); +bool client_recv_player_list(const uint8_t* payload, const uint8_t data_len); +bool client_recv_deal_cards(const uint8_t* payload, const uint8_t payload_len); +bool client_recv_selected_stack(const uint8_t* payload, const uint8_t payload_len); #endif // OXEN_NET_H diff --git a/src/net_client.c b/src/net_client.c index 6b5fa60..e742e7a 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -7,73 +7,9 @@ #include <unistd.h> #include <assert.h> #include "net.h" +#include "global.h" #include "player.h" #include "game.h" -#include "global.h" - -/** - * Client side function; Send hello to server - * @param[in] sock Socket to use - * @param[in] username Username of player - */ -void client_hello(int sock, const char* username) -{ - assert(username != NULL); - - uint8_t* buf; - uint8_t namelen = strlen(username); - - buf = malloc(namelen+2); // type + len + username - if(buf == NULL) - { - printf("client_hello: Out of memory\n"); - exit(EXIT_FAILURE); - } - - buf[NET_MSG_OFFSET_TYPE] = msg_type_hello; - buf[NET_MSG_OFFSET_PAYLOAD_LENGTH] = namelen; - memcpy(buf+NET_MSG_OFFSET_PAYLOAD, username, namelen); - - send(sock, buf, namelen+2, 0); - - free(buf); -} - -/** - * Client side function; Send selected card to server - * @param[in] sock Socket to use - * @param[in] c Selected card - */ -void client_selected_card(int sock, const card c) -{ - assert(c >= MIN_CARD && c <= MAX_CARD); - - uint8_t buf[3]; - - buf[NET_MSG_OFFSET_TYPE] = msg_type_selected_card; - buf[NET_MSG_OFFSET_PAYLOAD_LENGTH] = 1; - buf[NET_MSG_OFFSET_PAYLOAD] = c; - - send(sock, buf, 3, 0); -} - -/** - * Client side function; Send selected table stack to server - * @param[in] sock Socket to use - * @param[in] stackindex Index of selected stack - */ -void client_send_selected_stack(int sock, const uint8_t stackindex) -{ - assert(stackindex <= NUM_TABLE_STACKS); - - uint8_t buf[3]; - - buf[NET_MSG_OFFSET_TYPE] = msg_type_selected_stack_c; - buf[NET_MSG_OFFSET_PAYLOAD_LENGTH] = 1; - buf[NET_MSG_OFFSET_PAYLOAD] = stackindex; - - send(sock, buf, 3, 0); -} /** * Client side function; connects to specified host:port @@ -126,7 +62,7 @@ int client_connect_server(const char* host, const char* port) return sock; } -void* client_recv_player_list(const uint8_t* payload, const uint8_t data_len) +bool client_recv_player_list(const uint8_t* payload, const uint8_t data_len) { assert(payload != NULL); @@ -142,40 +78,79 @@ void* client_recv_player_list(const uint8_t* payload, const uint8_t data_len) ds->players.players[i].player_id = payload[pos++]; namelen = payload[pos++]; assert(namelen <= MAX_PLAYER_NAME_LENGTH); - strncpy(ds->players.players[i].player_name, payload+pos, namelen); + strncpy(ds->players.players[i].player_name, (const char*) payload+pos, namelen); ds->players.players[i].player_name[namelen] = '\0'; pos += namelen; } - return NULL; // TODO return boolean (for success indication) + return true; } -hand_t *client_recv_deal_cards(const uint8_t* payload, const uint8_t payload_len) +bool client_recv_deal_cards(const uint8_t* payload, const uint8_t payload_len) { assert(payload != NULL); - - hand_t *h = malloc(sizeof(hand_t)); - assert(payload_len == MAX_HAND_CARDS); // deal_cards packet have fixed size + data_store* ds = datamodel(); + for(int i=0; i<MAX_HAND_CARDS; i++) - { - h->cards[i] = payload[i]; - } + ds->hand.cards[i] = payload[i]; - return h; + return true; } -uint8_t* client_recv_selected_stack(const uint8_t* payload, const uint8_t payload_len) +bool client_recv_selected_stack(const uint8_t* payload, const uint8_t payload_len) { - assert(payload != NULL); - assert(payload_len == 1); + assert(payload != NULL && payload_len == 1); + + data_store* ds = datamodel(); + ds->stack_index = payload[0]; + + assert(ds->stack_index <= NUM_TABLE_STACKS); + + return true; +} + +bool client_recv_initial_stacks(const uint8_t* payload, const uint8_t payload_len) +{ + assert(payload != NULL && payload_len == NUM_TABLE_STACKS); + + data_store* ds = datamodel(); + for(int i=0; i<NUM_TABLE_STACKS; i++) + ds->table_stacks.stacks[i].cards[0] = payload[i]; + + return true; +} + +uint8_t client_send_hello(uint8_t* payload, const uint8_t payload_len) +{ + data_store* ds = datamodel(); + uint8_t namelen = strlen(ds->nickname); + + memcpy(payload, ds->nickname, namelen); + + return namelen; +} + +uint8_t client_send_selected_card(uint8_t* payload, const uint8_t payload_len) +{ + data_store* ds = datamodel(); + card c = ds->selected_card; + + assert(c >= MIN_CARD && c <= MAX_CARD); + + payload[0] = c; - uint8_t* stackindex = malloc(sizeof(uint8_t)); - *stackindex = payload[0]; + return 1; +} + +uint8_t client_send_selected_stack(uint8_t* payload, const uint8_t payload_len) +{ + data_store* ds = datamodel(); - assert(*stackindex <= NUM_TABLE_STACKS); + payload[0] = ds->stack_index; + assert(ds->stack_index <= NUM_TABLE_STACKS); - return stackindex; + return 1; } diff --git a/src/net_server.c b/src/net_server.c index 52dca17..a7f6c48 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -8,6 +8,7 @@ #include <assert.h> #include "net.h" #include "player.h" +#include "global.h" /** * Server side function; start server on specified port @@ -76,108 +77,30 @@ int server_start(const char* port) /** * Server side function; accepts connections from clients * @param[in] serversock Socket on which server is listening + * @param[out] client_socks Socket list in which to store open client connections * @param[in] count Number of clients that should connect - * @return List of $count open sockets with connections to clients */ -int* server_get_players(int serversock, const uint8_t count) +void server_get_players(int serversock, socket_list_t* client_socks, const uint8_t count) { - int* clientsocks; int i; assert(count < MAX_PLAYERS && count > 0); - clientsocks = malloc(count*sizeof(int)); - if(clientsocks == NULL) - { - printf("server_get_players: Out of memory\n"); - exit(EXIT_FAILURE); - } - // accept connections for(i=0; i<count; i++) { - int sock; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); - sock = accept(serversock, (struct sockaddr*) &addr, &addrlen); - if(sock == -1) + client_socks->sockets[i] = accept(serversock, (struct sockaddr*) &addr, &addrlen); + if(client_socks->sockets[i] == -1) { - printf("accept: %s\n", strerror(sock)); + printf("accept: %s\n", strerror(client_socks->sockets[i])); exit(EXIT_FAILURE); } //printf("new client connected: %s\n", inet_ntop(sock.ss_family, get_in_addr((struct sockaddr*)&sock), INET6_ADDRSTRLEN)); printf("new client connected (%d/%d)\n", i+1, count); - clientsocks[i] = sock; } - - return clientsocks; -} - -/** - * Server side function; notifies players of game start and send list of all players - * @param[in] clients List of sockets with connection to clients - * @param[in] clientcount Number of clients - * @param[in] players List of all players (including self) to send - */ -void server_start_game(int* clients, const uint8_t clientcount, const player_list* players) -{ - assert(clients != NULL); - assert(players != NULL); - - uint8_t* buf; - uint8_t usercount = players->count; - uint32_t pos; - uint32_t buflen = 3 + 2*usercount; // type + packetlen + usercount + (usercount * player_id) + (usercount * len) - - //for(int i=0; i<usercount; i++) - // buflen += strlen(players->names[i]); - - buf = malloc(buflen); - if(buf == NULL) - { - printf("server_start_game: Out of memory\n"); - exit(EXIT_FAILURE); - } - buf[NET_MSG_OFFSET_TYPE] = msg_type_start_game; - buf[NET_MSG_OFFSET_PAYLOAD_LENGTH] = buflen - 2; - pos = NET_MSG_OFFSET_PAYLOAD; - buf[pos++] = players->count; - // copy usernames with length to buffer - for(int i=0; i<usercount; i++) - { - /* - buf[pos++] = i; // player_id - uint8_t len = strlen(players->names[i]); - buf[pos++] = len; - memcpy(buf+pos, players->names[i], len); - pos += len;*/ - } - - // send to all users - for(int i=0; i<clientcount; i++) - send(clients[i], buf, buflen, 0); - - free(buf); -} - -/** - * Server side function; broadcast a selected table stack to all clients - * @param[in] clients Array of sockets with connections to clients - * @param[in] clientcount Number of sockets/clients - * @param[in] stackindex Selected stack to broadcast - */ -void server_send_selected_stack(int* clients, const uint8_t clientcount, const uint8_t stackindex) -{ - assert(clients != NULL); - assert(stackindex <= NUM_TABLE_STACKS); - - uint8_t buf[3]; - buf[NET_MSG_OFFSET_TYPE] = msg_type_selected_stack_s; - buf[NET_MSG_OFFSET_PAYLOAD_LENGTH] = 1; - buf[NET_MSG_OFFSET_PAYLOAD] = stackindex; - - for(int i=0; i<clientcount; i++) - send(clients[i], buf, 3, 0); + client_socks->count = count; } /** @@ -226,21 +149,52 @@ uint8_t* server_recv_selected_stack(const uint8_t* payload, const uint8_t payloa return index; } -/** - * Server side function; deal cards to a client (send hand) - * @param[in] sock Socket to use - * @param[in] h Hand to send - */ -void server_deal_cards(int sock, const hand_t *h) +uint8_t server_send_start_game(uint8_t* payload, const uint8_t payload_len) { - assert(h != NULL); + uint16_t pos = 0; + data_store* ds = datamodel(); + player_list* players = &ds->players; - uint8_t buf[2+MAX_HAND_CARDS]; + payload[pos++] = players->count; + + // copy player_ids, length and nicknames to buffer + for(int i=0; i<players->count; i++) + { + pnoc_t* pl = &players->players[i]; + payload[pos++] = pl->player_id; + uint8_t len = strlen(pl->player_name); + payload[pos++] = len; + memcpy(payload+pos, pl->player_name, len); + payload += len; + } + + assert(pos <= payload_len); + + return pos; +} + +uint8_t server_send_selected_stack(uint8_t* payload, const uint8_t payload_len) +{ + data_store* ds = datamodel(); + + payload[0] = ds->stack_index; + + return 1; +} + +uint8_t server_send_deal_cards(uint8_t* payload, const uint8_t payload_len, const void* param) +{ + const hand_t* hand = (hand_t*) param; - buf[NET_MSG_OFFSET_TYPE] = msg_type_deal_cards; - buf[NET_MSG_OFFSET_PAYLOAD_LENGTH] = MAX_HAND_CARDS; for(int i=0; i<MAX_HAND_CARDS; i++) - buf[NET_MSG_OFFSET_PAYLOAD+i] = h->cards[i]; + payload[i] = hand->cards[i]; - send(sock, buf, 2+MAX_HAND_CARDS, 0); + return MAX_HAND_CARDS; } + + +uint8_t server_send_initial_stacks(uint8_t* payload, const uint8_t payload_len) +{ +// TODO +} + |
