Bozza iniziale del server

This commit is contained in:
Claudio Maggioni 2017-12-29 19:09:47 +01:00
parent d944ded792
commit e5ab042be3
3 changed files with 223 additions and 0 deletions

77
gamedata.c Normal file
View file

@ -0,0 +1,77 @@
#include <stdio.h>
#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;
}

17
gamedata.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef gamedata
#define gamedata
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
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

129
server.c Normal file
View file

@ -0,0 +1,129 @@
#include <arpa/inet.h>
#include <sys/types.h>
#include <stdint.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#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);
}