diff --git a/Assignment-06/starter/rsh_server.c b/Assignment-06/starter/rsh_server.c index 23042576d4b3cdbe8b591f2fd386329f20a1a609..013d9ca58f7b45de90cf98963d3395bd11126bb7 100644 --- a/Assignment-06/starter/rsh_server.c +++ b/Assignment-06/starter/rsh_server.c @@ -206,12 +206,9 @@ int boot_server(char *ifaces, int port){ * connections, and negative values terminate the server. * */ - int process_cli_requests(int svr_socket) { int cli_socket; - char buffer[RDSH_COMM_BUFF_SZ]; - ssize_t bytes_received; - int rc = OK; + pthread_t thread_id; printf("SERVER: Waiting for client connections...\n"); @@ -220,55 +217,23 @@ int process_cli_requests(int svr_socket) { cli_socket = accept(svr_socket, NULL, NULL); if (cli_socket == -1) { perror("SERVER: accept failed"); - rc = ERR_RDSH_COMMUNICATION; - break; - } - printf("SERVER: Client connected. Socket: %d\n", cli_socket); - - bytes_received = recv(cli_socket, buffer, sizeof(buffer), 0); - if (bytes_received < 0) { - perror("SERVER: recv failed"); - close(cli_socket); - rc = ERR_RDSH_COMMUNICATION; - break; - } else if (bytes_received == 0) { - // Client disconnected - printf("SERVER: Client disconnected.\n"); - close(cli_socket); - continue; + return ERR_RDSH_COMMUNICATION; } - // Null-terminate the received data - buffer[bytes_received] = '\0'; - printf("SERVER: Received %zd bytes: %s\n", bytes_received, buffer); - - - // Check for special commands - if (strncmp(buffer, "stop-server", strlen("stop-server")) == 0) { - printf("SERVER: Client requested server to stop.\n"); - rc = OK_EXIT; - close(cli_socket); - break; - } + printf("SERVER: Client connected. Socket: %d\n", cli_socket); - // Handle client requests - printf("SERVER: Executing client request...\n"); - rc = exec_client_requests(cli_socket); - if (rc < 0) { - fprintf(stderr, "SERVER: Error processing client requests: %d\n", rc); + // Create a new thread to handle the client + if (pthread_create(&thread_id, NULL, exec_client_requests, (void *)&cli_socket) < 0) { + perror("SERVER: Failed to create thread"); close(cli_socket); - break; + return ERR_RDSH_COMMUNICATION; } - // Close the client socket - close(cli_socket); - printf("SERVER: Client socket closed properly.\n"); + // Detach the thread to allow it to clean up automatically + pthread_detach(thread_id); } - // Clean up and stop the server - printf("SERVER: Stopping server...\n"); - stop_server(svr_socket); - return rc; + return OK; } /* @@ -313,31 +278,33 @@ int process_cli_requests(int svr_socket) { * or receive errors. */ -int exec_client_requests(int cli_socket) { + void *exec_client_requests(void *socket_handle) { + int cli_socket = *((int *)socket_handle); char cmd_buff[RDSH_COMM_BUFF_SZ]; ssize_t recv_bytes; int rc = OK; - printf("Waiting for client command...\n"); + printf("SERVER: New client connected. Socket: %d\n", cli_socket); // Receive the command from the client - recv_bytes = recv(cli_socket, cmd_buff, RDSH_COMM_BUFF_SZ, 0); + recv_bytes = recv(cli_socket, cmd_buff, sizeof(cmd_buff), 0); if (recv_bytes <= 0) { - perror("recv"); + perror("SERVER: recv failed"); close(cli_socket); - return ERR_RDSH_COMMUNICATION; + pthread_exit(NULL); } cmd_buff[recv_bytes] = '\0'; - printf("Received command: %s\n", cmd_buff); + printf("SERVER: Received command: %s\n", cmd_buff); // Execute the command if (strstr(cmd_buff, "|") != NULL) { // Handle pipeline commands command_list_t cmd_list; if (parse_pipeline(cmd_buff, &cmd_list) != OK) { - fprintf(stderr, "Error parsing pipeline\n"); - return ERR_TOO_MANY_COMMANDS; + fprintf(stderr, "SERVER: Error parsing pipeline\n"); + close(cli_socket); + pthread_exit(NULL); } rc = rsh_execute_pipeline(cli_socket, &cmd_list); @@ -349,40 +316,44 @@ int exec_client_requests(int cli_socket) { // Handle single commands cmd_buff_t cmd; if (build_cmd_buff(cmd_buff, &cmd) != OK) { - fprintf(stderr, "Error building command buffer\n"); - return ERR_MEMORY; + fprintf(stderr, "SERVER: Error building command buffer\n"); + close(cli_socket); + pthread_exit(NULL); } if (strcmp(cmd.argv[0], EXIT_CMD) == 0) { + printf("SERVER: Client requested exit.\n"); free(cmd._cmd_buffer); - printf("Client requested exit\n"); - return OK; + close(cli_socket); + pthread_exit(NULL); } else if (strcmp(cmd.argv[0], "cd") == 0) { // Handle cd command if (cmd.argc == 1) { chdir(getenv("HOME")); } else if (cmd.argc == 2) { if (chdir(cmd.argv[1]) != 0) { - perror("cd"); + perror("SERVER: cd failed"); } } else { - fprintf(stderr, "cd: too many arguments\n"); + fprintf(stderr, "SERVER: cd: too many arguments\n"); } free(cmd._cmd_buffer); - return OK; + close(cli_socket); + pthread_exit(NULL); } // Fork and execute the command pid_t pid = fork(); if (pid < 0) { - perror("fork failed"); - return ERR_MEMORY; + perror("SERVER: fork failed"); + close(cli_socket); + pthread_exit(NULL); } else if (pid == 0) { // Child process: execute the command dup2(cli_socket, STDOUT_FILENO); // Redirect stdout to client socket dup2(cli_socket, STDERR_FILENO); // Redirect stderr to client socket execvp(cmd.argv[0], cmd.argv); - perror("execvp failed"); + perror("SERVER: execvp failed"); exit(EXIT_FAILURE); } else { // Parent process: wait for the child to finish @@ -390,9 +361,7 @@ int exec_client_requests(int cli_socket) { wait(&status); if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) { - fprintf(stderr, "Command failed with exit code %d\n", WEXITSTATUS(status)); - } + printf("SERVER: Command executed with exit code: %d\n", WEXITSTATUS(status)); } } @@ -402,14 +371,16 @@ int exec_client_requests(int cli_socket) { // Send EOF to indicate end of response send_message_eof(cli_socket); - printf("Command executed successfully\n"); - return rc; + printf("SERVER: Client socket closed properly.\n"); + close(cli_socket); + pthread_exit(NULL); } + /* * send_message_eof(cli_socket) * cli_socket: The server-side socket that is connected to the client