From a926ae205ecb42a603e428346cf99dc1e66ed691 Mon Sep 17 00:00:00 2001 From: iceyrazor Date: Sun, 11 Oct 2026 00:21:32 -0500 Subject: major refactor: Some Thread Safety - removed web. silly to have that in a socket library - made shared changing variables atomic - added mutex locking to some things - removed requirement for iceys-c-libs (that was a web thing) - removed launch variable - check if on_message is actually defined - init on_message and on_disconnect NULL --- README.md | 4 +- Server.c | 6 +- Server.h | 18 ++-- launch-socket.c | 279 ++++++++++++++++++++++++++++++-------------------------- launch-socket.h | 6 +- launch-web.c | 101 -------------------- launch-web.h | 15 --- 7 files changed, 167 insertions(+), 262 deletions(-) delete mode 100755 launch-web.c delete mode 100755 launch-web.h diff --git a/README.md b/README.md index e25d25b..b1696a7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ # socket -my small websocket and webserver libs. - -requires iceys-c-libs a5e1191ad6c34636eb49c0ddaeb9af1bd5c07a2d +my small socket library. diff --git a/Server.c b/Server.c index 3fb55c6..8c3c8c4 100755 --- a/Server.c +++ b/Server.c @@ -4,7 +4,7 @@ #include #include -struct Server server_constructor(int domain, int service, int protocol, ulong interface, int port, int backlog, pthread_t(*launch)(struct Server *server)){ +struct Server server_constructor(int domain, int service, int protocol, ulong interface, int port, int backlog){ struct Server server; server.domain=domain; @@ -37,7 +37,9 @@ struct Server server_constructor(int domain, int service, int protocol, ulong in server.accepted_socket=NULL; - server.launch=launch; + server.on_message=NULL; + server.on_disconnect=NULL; + server.running=true; return server; diff --git a/Server.h b/Server.h index 0a55543..241351a 100755 --- a/Server.h +++ b/Server.h @@ -5,6 +5,7 @@ #include #include #include +#include struct AcceptedSocket{ int socketFD; @@ -12,7 +13,7 @@ struct AcceptedSocket{ int error; bool succ; pthread_t thread_id; - bool shutdown; + atomic_bool shutdown; struct AcceptedSocket *next; }; @@ -24,25 +25,22 @@ struct Server{ u_long interface; int port; int backlog; - bool running; + atomic_bool running; + + pthread_t server_thread_id; + pthread_t cleanup_thread_id; struct sockaddr_in address; int socket; - char *html_folder; + pthread_mutex_t list_lock; struct AcceptedSocket *accepted_socket; - pthread_t (*launch)(struct Server *server); void (*on_message)(struct Server *server, char message[], ssize_t amountRecv, int socketFD); void (*on_disconnect)(struct Server *server, int socketFD); }; -/* - * AF_INET, SOCK_STREAM, 0, INADDR_ANY, port, 10, launch_socket - * or - * AF_INET, SOCK_STREAM, 0, INADDR_ANY, port, 10, launch - */ -struct Server server_constructor(int domain, int service, int protocol, u_long interface, int port, int backlog, pthread_t (*launch)(struct Server *server)); +struct Server server_constructor(int domain, int service, int protocol, u_long interface, int port, int backlog); #endif /* Server_h */ diff --git a/launch-socket.c b/launch-socket.c index 0c2881c..38cd4eb 100755 --- a/launch-socket.c +++ b/launch-socket.c @@ -1,188 +1,209 @@ -#include -#include +#include #include -#include #include -#include -#include -#include #include +#include +#include #include +#include +#include #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{ +struct recv_data_arg { int socketFD; - struct Server *server; - struct AcceptedSocket *curr_socket; + 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; +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); + 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; + if (recv_d_arg->server->running && recv_d_arg->curr_socket->shutdown == false) { + if (amountRecv == 0) + break; - recv_d_arg->server->on_message(recv_d_arg->server, buffer, amountRecv, recv_d_arg->socketFD); + if (recv_d_arg->server->on_message) + recv_d_arg->server->on_message(recv_d_arg->server, buffer, amountRecv, recv_d_arg->socketFD); } } - - - recv_d_arg->curr_socket->shutdown=true; + 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); + 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){ +void cleanup_conns(struct Server* server) +{ + pthread_mutex_lock(&server->list_lock); + 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) { + pthread_join(server->accepted_socket->thread_id,NULL); free(server->accepted_socket); - server->accepted_socket=sel_socket; + server->accepted_socket = sel_socket; } else { + pthread_join(prev2_socket->next->thread_id,NULL); free(prev2_socket->next); - prev2_socket->next=sel_socket; + prev2_socket->next = sel_socket; } } else { - prev2_socket=prev_socket; + prev2_socket = prev_socket; } - prev_socket=sel_socket; + prev_socket = sel_socket; } } + pthread_mutex_unlock(&server->list_lock); } -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 { +void* cleanup_loop(void* threadarg) +{ + struct Server* server; + server = (struct Server*)threadarg; + while (server->running) { + cleanup_conns(server); + for (int i = 0; i < 60 && server->running; i++) { + sleep(1); + } + } + + pthread_exit(NULL); +} + +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); - 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; + 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; - int thread_err=pthread_create(&new_socket->thread_id, NULL, recv_data, recv_d_arg); + 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; } - - pthread_exit(NULL); } -void *cleanup_loop(void *threadarg){ - struct Server *server; - server=(struct Server *) threadarg; - while(server->running){ - cleanup_conns(server); - sleep(60); +void* await_client(void* threadarg) +{ + struct Server* server; + server = (struct Server*)threadarg; + while (server->running) { + 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 = 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); + if (thread_err != 0) { + fprintf(stderr, "ERROR CREATING THREAD FOR CLIENT: %d\n", thread_err); + perror("await client error"); + exit(-1); + } + } + } } 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 server_close_socket(struct Server* server) +{ + server->running = false; + pthread_join(server->cleanup_thread_id, NULL); - int shuterr=shutdown(server->socket,SHUT_RDWR); - int closeerr=close(server->socket); + int shuterr = shutdown(server->socket, SHUT_RDWR); + pthread_join(server->server_thread_id, NULL); + int closeerr = close(server->socket); - sleep(2); cleanup_conns(server); - - printf("\nshutdown with %d : %d\n",shuterr,closeerr); + pthread_mutex_destroy(&server->list_lock); + return shuterr+closeerr; } -pthread_t launch_socket(struct Server *server){ - int addrlen= sizeof(server->address); - - printf("running on port: %d\n",server->port); +int launch_socket(struct Server* server) +{ + pthread_mutex_init(&server->list_lock, NULL); - 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); + int thread_err2 = pthread_create(&server->cleanup_thread_id, 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); + int thread_err = pthread_create(&server->server_thread_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; + return 0; +} + +void broadcast(struct Server* server, int socketFD, char* message){ + pthread_mutex_lock(&server->list_lock); + struct AcceptedSocket* sel_socket = server->accepted_socket; + while (sel_socket != NULL) { + if (sel_socket->shutdown == false && sel_socket->socketFD != socketFD) { + send(sel_socket->socketFD, message, 30000, 0); + } + sel_socket = sel_socket->next; + } + pthread_mutex_unlock(&server->list_lock); } \ No newline at end of file diff --git a/launch-socket.h b/launch-socket.h index 0f87b5d..2e10b04 100755 --- a/launch-socket.h +++ b/launch-socket.h @@ -11,7 +11,9 @@ #include #include -void server_close_socket(struct Server *server); +int server_close_socket(struct Server *server); -pthread_t launch_socket(struct Server *server); +int launch_socket(struct Server *server); + +void broadcast(struct Server *server, int socketFD, char* message); #endif diff --git a/launch-web.c b/launch-web.c deleted file mode 100755 index ff2970b..0000000 --- a/launch-web.c +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -void server_close(struct Server *server){ - server->running=false; - - sleep(1); - - int shuterr=shutdown(server->socket,SHUT_RDWR); - int closeerr=close(server->socket); - - printf("\nshutdown with %d : %d\n",shuterr,closeerr); - //free(server); -} - -void *server_loop(void *threadarg){ - struct Server *server; - server=(struct Server *) threadarg; - - char buffer[30000]={0}; - int addrlen= sizeof(server->address); - - int new_socket; - char *meta_type="\r\ncontent-type: text/html\r\n\r\n"; - - printf("running on port: %d",server->port); - - while (server->running){ - char metadata[100]=""; - - printf("\n=== WAITING FOR CONNECTION ===\n\n"); - new_socket = accept(server->socket, (struct sockaddr *)&server->address, (socklen_t *)&addrlen); - - if(new_socket<0){ break; } - - if(read(new_socket,buffer,29999)<0){ printf("\nREAD FAILED\n\n"); close(new_socket); break; } - buffer[29999]='\0'; - - printf("%s\n",buffer); - - char response[30000] = {0}; - - - char file_req_buf[1000]={0}; - strcpy(file_req_buf,server->html_folder); - char file_req[1000]={0}; - str_before_nth(buffer+5, file_req, ' ', 0); - strcat(file_req_buf,file_req); - - - printf("file req: %s====\n",file_req_buf); - - - if(strncmp(file_req, "", 1) == 0){ - strcat(file_req_buf,"index.html"); - } - - char file_req_buf2[1000]={0}; - strcpy(file_req_buf2,str_remove_all(file_req_buf,"..")); - printf("file ret: %s====\n",file_req_buf); - - - if (access(file_req_buf, F_OK) == 0) { - char *status="HTTP/1.0 200 OK"; - memcpy(metadata,status,strlen(status)); - memcpy(metadata+strlen(metadata),meta_type,strlen(meta_type)); - memcpy(response, metadata, strlen(metadata)); - FILE* file=fopen(file_req_buf, "r"); - fread(response + strlen(metadata), 30000 - strlen(metadata) - 1, 1, file); - fclose(file); - } else { - char *status="HTTP/1.0 404 Not Found"; - memcpy(metadata,status,strlen(status)); - memcpy(metadata+strlen(metadata),meta_type,strlen(meta_type)); - memcpy(response, metadata, strlen(metadata)); - char* error = "error 404 file not found"; - memcpy(response + strlen(metadata), error, strlen(error)); - } - - printf("\n\n==response==\n%s\n",response); - - write(new_socket, response, strlen(response)); - close(new_socket); - } - - pthread_exit(NULL); -} - -pthread_t launch(struct Server *server){ - //HTTP/1.0 200 OK - - pthread_t id; - int thread_err=pthread_create(&id, NULL, server_loop, (void *) server); - return id; -} diff --git a/launch-web.h b/launch-web.h deleted file mode 100755 index 0a25288..0000000 --- a/launch-web.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef launch_web_h -#define launch_web_h -#include -#include -#include -#include -#include -#include -#include -#include - -void server_close(struct Server *server); - -pthread_t launch(struct Server *server); -#endif -- cgit v1.3