-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
105 lines (84 loc) · 3.09 KB
/
server.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
#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include "protocol.h"
int addClient(struct sockaddr_in** clients, ssize_t* clients_len, struct sockaddr_in* client){
int client_id = -1;
char client_str_ip[INET_ADDRSTRLEN];
for (size_t i = 0; i < *clients_len; i++){
if((client->sin_addr.s_addr == (*clients)[i].sin_addr.s_addr) && (client->sin_port == (*clients)[i].sin_port)){
client_id = i;
break;
}
}
if (client_id == -1){
*clients_len += 1;
*clients = realloc(*clients, sizeof(*client) * (*clients_len));
(*clients)[*clients_len - 1] = *client;
client_id = *clients_len - 1;
inet_ntop(AF_INET, &(client->sin_addr), client_str_ip, INET_ADDRSTRLEN);
printf("New user connected from %s:%d, total users: %zd.\n\n", client_str_ip, client->sin_port, *clients_len);
}
return client_id;
}
void broadcast(int socket, struct dtgram* message, size_t length, struct sockaddr_in* clients, ssize_t clients_len, int sender_id){
socklen_t client_address_size;
for (size_t i = 0; i < clients_len; i++){
if (i == sender_id) continue;
client_address_size = sizeof(clients[i]);
if (sendto(socket, message, length, 0, (struct sockaddr *) &clients[i], client_address_size) < 0){
printf("error sending message to socket id %d\n", sender_id);
}
}
printf("Port %d (%s) sended message:\n-> %s\n", clients[sender_id].sin_port, message->name, message->text);
}
/// @brief Is valid dgram
/// @return returns 0 if datagram is valid or less then 0 if is not
int validate_dgram(struct dtgram* message){
if (message->colour < 48 || message->colour > 55) return -1;
if (message->prefix != PREFIX) return -2;
if (message->prefix != PREFIX) return -3;
int sender_len = strlen(message->name);
if (sender_len > 32) return -4;
int text_len = strlen(message->text);
if (text_len > 1024) return -5;
if (message->text[0] == '\0') return -6;
if (message->text[0] == '\n') return -7;
return 0;
}
int main(int argc, char** argv){
int s, client_address_size, client_id, recived;
struct sockaddr_in client, server;
struct sockaddr_in* clients = malloc(0);
ssize_t clients_len = 0;
struct dtgram message;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0){
perror("error calling socket");
return __LINE__;
}
server.sin_family = AF_INET;
server.sin_port = htons(31006);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (struct sockaddr*)&server, sizeof(server)) < 0){
perror("bind");
return __LINE__;
}
printf("Port assigned is %d\n", ntohs(server.sin_port));
client_address_size = sizeof(client);
FILE* file = fopen("serverlogs.bin", "w");
while(1){
if((recived = recvfrom(s, &message, DTGRAMSIZE, 0, (struct sockaddr *) &client, (socklen_t *) &client_address_size)) >= 0){
client_id = addClient(&clients, &clients_len, &client);
}
if (validate_dgram(&message) == 0){
broadcast(s, &message, recived, clients, clients_len, client_id);
fwrite(&message, sizeof(char), recived, file);
fflush(file);
}
}
free(clients);
fclose(file);
close(s);
}