Advertisement
Guest User

Untitled

a guest
Jan 7th, 2015
245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.84 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <pthread.h>
  4. #include <fcntl.h>
  5. #include <netdb.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12.  
  13. char buffer[512];
  14. int chatLog_fd = 0;
  15. int max_fd;
  16. int chat_count = 0;
  17. pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
  18. fd_set all_fds;
  19.  
  20. void * chatDaemon(void * fd);
  21. void * consoleDaemon(void * n);
  22. void *get_in_addr(struct sockaddr *sa);
  23. void grabMutex();
  24. void releaseMutex();
  25.  
  26. int main (int argc, char **argv) {
  27.  
  28. struct addrinfo *result,
  29.         hint,
  30.         *pointer;
  31.  
  32. struct sockaddr_storage remoteHost;
  33.  
  34. socklen_t addrlen;
  35.  
  36. int listen_fd,
  37.     value,
  38.     new_fd,
  39.     i;
  40.  
  41. pthread_t chat[100];
  42.  
  43. char remoteIP[INET6_ADDRSTRLEN];
  44.  
  45. memset(&hint, 0, sizeof(hint));
  46.  
  47. hint.ai_family = AF_UNSPEC;
  48. hint.ai_socktype = SOCK_STREAM;
  49. hint.ai_flags = AI_PASSIVE;
  50.  
  51. /**
  52.  * Set-up for receiving addresses
  53.  */
  54.  
  55. if (value = (getaddrinfo(NULL, "2000", &hint, &result)) != 0) {
  56.  
  57.     fprintf(stderr, "Selecting port: %s\n", gai_strerror(value));
  58.     exit(1);
  59. }
  60.  
  61. value = 1;
  62. FD_ZERO(&all_fds); //Zero out the fd containers
  63.  
  64. for (pointer = result; pointer != NULL; pointer = pointer->ai_next) {
  65.  
  66.     listen_fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  67.  
  68.     if (listen_fd < 0)
  69.         continue;
  70.  
  71.     setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
  72.  
  73.     if (bind(listen_fd, pointer->ai_addr, pointer->ai_addrlen) < 0) {
  74.         close(listen_fd);
  75.         continue;
  76.     }
  77.  
  78.     break;
  79. } //Get a suitable port
  80.  
  81. if (pointer == NULL) {
  82.     fprintf(stderr, "Selecting port: %s\n", "Did not bind port");
  83.     exit(-1);
  84. }
  85.  
  86. freeaddrinfo(result); //Get back that memory
  87.  
  88. printf("debug: made it through set-up\n");  
  89. if (listen(listen_fd, 10) == -1) {
  90.  
  91.     perror("listen");
  92.     exit(-1);
  93. } //Check to make sure the listen worked
  94.  
  95. printf("debug: listening on socket: %d\n", listen_fd);
  96.  
  97. FD_SET(listen_fd, &all_fds); //add listen_fd to list
  98. max_fd = listen_fd; //keep track of the number of file descriptors
  99.  
  100. printf("listen_fd on port: %d\n", listen_fd);
  101.  
  102.  
  103. chatLog_fd = open("chatlog.txt", O_CREAT|O_RDWR);
  104.  
  105. while(1) {
  106.  
  107.     if (chat_count <= 10) {
  108.  
  109.         printf("debug: Waiting for new connection\n");
  110.  
  111.         addrlen = sizeof(remoteHost);
  112.         if (new_fd = accept(listen_fd, (struct sockaddr*) &(remoteHost), &addrlen) != -1) {
  113.  
  114.             write(new_fd, "Welcome to the chat server!\n", 28);
  115.  
  116.             printf("debug: accepted new connection\n");
  117.  
  118.             if (new_fd > max_fd)
  119.                 max_fd = new_fd;
  120.  
  121.             if (value = pthread_create((chat+chat_count), NULL, chatDaemon, (void *) &new_fd) != 0) {
  122.  
  123.                 fprintf(stderr, "Thread Creation: %s\n", gai_strerror(value));
  124.                 close(new_fd);
  125.                 free(chat+chat_count);
  126.                 chat_count--;
  127.             }
  128.  
  129.             chat_count++;
  130.  
  131.             printf("New connection from %s on fd: %d\n", inet_ntop(remoteHost.ss_family, get_in_addr((struct sockaddr*) &remoteHost), remoteIP, INET6_ADDRSTRLEN), new_fd);
  132.         }
  133.  
  134.         else {
  135.             perror("accept");
  136.             close(new_fd);
  137.         }
  138.     }
  139.  
  140.     else {
  141.         addrlen = sizeof(remoteHost);
  142.         if (new_fd = accept(listen_fd, (struct sockaddr*) &(remoteHost), &addrlen) != -1) {
  143.             write(new_fd, "Chat server full -- disconnecting", 16);
  144.             close(new_fd);
  145.         }
  146.  
  147.         else {
  148.             perror("accept");
  149.             close(new_fd);
  150.         }
  151.     }
  152. } //END WHILE
  153. } //END MAIN    
  154.  
  155.  
  156. void * chatDaemon(void * fd) {
  157.  
  158. int my_fd = *((int *)fd);
  159. fd_set read_fds;
  160. int i, bytesRead;
  161.  
  162. char *buffer;
  163. buffer = calloc(100, sizeof(char));
  164.  
  165. grabMutex();
  166. FD_SET(my_fd, &all_fds);
  167. releaseMutex();
  168.  
  169. for(;;) {
  170.  
  171.     if (bytesRead = recv(my_fd, buffer, 512, 0) <= 0) {
  172.  
  173.         if (bytesRead == 0) {
  174.  
  175.             printf("Socket %d disconnected\n", my_fd);
  176.         }
  177.  
  178.         else {
  179.             perror("recv");
  180.  
  181.             grabMutex();
  182.             close(my_fd);
  183.             FD_CLR(my_fd, &all_fds);
  184.             releaseMutex();
  185.  
  186.             pthread_exit(NULL);
  187.         }
  188.     }
  189.  
  190.     if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1) {
  191.         perror("select");
  192.         exit(EXIT_FAILURE);
  193.     }
  194.  
  195.     grabMutex();
  196.     for (i = 0; i <= max_fd; i++) {
  197.  
  198.         if (FD_ISSET(i, &read_fds)) {
  199.  
  200.             if (send(i, buffer, bytesRead, 0) == -1) {
  201.  
  202.                 perror("send");
  203.             }
  204.         }      
  205.     }
  206.  
  207.     write(chatLog_fd, buffer, bytesRead);
  208.     releaseMutex();
  209.  
  210.     write(1, buffer, bytesRead);
  211. }
  212. }
  213. void *get_in_addr(struct sockaddr *sa) {
  214.  
  215. if (sa->sa_family == AF_INET)
  216.     return &(((struct sockaddr_in*)sa)->sin_addr);
  217.  
  218. return &(((struct sockaddr_in6*)sa)->sin6_addr);
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement