From e5ab042be306d9a953a9e8b888b6418ea81fd481 Mon Sep 17 00:00:00 2001 From: praticamentetilde Date: Fri, 29 Dec 2017 19:09:47 +0100 Subject: [PATCH] Bozza iniziale del server --- gamedata.c | 77 ++++++++++++++++++++++++++++++++ gamedata.h | 17 +++++++ server.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 gamedata.c create mode 100644 gamedata.h create mode 100644 server.c diff --git a/gamedata.c b/gamedata.c new file mode 100644 index 0000000..8dd668b --- /dev/null +++ b/gamedata.c @@ -0,0 +1,77 @@ +#include +#include "gamedata.h" + +struct _gamedata { + double chf; + int bitto; + int flour; + int pizzoccheri; + double chf_unit; +}; + +gamedata_t* gamedata_new() { + gamedata_t* self = (gamedata_t*) malloc(sizeof(gamedata_t)); + if(errno != 0) { + perror("gamedata malloc() creation error: "); + } + + self->chf = 0; + self->bitto = 500; + self->flour = 200; + self->pizzoccheri = 0; + self->chf_unit = 0.5; + return self; +} + +void gamedata_delete(gamedata_t* self) { + free(self); +} + +void gamedata_print_status(gamedata_t *self, FILE* out) { + fprintf(out, "OK BITTO %d, FLOUR %d, ", self->bitto, self->flour); + fprintf(out, "INVENTORY %d, ", self->pizzoccheri); + fprintf(out, "UNIT PRICE %.02f CHF, PROFIT %.02f CHF\n", self->chf_unit, self->chf); +} + +#define Q_BITTO_FOR_PIZZOCCHERO 1 +#define Q_FLOUR_FOR_PIZZOCCHERO 2 +bool gamedata_make_pizzoccheri(gamedata_t *self, unsigned int q) { + int q_flour = q * Q_FLOUR_FOR_PIZZOCCHERO; + int q_bitto = q * Q_BITTO_FOR_PIZZOCCHERO; + + if(self->flour < q_flour || self->bitto < q_bitto) { + return false; + } + + self->flour -= q_flour; + self->bitto -= q_bitto; + self->pizzoccheri += q; + + return true; +} + +#define PRICE_BITTO_UNIT 0.5 +bool gamedata_buy_bitto(gamedata_t *self, unsigned int q) { + double price = q * PRICE_BITTO_UNIT; + + if(price > self->chf) { + return false; + } + + self->chf -= price; + self->bitto += q; + return true; +} + +#define PRICE_FLOUR_UNIT 0.5 +bool gamedata_buy_flour(gamedata_t *self, unsigned int q) { + double price = q * PRICE_FLOUR_UNIT; + + if(price > self->chf) { + return false; + } + + self->chf -= price; + self->flour += q; + return true; +} diff --git a/gamedata.h b/gamedata.h new file mode 100644 index 0000000..8feaf9a --- /dev/null +++ b/gamedata.h @@ -0,0 +1,17 @@ +#ifndef gamedata +#define gamedata +#include +#include +#include +#include + +typedef struct _gamedata gamedata_t; + +extern gamedata_t* gamedata_new(); +extern void gamedata_delete(); +extern bool gamedata_buy_bitto(gamedata_t*, unsigned int); +extern bool gamedata_buy_flour(gamedata_t*, unsigned int); +extern void gamedata_print_status(gamedata_t*, FILE*); +extern bool gamedata_make_pizzoccheri(gamedata_t*, unsigned int); + +#endif diff --git a/server.c b/server.c new file mode 100644 index 0000000..8889c6b --- /dev/null +++ b/server.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gamedata.h" + +#define SERVER_ADDR htonl(INADDR_ANY) +#define MAX_CLIENTS 100 +#define MAX_COMMAND_LINE_LENGTH 101 + +bool prefix(const char *pre, const char *str) { + return strncmp(pre, str, strlen(pre)) == 0; +} + +int main(int argc, char** argv) { + + if(argc < 2) { + fprintf(stderr, "Give port number as $1\n"); + exit(255); + } + + int sock_conn_d, sock_data_d; + struct sockaddr_in server; + + if((sock_conn_d = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + perror("server socket not created"); + exit(1); + } + + memset(&server, 0, sizeof(server)); // zero the memory + + server.sin_family = AF_INET; + server.sin_addr.s_addr = SERVER_ADDR; + server.sin_port = htons(atoi(argv[1])); + + if(bind(sock_conn_d, (struct sockaddr*)&server, sizeof(server)) == -1) { + perror("server socket not bound"); + exit(2); + } + + while(true) { + if(listen(sock_conn_d, MAX_CLIENTS) != 0) { + perror("cannot listen on socket"); + close(sock_conn_d); + exit(3); + } + + printf("listening...\n"); + + struct sockaddr_in client; + socklen_t client_len = sizeof(client); + sock_data_d = accept(sock_conn_d, (struct sockaddr*)&client, &client_len); + + if(sock_data_d == -1) { + perror("cannot accept client"); + close(sock_conn_d); + exit(4); + } + + pid_t pid = fork(); + + if(pid < 0) { + perror("cannot fork for new client"); + exit(6); + } + else if(pid == 0) { + gamedata_t *curr_data = gamedata_new(); + + unsigned char command[MAX_COMMAND_LINE_LENGTH]; + FILE* in = fdopen(sock_data_d, "r"); + FILE* out = fdopen(dup(sock_data_d), "w"); + + fprintf(out, "OK Connection establshed.\n"); + fflush(out); + + while(true) { + fgets(command, MAX_COMMAND_LINE_LENGTH, in); + + union { + unsigned int u; + double d; + } arg1; + + if(sscanf(command, "MAKE %u\n", &(arg1.u)) == 1) { + bool status = gamedata_make_pizzoccheri(curr_data, arg1.u); + fprintf(out, status ? "OK Made.\n" : "KO 1 Insufficient resources.\n"); + } + else if(sscanf(command, "BUY BITTO %u", &(arg1.u)) == 1) { + bool status = gamedata_buy_bitto(curr_data, arg1.u); + fprintf(out, status ? "OK Purchased.\n" : "KO 2 Insufficient funds\n"); + } + else if(sscanf(command, "BUY FLOUR %u", &(arg1.u)) == 1) { + bool status = gamedata_buy_flour(curr_data, arg1.u); + fprintf(out, status ? "OK Purchased.\n" : "KO 3 Insufficient funds\n"); + } + else if(prefix("STATUS", command)) { + gamedata_print_status(curr_data, out); + } + else if(prefix("EXIT", command)) { + fprintf(out, "OK Closing...\n"); + break; + } + else { + fprintf(out, "KO 255 Syntax error\n"); + } + + fflush(out); + } + + printf("closing data socket...\n"); + + fclose(in); + fclose(out); + + gamedata_delete(curr_data); + + printf("exiting...\n"); + exit(0); + } + // if father process just continue + } + close(sock_conn_d); + exit(0); +}