-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtd.c
executable file
·400 lines (306 loc) · 11.2 KB
/
td.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
/**
*
* Dario Antonio Lassoni
* Matricola: 565721
*
*/
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include "libs/logger.h"
#include "libs/device_utils.h"
#include "libs/common_utils.h"
#include "libs/database.h"
void print_help() {
printf(" menu\n\tmostra il menu dei piatti contenente:\n\t1. il codice identificativo del piatto\n\t2. la descrizione del piatto\n\t3. il prezzo\n");
printf(" comanda {<piatto_1-quantità_1>...<piatto_n-quantità_n>}\n\tinvia una comanda con i piatti e la quantità indicati\n");
printf(" conto\n\tchiede il conto e mostra il prezzo di ogni singolo piatto.\n\tUna volta chiesto il conto non è più possibile eseguire altri comandi.\n");
}
void print_start_menu() {
printf("***************************** BENVENUTO *****************************\n");
printf("Digita un comando:\n\n");
printf("1) help\t\t--> mostra i dettagli dei comandi\n");
printf("2) menu\t\t--> mostra il menu dei piatti\n");
printf("3) comanda\t--> invia una comanda\n");
printf("4) conto\t--> chiede il conto\n");
}
int main(int argc, char* argv[]) {
int ret, sd, i, fdmax;
fd_set master, read_fds;
struct sockaddr_in srv_addr;
struct device dev;
char *input, *buffer;
struct cmd_struct* command;
struct table *table_list, *temp_table;
struct dish *dish_list, *temp_dish;
input = (char*)malloc(sizeof(char) * INPUT_SIZE);
buffer = NULL;
command = NULL;
table_list = NULL;
temp_table = NULL;
dish_list = NULL;
temp_dish = NULL;
/* Check della porta */
if(!check_port(argc, argv)) {
printf("Argomenti errati. Specificare correttamente il comando come segue: ./td <porta>\n");
exit(0);
}
/* Creazione socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
/* Creazione indirizzo del server */
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons(4242);
inet_pton(AF_INET, "127.0.0.1", &srv_addr.sin_addr);
/* Creazione della struttura device per la fase di riconoscimento */
dev.port = atoi(argv[1]);
dev.type = TD;
dev.next = NULL;
/* Connessione */
ret = connect(sd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
if(ret < 0) {
perror("Errore in fase di connessione: ");
exit(1);
}
/* Init dei set utilizzati per la select */
FD_ZERO(&master);
FD_ZERO(&read_fds);
FD_SET(0, &master); // Descrittore STDIN del Kitchen Device
FD_SET(sd, &master);
fdmax = sd;
/* Invio della richiesta di riconoscimento verso il server */
write_text_to_buffer((void*)&buffer, "RECOGNIZE_ME");
ret = send_data(sd, buffer);
if(ret < 0) {
perror("Errore in fase di riconoscimento (step 1): \n");
exit(1);
}
/* Attesa da parte del server dell'acquisizione della richiesta */
ret = receive_data(sd, (void*)&buffer);
if(ret < 0) {
perror("Errore in fase di riconoscimento (step 2): \n");
exit(1);
}
if(strcmp("START_RECOGNIZE", buffer)) {
printf("Errore in fase di riconoscimento: segnale di inizio riconoscimento non ricevuto dal server");
exit(1);
}
/* Invio la tipologia del device al server per la fase di riconoscimento */
sprintf(buffer, "%d %d", dev.port, dev.type);
ret = send_data(sd, buffer);
if(ret < 0) {
perror("Errore in fase di riconoscimento (step 3): \n");
exit(1);
}
/* In attesa di ACK da parte del server per conferma di riconoscimento avvenuto */
ret = receive_data(sd, (void*)&buffer);
if(strcmp("END_RECOGNIZE", buffer)) {
printf("Errore in fase di riconoscimento: segnale di fine riconoscimento non ricevuto dal server");
exit(1);
}
if(ret < 0) {
perror("Errore in fase di ricezione dell'ACK per avvenuto riconoscimento: \n");
exit(1);
}
for(;;) {
printf("Inserire il codice di prenotazione: ");
fflush(stdout);
free_mem((void*)&buffer);
buffer = (char*)malloc(sizeof(char) * CMD_LOGIN_LEN); // login + BOOKING_CODE_LEN
strcpy(buffer, "login ");
/* Prelevo in input il codice di prenotazione */
fgets(input, BOOKING_CODE_LEN, stdin);
if(strcmp(input, "\n") == 0) {
free_mem((void*)&buffer);
continue;
}
/* Concatenzione del comando login con il codice di prenotazione da inviare al server */
strcat(buffer, input);
/* Invio del comando login <BOOKING_CODE> */
ret = send_data(sd, buffer);
if(ret < 0) {
perror("Errore in fase di invio codice di prenotazione");
exit(1);
}
/* Attesa della response da parte del server per conferma verifica */
ret = receive_data(sd, (void*)&buffer);
if(ret < 0) {
perror("Errore in fase di ricezione verifica codice prenotazione");
exit(1);
}
if(strcmp(buffer, "BOOKING_CODE_IS_VALID\0") == 0) {
printf("Codice prenotazione corretto\n");
free_mem((void*)&buffer);
memset(input, 0, INPUT_SIZE);
break;
} else if(strcmp(buffer, "BOOKING_CODE_IS_NOT_VALID\0") == 0) {
printf("Codice di prenotazione non valido.\n");
} else {
printf("Errore: è stato ricevuto un messaggio di validazione errato dal server\n");
}
}
print_start_menu();
for(;;) {
/* init del read_fds usato nella select() */
read_fds = master;
/* Mi blocco in attesa di descrittori pronti in lettura */
ret = select(fdmax + 1, &read_fds, NULL, NULL, NULL);
if(ret < 0) {
LOG_ERROR("Errore durante la select");
exit(1);
}
/* Scorro tutti i descrittori nella read_fds */
for(i = 0; i <= fdmax; i++) {
/* Controllo se i è pronto */
if(FD_ISSET(i, &read_fds)) {
if(i == 0) { // Gestione comandi ricevuti dallo Standard Input del Kitchen Device
fgets(input, INPUT_SIZE, stdin);
if(strcmp(input, "esc\n") == 0) {
free_mem((void*)&buffer);
free_mem((void*)&input);
temp_table = table_list;
while(table_list != NULL) {
temp_table = temp_table->next;
free_mem((void*)&table_list);
table_list = temp_table;
}
temp_table = NULL;
printf("Chiusura device...\n");
exit(0);
} else if(strcmp(input, "help\n") == 0) {
/* Stampa i dettagli dei comandi */
print_help();
continue;
} else if(strcmp(input, "menu\n") == 0) {
/* Recupera i piatti del menu dal server */
write_text_to_buffer((void*)&buffer, input);
/* Invio del comando menu */
ret = send_data(sd, buffer);
if(ret < 0) {
perror("Errore in fase di invio comando: ");
exit(1);
}
dish_list = NULL;
temp_dish = NULL;
for(;;) {
/* Attesa della response con i piatti del menu */
ret = receive_data(sd, (void*)&buffer);
if(strcmp(buffer, "END_MSG\0") == 0)
break;
/* Aggiunta del tavolo nella table_list */
temp_dish = (struct dish*)malloc(sizeof(struct dish));
temp_dish->next = NULL;
ret = sscanf(buffer, "%d %s - %[^\n]", &temp_dish->price, &temp_dish->identifier[0], &temp_dish->description[0]);
add_to_dish_list(&dish_list, temp_dish);
}
free_mem((void*)&buffer);
print_menu_dishes(dish_list);
} else if(strncmp(input, "comanda", 7) == 0) { // Controlla che la stringa inizi per 'comanda'
command = create_cmd_struct_comanda(input, NULL, -1);
if(command == NULL) {
printf("Sintassi del comando 'comanda' è errata.\n");
printf("Sintassi: comanda {<piatto_1-quantità_1> <piatto_2-quantità_2> ... <piatto_n-quantità_n>}\n");
continue; // Skip dell'invio, sintassi del comando errata
}
/* Invio della comanda */
write_text_to_buffer((void*)&buffer, input);
ret = send_data(sd, buffer);
if(ret < 0) {
perror("Errore in fase di invio comando: ");
exit(1);
}
/* Attesa response avvenuta ricezione comanda */
ret = receive_data(sd, (void*)&buffer);
if(ret < 0) {
perror("Errore durante l'attesa di ricezione\n");
exit(1);
}
if(strcmp("DISH_NOT_PRESENT", buffer) == 0) {
printf("Nella comanda sono presenti piatti che non fanno parte del menu\n");
fflush(stdout);
continue;
} else if(strncmp("COMANDA", buffer, 7) != 0) { // Se nel messaggio ricevuto non è presente la stringa 'COMANDA'
printf("Errore in fase di ricezione response per avvenuta ricezione comanda\n");
fflush(stdout);
continue;
}
printf("%s\n", buffer);
fflush(stdout);
free_mem((void*)&buffer);
} else if(strcmp(input, "conto\n") == 0) {
/* Invio richiesta di conto */
write_text_to_buffer((void*)&buffer, input);
ret = send_data(sd, buffer);
if(ret < 0) {
perror("Errore in fase di invio comando: ");
exit(1); // CAPIRE COME AGIRE IN QUESTI CASI, EVITANDO DI FARE LA EXIT
}
for(;;) {
/* Ricezione del conto */
ret = receive_data(sd, (void*)&buffer);
if(ret < 0) {
perror("Errore in fase di invio comando: ");
exit(1); // CAPIRE COME AGIRE IN QUESTI CASI, EVITANDO DI FARE LA EXIT
}
if(strcmp(buffer, "NO_ORDERS\0") == 0) {
printf("Impossibile calcolare il conto: non è presente nessuna comanda associata\n");
break;
}
if(strcmp("LAST_DISH\0", buffer) == 0) {
ret = receive_data(sd, (void*)&buffer);
if(ret < 0) {
perror("Errore in fase di ricezione comando");
exit(1); // CAPIRE COME AGIRE IN QUESTI CASI, EVITANDO DI FARE LA EXIT
}
printf("%s\n", buffer);
break;
}
printf("%s\n", buffer);
}
fflush(stdout);
/* Pulizia memoria e disconnessione dopo aver chiesto il conto */
free_mem((void*)&buffer);
free_mem((void*)&input);
temp_table = table_list;
while(table_list != NULL) {
temp_table = temp_table->next;
free_mem((void*)&table_list);
table_list = temp_table;
}
temp_table = NULL;
printf("Grazie e arrivederci!\n");
exit(0);
}
} else if(i == sd) { // Gestione notifiche o richiesta di disconnessione dal server
ret = receive_data(sd, (void*)&buffer);
if(ret < 0) {
perror("Errore in fase di ricezione");
continue;
}
if(strcmp(buffer, "SHUTDOWN") == 0) { // Richiesta di disconnessione da parte del server
free_mem((void*)&buffer);
free_mem((void*)&input);
temp_table = table_list;
while(table_list != NULL) {
temp_table = temp_table->next;
free_mem((void*)&table_list);
table_list = temp_table;
}
temp_table = NULL;
printf("Chiusura device...\n");
exit(0);
} else { // Stampa della notifica
printf("%s\n", buffer);
fflush(stdout);
}
}
}
}
}
}