void ServerFreeSafe(struct server* st_server) { struct client* st_client; struct file* st_file; assert(!st_server->listening); /* Free memory related to the clients. */ if(st_server->st_clients != NULL) { for(int i = 0; i < st_server->st_clients->current; i++) { st_client = (struct client*)VectorGetPointer(st_server->st_clients, i); if(ClientClose(st_client) == FAILED) printf("Could not gracefully terminate client %s:%d\n", st_client->ip, st_client->port); ClientDelete(st_client); } VectorFree(st_server->st_clients); } /* Free memory related to the clients. */ if(st_server->st_files != NULL) { for(int i = 0; i < st_server->st_files->current; i++) { st_file = (struct file*)VectorGetPointer(st_server->st_files, i); ServerDeleteFile(st_server, st_file->descriptor); } VectorFree(st_server->st_files); } }
static void _Terminate(Client* client, int code) { Selector* selector = client->selector; ClientDelete(client); if (selector) SelectorDestroy(selector); exit(code); }
int ServerListen(struct server* st_server) { int32_t client_socket = -1; socklen_t client_addlen = sizeof(socklen_t); struct sockaddr client_addr; struct client* st_newclient; printf("Starting the server...\n"); /* Allocate the clients list. */ st_server->st_clients = VectorAllocate(100); if(st_server->st_clients == NULL) { SetError(STATUS_ERR_NOMEM); /* TODO: write an error message. */ return FAILED; } /* Allocate the files list. */ st_server->st_files = VectorAllocate(10); if(st_server->st_files == NULL) { SetError(STATUS_ERR_NOMEM); /* TODO: write an error message. */ return FAILED; } /* Loop indefinitely in order to establish a connection with clients. */ st_server->listening = TRUE; while(st_server->listening) { st_newclient = NULL; /* Wait for a client to connect. */ client_socket = accept(st_server->socket, &client_addr, &client_addlen); if(client_socket < 0) { /* If a bad file descriptor happens, it means the server was terminated. */ if(errno == EBADF) break; else goto ERROR; } /* Allocate the memory for the structure. */ st_newclient = ClientNew(st_server, client_socket, (struct sockaddr_in*)&client_addr); if(st_newclient == NULL) goto ERROR; /* Add the client into the list. */ if(VectorPushPointer(st_server->st_clients, st_newclient) == FAILED) { /* TODO: write an error message. */ goto ERROR; } /* Start listening to commands from the client. */ ClientListen(st_newclient); } return SUCCESS; ERROR: printf("An error happened.\n"); printf("Terminating the server...\n"); st_server->listening = FALSE; if(st_newclient != NULL) ClientDelete(st_newclient); ServerFreeSafe(st_server); return FAILED; }