#include #include #include #include #include #include "Server.c" #include "Server.h" #include #include #include #include struct AcceptedSocket* acceptIncoming(struct Server *server){ int serverSocketFd=server->socket; struct sockaddr_in clientAddress; socklen_t ClientAddressSize = sizeof(struct sockaddr); int clientSocketFD = accept(serverSocketFd,(struct sockaddr *)&clientAddress,&ClientAddressSize); if(server->running){ struct AcceptedSocket* acceptedSocket = malloc(sizeof(struct AcceptedSocket)); acceptedSocket->address=clientAddress; acceptedSocket->socketFD=clientSocketFD; acceptedSocket->succ=clientSocketFD>0; acceptedSocket->next=NULL; acceptedSocket->shutdown=false; if(!acceptedSocket){ acceptedSocket->error=clientSocketFD; } else { if(server->running){ struct AcceptedSocket *sel_socket=server->accepted_socket; if(sel_socket==NULL){ server->accepted_socket=acceptedSocket; } else { while(1){ if(sel_socket->next==NULL){ sel_socket->next=acceptedSocket; break; } else { sel_socket=sel_socket->next; } } } } } return acceptedSocket; } else { return NULL; } } struct recv_data_arg{ int socketFD; struct Server *server; struct AcceptedSocket *curr_socket; }; void *recv_data(void *threadarg){ struct recv_data_arg *recv_d_arg; recv_d_arg=(struct recv_data_arg *) threadarg; while(recv_d_arg->server->running){ char buffer[30000]={0}; ssize_t amountRecv=recv(recv_d_arg->socketFD, buffer, 30000, 0); if(recv_d_arg->server->running){ if(amountRecv==0) break; recv_d_arg->server->on_message(recv_d_arg->server, buffer, amountRecv, recv_d_arg->socketFD); } } recv_d_arg->curr_socket->shutdown=true; close(recv_d_arg->socketFD); if(recv_d_arg->server->on_disconnect){ recv_d_arg->server->on_disconnect(recv_d_arg->server,recv_d_arg->socketFD); } free(recv_d_arg); pthread_exit(NULL); } void cleanup_conns(struct Server *server){ if(server->accepted_socket){ struct AcceptedSocket *sel_socket=server->accepted_socket; struct AcceptedSocket *prev_socket=server->accepted_socket; struct AcceptedSocket *prev2_socket=server->accepted_socket; while (sel_socket!=NULL){ sel_socket=sel_socket->next; if(prev_socket->shutdown==true){ if(prev_socket==server->accepted_socket){ free(server->accepted_socket); server->accepted_socket=sel_socket; } else { free(prev2_socket->next); prev2_socket->next=sel_socket; } } else { prev2_socket=prev_socket; } prev_socket=sel_socket; } } } void *await_client(void *threadarg){ struct Server *server; server=(struct Server *) threadarg; while (server->running){ printf("\n=== WAITING FOR CONNECTION ===\n\n"); struct AcceptedSocket* new_socket = acceptIncoming(server); if(server->running){ if(new_socket->succ==0){ free(new_socket); } else { struct recv_data_arg *recv_d_arg; recv_d_arg=malloc(sizeof(* recv_d_arg)); recv_d_arg->socketFD=new_socket->socketFD; recv_d_arg->server=server; recv_d_arg->curr_socket=new_socket; int thread_err=pthread_create(&new_socket->thread_id, NULL, recv_data, recv_d_arg); } } } pthread_exit(NULL); } void *cleanup_loop(void *threadarg){ struct Server *server; server=(struct Server *) threadarg; while(server->running){ cleanup_conns(server); sleep(60); } pthread_exit(NULL); } void server_close_socket(struct Server *server){ server->running=false; struct AcceptedSocket *sel_socket_A=server->accepted_socket; while(sel_socket_A!=NULL){ close(sel_socket_A->socketFD); sel_socket_A->shutdown=true; sel_socket_A=sel_socket_A->next; } int shuterr=shutdown(server->socket,SHUT_RDWR); int closeerr=close(server->socket); sleep(2); cleanup_conns(server); printf("\nshutdown with %d : %d\n",shuterr,closeerr); } pthread_t launch_socket(struct Server *server){ int addrlen= sizeof(server->address); printf("running on port: %d\n",server->port); pthread_t id2; int thread_err2=pthread_create(&id2, NULL, cleanup_loop, (void *) server); if (thread_err2!=0){ fprintf(stderr,"ERROR WITH CLEANUP LOOP: %d\n",thread_err2); perror("cleanup loop err"); exit(-1); } pthread_t id; int thread_err=pthread_create(&id, NULL, await_client, (void *) server); if (thread_err!=0){ fprintf(stderr,"ERROR WITH AWAIT CLIENT: %d\n",thread_err); perror("await client error"); exit(-1); } return id; }