PageRenderTime 80ms CodeModel.GetById 28ms app.highlight 39ms RepoModel.GetById 3ms app.codeStats 0ms

/udp_chat_server/Server.c

https://bitbucket.org/schnika/chat-server-client
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}