/udp_chat_server/Server.c
C | 475 lines | 363 code | 79 blank | 33 comment | 55 complexity | 6c384b95d68d0c41628c9526d1d04dc0 MD5 | raw file
1#include "Server.h"
2
3/* accept or decline a connection request.
4 * A new user gets accepted when the choosen name is not in the user list
5 */
6void
7sendSV_CON_REP()
8{
9 ID = 2;
10 uint8_t accepted = 1;
11 uint16_t name_length;
12 memcpy(&name_length, CL_CON_REQ + 1, sizeof(uint16_t));
13 name_length = ntohs(name_length);
14
15 char *name = malloc(name_length);
16 strncpy(name, CL_CON_REQ + 3, name_length);
17 /* Check if username already in list */
18
19 if(find_username(name) == 1)
20 {
21 add_user(name);
22 accepted = 0;
23
24 }else accepted = 1;
25
26 SV_CON_REP = malloc(sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint16_t));
27 memcpy(SV_CON_REP, &ID, sizeof(uint8_t));
28 memcpy(SV_CON_REP + 1, &accepted, sizeof(uint8_t));
29
30 uint16_t cl_port = user->new_sv_sock_addr.sin_port;
31 memcpy(SV_CON_REP + 2, &cl_port, sizeof(uint16_t));
32
33 err = sendto(server_socket, SV_CON_REP, 4, 0, &from, sizeof(struct sockaddr_in));
34 if (err == -1)
35 printf("ERROR: Cannot send SV_CON_REP to client.\n");
36
37 if(accepted == 0)
38 {
39 sendSV_CON_AMSG();
40 }
41}
42
43
44/* inform all users about the new client */
45void
46sendSV_CON_AMSG()
47{
48 ID = 3;
49 SV_CON_AMSG = malloc(strlen(user->name)+3);
50 uint16_t name_length = htons(strlen(user->name));
51 memcpy(SV_CON_AMSG, &ID, sizeof(uint8_t));
52 memcpy(SV_CON_AMSG + 1, &name_length, sizeof(uint16_t));
53 strncpy(SV_CON_AMSG + 3, user->name, strlen(user->name));
54
55 sendToAll(SV_CON_AMSG, 3 + strlen(user->name));
56}
57
58/* build a recieved user message end send it to all users */
59void
60sendSV_AMSG(struct user *sender)
61{
62
63 ID = 5;
64 uint16_t name_length = htons(strlen(sender->name));
65
66 uint32_t msg_length;
67 memcpy(&msg_length, CL_MSG+1, sizeof(uint32_t));
68 msg_length = ntohl(msg_length);
69 char *msg = malloc(msg_length);
70 strncpy(msg, CL_MSG+5, msg_length);
71
72 SV_AMSG = malloc(7 + strlen(msg) + strlen(sender->name));
73
74 msg_length = htonl(msg_length);
75 memcpy(SV_AMSG, &ID, 1);
76 memcpy(SV_AMSG+1, &name_length, 2);
77 memcpy(SV_AMSG+3, sender->name, strlen(sender->name));
78 memcpy(SV_AMSG+3+strlen(sender->name), &msg_length, 4);
79 memcpy(SV_AMSG+7+strlen(sender->name), msg, ntohl(msg_length));
80
81 sendToAll(SV_AMSG, 7 + strlen(sender->name) + ntohl(msg_length));
82}
83
84/* build char* SV_DISC_REP as response to CL_DISC_REQ */
85void
86sendSV_DISC_REP(struct user *sender)
87{
88 ID = 7;
89 SV_DISC_REP = malloc(1);
90 memcpy(SV_DISC_REP, &ID, 1);
91 int count;
92 for (count = 0; count < 2; count ++)
93 {
94 to.sin_family = AF_INET;
95 to.sin_port = htons(sender->port);
96 to.sin_addr.s_addr = inet_addr(sender->IP);
97 err = sendto(sender->sv_socket, SV_DISC_REP, 1, 0, &to, sizeof(struct sockaddr_in));
98 if (err == -1)
99 {
100 printf("ERROR: Cannot send SV_DISC_REP to client.\n");
101 count += 1;
102 sleep(5);
103 }
104 else
105 sendSV_DISC_AMSG(sender->name);
106 remove_user(sender);
107 break;
108
109 }
110
111}
112
113/* build char *SV_DISC_AMSG to inform about client disconnect */
114void
115sendSV_DISC_AMSG(char *name)
116{
117 ID = 8;
118 uint16_t name_length;
119 name_length = strlen(name);
120 name_length = htons(name_length);
121
122 SV_DISC_AMSG = malloc(3 + strlen(name));
123
124 memcpy(SV_DISC_AMSG, &ID, 1);
125 memcpy(SV_DISC_AMSG+1, &name_length, 2);
126 strncpy(SV_DISC_AMSG+3, name, strlen(name));
127
128 sendToAll(SV_DISC_AMSG, 3 + strlen(name));
129
130
131}
132
133/* send messages to all users in the list */
134void
135sendToAll(char *msg, int msg_length)
136{
137 struct user *receiver = user;
138 int i;
139 for (i = 0; i < usercount; i++)
140 {
141 to.sin_family = AF_INET;
142 to.sin_port = htons(receiver->port);
143 to.sin_addr.s_addr = inet_addr(receiver->IP);
144 err = sendto(receiver->sv_socket, msg, msg_length, 0, &to, sizeof(struct sockaddr_in));
145 if (err == -1)
146 printf("ERROR: Cannot send msg (ID: %i) to client.\n", atoi(msg[0]));
147 receiver = receiver->next;
148 }
149}
150
151
152/* remove user from list, clear the associated socket and free allocated space */
153void
154remove_user(struct user *leaver)
155{
156 struct user *tmp;
157 tmp = user;
158 int i;
159 for (i = 0; i < usercount; i++)
160 {
161 if(tmp->name == leaver->name)
162 {
163 close(tmp->sv_socket);
164 free(tmp);
165 usercount --;
166 break;
167
168 }
169 else if (tmp->next->name == leaver->name)
170 {
171 tmp->next = leaver->next;
172 close(leaver->sv_socket);
173 free(tmp->next);;
174 usercount --;
175 break;
176 }
177 else
178 tmp = tmp->next;
179 }
180}
181
182
183/*
184 * checks wether username exists
185 * @param name - the username to look for
186 * return 1 - username doesn't exist
187 * return 0 - username already exists
188 */
189int
190find_username(char *name)
191{
192 struct user *tmp = malloc(sizeof(struct user *));
193
194 if(usercount == 0)
195 {
196 return 1;
197 }
198 else
199 {
200 tmp = user;
201 while(tmp->next != NULL)
202 {
203 if(strncmp(tmp->name, name, strnlen(name)) == 0)
204 {
205 return 0;
206 }
207 tmp = tmp->next;
208 }
209 return 1;
210 }
211
212}
213/* add user
214 * @param name = username of the new_user user
215 */
216void
217add_user(char *name)
218{
219 new_user = malloc(sizeof(struct user));
220
221 // set name
222 strncpy(new_user->name, name, strlen(name));
223 new_user->rep_counter;
224
225 new_user->sv_socket = socket(AF_INET, SOCK_DGRAM, 0);
226
227 strncpy(new_user->IP,inet_ntoa(from.sin_addr), strlen(inet_ntoa(from.sin_addr)));
228 new_user->port = ntohs(from.sin_port);
229 struct sockaddr_in sv_sock_add;
230 sv_sock_add.sin_family = AF_INET;
231 sv_sock_add.sin_port = 0;
232 sv_sock_add.sin_addr.s_addr = inet_addr("127.0.0.1");
233
234 new_user->new_sv_sock_addr = sv_sock_add;
235
236
237 /* new_user port for the new_user client socket */
238 err = bind(new_user->sv_socket, (struct sockaddr *) &new_user->new_sv_sock_addr, sizeof(struct sockaddr_in));
239 if(err < 0)
240 {
241 perror("Bind error");
242 }
243
244 // set next user
245 new_user->next = user;
246 user = new_user;
247
248 usercount += 1;
249
250}
251
252/* Portnumber validation */
253int
254isValidPort(char *str)
255{
256 in_port_t tmp_port;
257 tmp_port = atoi(str);
258 if(tmp_port < 1024 || tmp_port > 65535)
259 {
260 printf("Invalid port number. Port hast do be between 1024 and 65535.\n");
261 return 0;
262 }
263 printf("Valid port: %u\n", tmp_port);
264 return 1;
265}
266
267
268/* Initialize field descriptors */
269void
270init_fds()
271{
272 FD_ZERO(&readset);
273 FD_SET(server_socket, &readset);
274
275 struct user *tmp;
276 tmp = user;
277
278 highsock = server_socket;
279 int i;
280 for (i = 0; i<usercount; i++)
281 {
282 FD_SET(tmp->sv_socket, &readset);
283 if (tmp->sv_socket > highsock)
284 highsock = tmp->sv_socket;
285 tmp = tmp->next;
286
287 }
288}
289
290
291int main(int argc, char**argv)
292{
293
294 /* Init user */
295 user = malloc(sizeof(struct user));
296 user = NULL;
297 usercount = 0;
298
299 time_to_wait = malloc(sizeof(struct timeval *));
300 time_to_wait->tv_sec = 5;
301 time_to_wait->tv_usec = 0;
302
303 struct timeval *time_now = malloc(sizeof(struct timeval *));
304 struct timeval *last_res = malloc(sizeof(struct timeval *));
305 struct timeval *time_diff = malloc(sizeof(struct timeval *));
306
307
308
309 int error;
310 int flen;
311 int rep_len;
312
313 int c;
314 int index;
315
316 opterr = 0;
317
318 while ((c = getopt(argc, argv, "p:")) != -1)
319 switch(c)
320 {
321 case 'p':
322 if (isValidPort(optarg) != 0)
323 {
324 serv_port = atoi(optarg);
325 break;
326 }
327 return 1;
328 case '?':
329 if (optopt == 'p')
330 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
331 else if (isprint (optopt))
332 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
333 else
334 fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
335 return 1;
336 default:
337 abort ();
338 }
339
340 server_socket = socket(AF_INET, SOCK_DGRAM, 0);
341
342 if (server_socket < 1)
343 {
344 perror("Create socket");
345 } printf("Socket created!\n");
346
347 /* set port and ip*/
348 server_socket_address.sin_family = AF_INET;
349 server_socket_address.sin_port = htons(serv_port);
350 server_socket_address.sin_addr.s_addr = inet_addr("127.0.0.1");
351 printf("IP Adresse: %s Port: %u\n", inet_ntoa(server_socket_address.sin_addr), ntohs(server_socket_address.sin_port));
352
353 error = bind(server_socket, (struct sockaddr *) &server_socket_address, sizeof(struct sockaddr_in));
354
355 if(error < 0)
356 {
357 perror("Bind error");
358 } else printf("Socket bound!\n");
359
360 int res;
361 int sock;
362 time_now->tv_sec = time(NULL);
363 while(1)
364 {
365
366 ID = 0;
367 init_fds();
368 cl_rep_buffer = malloc(64);
369 res = select(highsock + 1, &readset, NULL, NULL, time_to_wait);
370 /* select error*/
371 if (res == -1)
372 {
373 perror("Select Error.");
374 }
375 /* timeout. increase rep_counter for each connected user */
376 else if (res == 0)
377 {
378 time_to_wait->tv_sec = 5;
379 ID = 9;
380 SV_PING_REQ = malloc(1);
381 memcpy(SV_PING_REQ, &ID, sizeof(uint8_t));
382 struct user *tmp;
383 tmp = user;
384 int i;
385 for(i = 0; i<usercount; i++)
386 {
387 sendToAll(SV_PING_REQ, 1);
388 tmp->rep_counter += 1;
389 if(tmp->rep_counter == 4)
390 {
391 printf("Verbindung zu User %s unterbrochen. Nutzr wird vom Server entfernt.\n", tmp->name);
392 remove_user(tmp);
393 }
394 }
395 }
396
397 else if (res > 0)
398 {
399 last_res->tv_sec = time(NULL);
400
401 /* calc time diff */
402 timersub(time_now, last_res, time_diff);
403
404 timersub(time_to_wait, time_diff, time_to_wait);
405
406 if (FD_ISSET(server_socket, &readset))
407 {
408 rep_len = recvfrom(server_socket, cl_rep_buffer, 64, 0, (struct sockaddr*) &from, &flen);
409 memcpy(&ID, cl_rep_buffer, sizeof(uint8_t));
410 if (ID == 1)
411 {
412 printf("Anfrage gestellt.\n");
413 CL_CON_REQ = malloc(rep_len);
414 memcpy(CL_CON_REQ, cl_rep_buffer, rep_len);
415 sendSV_CON_REP();
416 }
417 else
418 {
419 printf("Falsche Anfrage gestellt.\n");
420 }
421 }
422
423
424 struct user *tmp;
425 tmp = user;
426 int i;
427
428 for (i = 0; i < usercount; i++)
429 {
430 if(FD_ISSET(tmp->sv_socket, &readset))
431 {
432 rep_len = recvfrom(tmp->sv_socket, cl_rep_buffer, 64, 0, (struct sockaddr*) &from, &flen);
433 if(rep_len < 0)
434 break;
435 memcpy(&ID, cl_rep_buffer, sizeof(uint8_t));
436
437 switch(ID)
438 {
439
440 /* CL_MSG */
441 case 4:
442 {
443 CL_MSG = malloc(rep_len);
444 memcpy(CL_MSG, cl_rep_buffer, rep_len);
445 sendSV_AMSG(tmp);
446 break;
447 }
448
449 /* CL_DISC_REQ */
450 case 6:
451 {
452 CL_DISC_REQ = malloc(rep_len);
453 memcpy(CL_DISC_REQ, cl_rep_buffer, rep_len);
454 sendSV_DISC_REP(tmp);
455 break;
456 }
457
458 /* CL_PING_REP */
459 case 10:
460 {
461 // reset rep_counter
462 tmp->rep_counter = 0;
463 }
464 default:
465 {
466 break;
467 }
468 }
469 }
470 tmp = tmp->next;
471 }
472 }
473
474 }
475}