UniversalPizzoccheri/server.c

138 lines
3.6 KiB
C

#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(prefix("sell", command)) {
unsigned int sold = gamedata_sell_pizzoccheri(curr_data);
fprintf(out, "OK %d sold.\n", sold);
}
else if(sscanf(command, "set price %lf\n", &(arg1.d)) == 1) {
bool status = gamedata_set_unit_price(curr_data, arg1.d);
fprintf(out, status ? "OK The price of one pizzocchero is now at %.02lf CHF.\n"
: "KO %.02lf CHF is not a valid price.\n", arg1.d);
}
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);
}