/udp_chat_server/Server.c
C | 475 lines | 363 code | 79 blank | 33 comment | 55 complexity | 6c384b95d68d0c41628c9526d1d04dc0 MD5 | raw file
- #include "Server.h"
- /* accept or decline a connection request.
- * A new user gets accepted when the choosen name is not in the user list
- */
- void
- sendSV_CON_REP()
- {
- ID = 2;
- uint8_t accepted = 1;
- uint16_t name_length;
- memcpy(&name_length, CL_CON_REQ + 1, sizeof(uint16_t));
- name_length = ntohs(name_length);
- char *name = malloc(name_length);
- strncpy(name, CL_CON_REQ + 3, name_length);
- /* Check if username already in list */
- if(find_username(name) == 1)
- {
- add_user(name);
- accepted = 0;
- }else accepted = 1;
- SV_CON_REP = malloc(sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint16_t));
- memcpy(SV_CON_REP, &ID, sizeof(uint8_t));
- memcpy(SV_CON_REP + 1, &accepted, sizeof(uint8_t));
- uint16_t cl_port = user->new_sv_sock_addr.sin_port;
- memcpy(SV_CON_REP + 2, &cl_port, sizeof(uint16_t));
- err = sendto(server_socket, SV_CON_REP, 4, 0, &from, sizeof(struct sockaddr_in));
- if (err == -1)
- printf("ERROR: Cannot send SV_CON_REP to client.\n");
- if(accepted == 0)
- {
- sendSV_CON_AMSG();
- }
- }
- /* inform all users about the new client */
- void
- sendSV_CON_AMSG()
- {
- ID = 3;
- SV_CON_AMSG = malloc(strlen(user->name)+3);
- uint16_t name_length = htons(strlen(user->name));
- memcpy(SV_CON_AMSG, &ID, sizeof(uint8_t));
- memcpy(SV_CON_AMSG + 1, &name_length, sizeof(uint16_t));
- strncpy(SV_CON_AMSG + 3, user->name, strlen(user->name));
- sendToAll(SV_CON_AMSG, 3 + strlen(user->name));
- }
- /* build a recieved user message end send it to all users */
- void
- sendSV_AMSG(struct user *sender)
- {
- ID = 5;
- uint16_t name_length = htons(strlen(sender->name));
-
- uint32_t msg_length;
- memcpy(&msg_length, CL_MSG+1, sizeof(uint32_t));
- msg_length = ntohl(msg_length);
- char *msg = malloc(msg_length);
- strncpy(msg, CL_MSG+5, msg_length);
- SV_AMSG = malloc(7 + strlen(msg) + strlen(sender->name));
-
- msg_length = htonl(msg_length);
- memcpy(SV_AMSG, &ID, 1);
- memcpy(SV_AMSG+1, &name_length, 2);
- memcpy(SV_AMSG+3, sender->name, strlen(sender->name));
- memcpy(SV_AMSG+3+strlen(sender->name), &msg_length, 4);
- memcpy(SV_AMSG+7+strlen(sender->name), msg, ntohl(msg_length));
-
- sendToAll(SV_AMSG, 7 + strlen(sender->name) + ntohl(msg_length));
- }
- /* build char* SV_DISC_REP as response to CL_DISC_REQ */
- void
- sendSV_DISC_REP(struct user *sender)
- {
- ID = 7;
- SV_DISC_REP = malloc(1);
- memcpy(SV_DISC_REP, &ID, 1);
- int count;
- for (count = 0; count < 2; count ++)
- {
- to.sin_family = AF_INET;
- to.sin_port = htons(sender->port);
- to.sin_addr.s_addr = inet_addr(sender->IP);
- err = sendto(sender->sv_socket, SV_DISC_REP, 1, 0, &to, sizeof(struct sockaddr_in));
- if (err == -1)
- {
- printf("ERROR: Cannot send SV_DISC_REP to client.\n");
- count += 1;
- sleep(5);
- }
- else
- sendSV_DISC_AMSG(sender->name);
- remove_user(sender);
- break;
-
- }
- }
- /* build char *SV_DISC_AMSG to inform about client disconnect */
- void
- sendSV_DISC_AMSG(char *name)
- {
- ID = 8;
- uint16_t name_length;
- name_length = strlen(name);
- name_length = htons(name_length);
- SV_DISC_AMSG = malloc(3 + strlen(name));
- memcpy(SV_DISC_AMSG, &ID, 1);
- memcpy(SV_DISC_AMSG+1, &name_length, 2);
- strncpy(SV_DISC_AMSG+3, name, strlen(name));
- sendToAll(SV_DISC_AMSG, 3 + strlen(name));
-
- }
- /* send messages to all users in the list */
- void
- sendToAll(char *msg, int msg_length)
- {
- struct user *receiver = user;
- int i;
- for (i = 0; i < usercount; i++)
- {
- to.sin_family = AF_INET;
- to.sin_port = htons(receiver->port);
- to.sin_addr.s_addr = inet_addr(receiver->IP);
- err = sendto(receiver->sv_socket, msg, msg_length, 0, &to, sizeof(struct sockaddr_in));
- if (err == -1)
- printf("ERROR: Cannot send msg (ID: %i) to client.\n", atoi(msg[0]));
- receiver = receiver->next;
- }
- }
- /* remove user from list, clear the associated socket and free allocated space */
- void
- remove_user(struct user *leaver)
- {
- struct user *tmp;
- tmp = user;
- int i;
- for (i = 0; i < usercount; i++)
- {
- if(tmp->name == leaver->name)
- {
- close(tmp->sv_socket);
- free(tmp);
- usercount --;
- break;
- }
- else if (tmp->next->name == leaver->name)
- {
- tmp->next = leaver->next;
- close(leaver->sv_socket);
- free(tmp->next);;
- usercount --;
- break;
- }
- else
- tmp = tmp->next;
- }
- }
- /*
- * checks wether username exists
- * @param name - the username to look for
- * return 1 - username doesn't exist
- * return 0 - username already exists
- */
- int
- find_username(char *name)
- {
- struct user *tmp = malloc(sizeof(struct user *));
- if(usercount == 0)
- {
- return 1;
- }
- else
- {
- tmp = user;
- while(tmp->next != NULL)
- {
- if(strncmp(tmp->name, name, strnlen(name)) == 0)
- {
- return 0;
- }
- tmp = tmp->next;
- }
- return 1;
- }
- }
- /* add user
- * @param name = username of the new_user user
- */
- void
- add_user(char *name)
- {
- new_user = malloc(sizeof(struct user));
-
- // set name
- strncpy(new_user->name, name, strlen(name));
- new_user->rep_counter;
- new_user->sv_socket = socket(AF_INET, SOCK_DGRAM, 0);
- strncpy(new_user->IP,inet_ntoa(from.sin_addr), strlen(inet_ntoa(from.sin_addr)));
- new_user->port = ntohs(from.sin_port);
- struct sockaddr_in sv_sock_add;
- sv_sock_add.sin_family = AF_INET;
- sv_sock_add.sin_port = 0;
- sv_sock_add.sin_addr.s_addr = inet_addr("127.0.0.1");
- new_user->new_sv_sock_addr = sv_sock_add;
- /* new_user port for the new_user client socket */
- err = bind(new_user->sv_socket, (struct sockaddr *) &new_user->new_sv_sock_addr, sizeof(struct sockaddr_in));
- if(err < 0)
- {
- perror("Bind error");
- }
- // set next user
- new_user->next = user;
- user = new_user;
-