diff options
Diffstat (limited to 'src/net/client.c')
| -rw-r--r-- | src/net/client.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/net/client.c b/src/net/client.c new file mode 100644 index 0000000..2606bd4 --- /dev/null +++ b/src/net/client.c @@ -0,0 +1,156 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <assert.h> +#include "client.h" +#include "../global.h" +#include "../player.h" +#include "../game.h" + +/** + * Client side function; connects to specified host:port + * @param[in] host Hostname of server + * @param[in] port Port of server + * @return Socket with open connection to server + */ +int client_connect_server(const char* host, const char* port) +{ + assert(host != NULL); + assert(port != NULL); + + int status; + int sock; + struct addrinfo hints, *result, *tmp; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; // TCP socket + + status = getaddrinfo(host, port, &hints, &result); + if(status != 0) + { + printf("getaddrinfo: %s\n", gai_strerror(status)); + exit(EXIT_FAILURE); + } + + // connect to first result in linked addrinfo list + for(tmp = result; tmp != NULL; tmp = tmp->ai_next) + { + // create socket + sock = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); + if(sock == -1) + continue; + + // connect! + if(connect(sock, tmp->ai_addr, tmp->ai_addrlen) != -1) + break; // Success! + + close(sock); + } + + if(tmp == NULL) + { + printf("failed to connect\n"); + exit(EXIT_FAILURE); + } + freeaddrinfo(result); + + return sock; +} + +bool client_recv_player_list(const uint8_t* payload, const uint8_t data_len) +{ + assert(payload != NULL); + + data_store* ds = datamodel(); + uint32_t pos = 0; + + ds->players.count = payload[pos++]; + + // read usernames from buffer + for(int i=0; i<ds->players.count; i++) + { + uint8_t namelen; + ds->players.players[i].player_id = payload[pos++]; + namelen = payload[pos++]; + assert(namelen <= MAX_PLAYER_NAME_LENGTH); + strncpy(ds->players.players[i].player_name, (const char*) payload+pos, namelen); + ds->players.players[i].player_name[namelen] = '\0'; + pos += namelen; + } + + return true; +} + +bool client_recv_deal_cards(const uint8_t* payload, const uint8_t payload_len) +{ + assert(payload != NULL); + 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++) + ds->hand.cards[i] = payload[i]; + + return true; +} + +bool client_recv_selected_stack(const uint8_t* payload, const uint8_t payload_len) +{ + 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; + + return 1; +} + +uint8_t client_send_selected_stack(uint8_t* payload, const uint8_t payload_len) +{ + data_store* ds = datamodel(); + + payload[0] = ds->stack_index; + assert(ds->stack_index <= NUM_TABLE_STACKS); + + return 1; +} + |
