Advertisement
Guest User

client.c

a guest
Apr 8th, 2020
391
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.40 KB | None | 0 0
  1. /**
  2.  * Charming Chatroom
  3.  * CS 241 - Spring 2020
  4.  */
  5.  
  6. #include <errno.h>
  7. #include <netdb.h>
  8. #include <pthread.h>
  9. #include <signal.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <sys/socket.h>
  14. #include <sys/types.h>
  15. #include <unistd.h>
  16.  
  17. #include "chat_window.h"
  18. #include "utils.h"
  19.  
  20. static volatile int serverSocket;
  21. static pthread_t threads[2];
  22.  
  23. void *write_to_server(void *arg);
  24. void *read_from_server(void *arg);
  25. void close_program(int signal);
  26.  
  27. /**
  28.  * Shuts down connection with 'serverSocket'.
  29.  * Called by close_program upon SIGINT.
  30.  */
  31. void close_server_connection() {
  32.     // Your code here
  33.  
  34.     // close sockets
  35.     // int shut = shutdown(serverSocket, SHUT_RDWR);
  36.     // if (shut == -1) {
  37.     //     perror("shutdown failed \n");
  38.     // }
  39.  
  40.     // int closed = close(serverSocket);
  41.     // if (closed == -1) {
  42.     //     perror("close failed \n");
  43.     // }
  44.  
  45.     // // free memory
  46.     // pthread_cancel(threads[0]);
  47.     // pthread_cancel(threads[1]);
  48.  
  49.     // exit program
  50.  
  51.     destroy_windows();
  52.     close(serverSocket);
  53. }
  54.  
  55. /**
  56.  * Sets up a connection to a chatroom server and returns
  57.  * the file descriptor associated with the connection.
  58.  *
  59.  * host - Server to connect to.
  60.  * port - Port to connect to server on.
  61.  *
  62.  * Returns integer of valid file descriptor, or exit(1) on failure.
  63.  */
  64. // sources: CS 241 Coursebook Ch 11 and Lectures 25-26
  65.  
  66. static struct addrinfo hints;
  67. static struct addrinfo*res;
  68. int connect_to_server(const char *host, const char *port) {
  69.     /*QUESTION 1*/
  70.     /*QUESTION 2*/
  71.     /*QUESTION 3*/
  72.  
  73.     /*QUESTION 4*/
  74.     /*QUESTION 5*/
  75.  
  76.     /*QUESTION 6*/
  77.  
  78.     /*QUESTION 7*/
  79.    
  80.     //memset(&hints, 0, sizeof(hints));
  81.     hints.ai_family = AF_INET; // IPv4
  82.     hints.ai_socktype = SOCK_STREAM; // TCP
  83.     hints.ai_flags = AI_PASSIVE;
  84.  
  85.     int get_addr_result = getaddrinfo(host, port, &hints, &res);
  86.     if (get_addr_result != 0) {
  87.        
  88.         fprintf(stderr, "%s\n", gai_strerror(get_addr_result)); // print out the message?
  89.         exit(1);
  90.     }
  91.  
  92.     serverSocket = socket(AF_INET, SOCK_STREAM, 0);
  93.     if (serverSocket == -1) {
  94.         perror("failed to create socket\n");
  95.         exit(1);
  96.     }
  97.  
  98.     int connect_res = connect(serverSocket, res->ai_addr, res->ai_addrlen);
  99.     if (connect_res == -1) {
  100.         perror("failed to connect socket to port\n");
  101.         exit(1);
  102.     }
  103.  
  104.     // NOTE: this stuff already done in main??
  105.  
  106.     /* launch threads to read and write to/from server?
  107.     for (int i = 0; i < 2; i++) {
  108.         pthread_create(&threads, NULL, (void*)&read_from_server, NULL);
  109.         pthread_create(&threads, NULL, (void*)&write_from_server, NULL);
  110.     }
  111.  
  112.     // just join the threads afterwards?
  113.     for (int i = 0; i < 2; i++) {
  114.         pthread_join(&threads, NULL);
  115.     }*/
  116.     freeaddrinfo(res);
  117.     res = NULL;
  118.     return serverSocket; // is this right file descriptor to return?
  119. }
  120.  
  121. typedef struct _thread_cancel_args {
  122.     char **buffer;
  123.     char **msg;
  124. } thread_cancel_args;
  125.  
  126. /**
  127.  * Cleanup routine in case the thread gets cancelled.
  128.  * Ensure buffers are freed if they point to valid memory.
  129.  */
  130. void thread_cancellation_handler(void *arg) {
  131.     printf("Cancellation handler\n");
  132.     thread_cancel_args *a = (thread_cancel_args *)arg;
  133.     char **msg = a->msg;
  134.     char **buffer = a->buffer;
  135.     if (*buffer) {
  136.         free(*buffer);
  137.         *buffer = NULL;
  138.     }
  139.     if (msg && *msg) {
  140.         free(*msg);
  141.         *msg = NULL;
  142.     }
  143. }
  144.  
  145. /**
  146.  * Reads bytes from user and writes them to server.
  147.  *
  148.  * arg - void* casting of char* that is the username of client.
  149.  */
  150. void *write_to_server(void *arg) {
  151.     char *name = (char *)arg;
  152.     char *buffer = NULL;
  153.     char *msg = NULL;
  154.     ssize_t retval = 1;
  155.  
  156.     thread_cancel_args cancel_args;
  157.     cancel_args.buffer = &buffer;
  158.     cancel_args.msg = &msg;
  159.     // Setup thread cancellation handlers.
  160.     // Read up on pthread_cancel, thread cancellation states,
  161.     // pthread_cleanup_push for more!
  162.     pthread_cleanup_push(thread_cancellation_handler, &cancel_args);
  163.  
  164.     while (retval > 0) {
  165.         read_message_from_screen(&buffer);
  166.         if (buffer == NULL)
  167.             break;
  168.  
  169.         msg = create_message(name, buffer);
  170.         size_t len = strlen(msg) + 1;
  171.  
  172.         retval = write_message_size(len, serverSocket);
  173.         if (retval > 0)
  174.             retval = write_all_to_socket(serverSocket, msg, len);
  175.  
  176.         free(msg);
  177.         msg = NULL;
  178.     }
  179.  
  180.     pthread_cleanup_pop(0);
  181.     return 0;
  182. }
  183.  
  184. /**
  185.  * Reads bytes from the server and prints them to the user.
  186.  *
  187.  * arg - void* requriment for pthread_create function.
  188.  */
  189. void *read_from_server(void *arg) {
  190.     // Silence the unused parameter warning.
  191.     (void)arg;
  192.     ssize_t retval = 1;
  193.     char *buffer = NULL;
  194.     thread_cancel_args cancellation_args;
  195.     cancellation_args.buffer = &buffer;
  196.     cancellation_args.msg = NULL;
  197.     pthread_cleanup_push(thread_cancellation_handler, &cancellation_args);
  198.  
  199.     while (retval > 0) {
  200.         retval = get_message_size(serverSocket);
  201.         if (retval > 0) {
  202.             buffer = calloc(1, retval);
  203.             retval = read_all_from_socket(serverSocket, buffer, retval);
  204.         }
  205.         if (retval > 0)
  206.             write_message_to_screen("%s\n", buffer);
  207.  
  208.         free(buffer);
  209.         buffer = NULL;
  210.     }
  211.  
  212.     pthread_cleanup_pop(0);
  213.     return 0;
  214. }
  215.  
  216. /**
  217.  * Signal handler used to close this client program.
  218.  */
  219. void close_program(int signal) {
  220.     if (signal == SIGINT) {
  221.         pthread_cancel(threads[0]);
  222.         pthread_cancel(threads[1]);
  223.         close_chat();
  224.         close_server_connection();
  225.     }
  226. }
  227.  
  228. int main(int argc, char **argv) {
  229.     if (argc < 4 || argc > 5) {
  230.         fprintf(stderr, "Usage: %s <address> <port> <username> [output_file]\n",
  231.                 argv[0]);
  232.         exit(1);
  233.     }
  234.  
  235.     char *output_filename;
  236.     if (argc == 5) {
  237.         output_filename = argv[4];
  238.     } else {
  239.         output_filename = NULL;
  240.     }
  241.  
  242.     // Setup signal handler.
  243.     signal(SIGINT, close_program);
  244.     create_windows(output_filename);
  245.     atexit(destroy_windows);
  246.  
  247.     serverSocket = connect_to_server(argv[1], argv[2]);
  248.  
  249.     pthread_create(&threads[0], NULL, write_to_server, (void *)argv[3]);
  250.     pthread_create(&threads[1], NULL, read_from_server, NULL);
  251.  
  252.     pthread_join(threads[0], NULL);
  253.     pthread_join(threads[1], NULL);
  254.  
  255.     return 0;
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement