summaryrefslogtreecommitdiff
path: root/src/net/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/client.c')
-rw-r--r--src/net/client.c156
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;
+}
+