#include #include #include #include #include #include #include #include #include "net.h" #include "player.h" #include "global.h" /** * Server side function; start server on specified port * @param[in] port Port on which server should listen * @return Listening socket */ int server_start(const char* port) { assert(port != NULL); int status; int serversock; struct addrinfo hints, *result, *tmp; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; // IPv4 or IPv6 hints.ai_socktype = SOCK_STREAM; // TCP socket hints.ai_flags = AI_PASSIVE; // wildcard IP hints.ai_protocol = 0; // any protocol status = getaddrinfo(NULL, port, &hints, &result); if(status != 0) { printf("getaddrinfo: %s\n", gai_strerror(status)); exit(EXIT_FAILURE); } // iterate over linked addrinfo list and use first useable entry for(tmp = result; tmp != NULL; tmp = tmp->ai_next) { int yes=1; // create socket serversock = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); if(serversock == -1) continue; // try to reuse still open sockets in TIME_WAIT state setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); // try to bind to address/port if(bind(serversock, tmp->ai_addr, tmp->ai_addrlen) == 0) break; // Success! close(serversock); } if(tmp == NULL) { printf("failed to bind\n"); exit(EXIT_FAILURE); } freeaddrinfo(result); // start listening status = listen(serversock, 1); if(status == -1) { printf("listen: %s\n", strerror(status)); exit(EXIT_FAILURE); } return serversock; } /** * 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 */ void server_get_players(int serversock, socket_list_t* client_socks, const uint8_t count) { int i; assert(count < MAX_PLAYERS && count > 0); // accept connections for(i=0; isockets[i] = accept(serversock, (struct sockaddr*) &addr, &addrlen); if(client_socks->sockets[i] == -1) { 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); } client_socks->count = count; } /** * Server side function; receive hello message from client and read username * @param[in] sock Socket to use * @return Username of client */ char* server_recv_hello(const uint8_t* payload, const uint8_t payload_len) { assert(payload != NULL); char* name; name = malloc(payload_len+1); if(name == NULL) { printf("sender_recv_hello: Out of memory\n"); exit(EXIT_FAILURE); } memcpy(name, payload, payload_len); name[payload_len] = '\0'; return name; } card* server_recv_selected_card(const uint8_t* payload, const uint8_t payload_len) { assert(payload != NULL && payload_len == 1); card* c = malloc(sizeof(card)); assert(c != NULL); *c = payload[0]; return c; } uint8_t* server_recv_selected_stack(const uint8_t* payload, const uint8_t payload_len) { assert(payload != NULL && payload_len == 1); uint8_t* index = malloc(sizeof(uint8_t)); assert(index != NULL); *index = payload[0]; return index; } uint8_t server_send_start_game(uint8_t* payload, const uint8_t payload_len) { uint16_t pos = 0; data_store* ds = datamodel(); player_list* players = &ds->players; payload[pos++] = players->count; // copy player_ids, length and nicknames to buffer for(int i=0; icount; 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; for(int i=0; icards[i]; return MAX_HAND_CARDS; } uint8_t server_send_initial_stacks(uint8_t* payload, const uint8_t payload_len) { // TODO }