/ml_server/src/server.c

https://bitbucket.org/mokonzi131/gos_project_1 · C · 178 lines · 134 code · 27 blank · 17 comment · 23 complexity · eb2feafa5a6fde07b63423cb298a2915 MD5 · raw file

  1. // Michael Landes
  2. // GaTech : GOS : Project 1
  3. ///////////////////////////
  4. #include "globals.h"
  5. #include "server.h"
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <assert.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <arpa/inet.h>
  14. #include <unistd.h>
  15. #include <sys/stat.h>
  16. #include <pthread.h>
  17. #include "worker.h"
  18. #include "safeq.h"
  19. /* DATA */
  20. const unsigned short int ml_DEFAULT_PORT_NUMBER = 51115;
  21. const unsigned short int ml_PORT_MAX = 65535;
  22. const unsigned int ml_DEFAULT_WORKERS_NUMBER = 5;
  23. const unsigned int ml_WORKERS_MAX = 50;
  24. static const unsigned int BACKLOG = 20;
  25. static char* rootDirectory;
  26. static int hServerSocket;
  27. static struct sockaddr_in ServerAddress;
  28. static unsigned int workers;
  29. static pthread_t* workerPool;
  30. static int* workerArgs;
  31. /* PRIVATE INTERFACE */
  32. static int initialize(unsigned short int, const char*, unsigned int);
  33. static int run(void);
  34. /* PUBLIC INTERFACE */
  35. int ml_server(unsigned short int port, const char* root, unsigned int workers)
  36. {
  37. int result;
  38. result = initialize(port, root, workers);
  39. switch(result)
  40. {
  41. case (SUCCESS):
  42. break;
  43. default:
  44. printf("ERROR: Could not initialize the server\n");
  45. return result;
  46. }
  47. result = run();
  48. switch(result)
  49. {
  50. case (SUCCESS):
  51. break;
  52. default:
  53. printf("ERROR: Server is down\n");
  54. return result;
  55. }
  56. return result;
  57. }
  58. char* ml_server_getRootDir()
  59. {
  60. return rootDirectory;
  61. }
  62. /* IMPLEMENTATION */
  63. static int initialize(unsigned short int port, const char* root, unsigned int _workers)
  64. {
  65. int nAddressSize = sizeof(struct sockaddr_in);
  66. int i;
  67. struct stat rootstat;
  68. printf("INITIALIZING Server...\n");
  69. // setup the port
  70. port = (port == 0 ? ml_DEFAULT_PORT_NUMBER : port);
  71. assert(port > 0 && port <= ml_PORT_MAX);
  72. // setup the root directory
  73. rootDirectory = (char*) malloc (sizeof(char) * strlen((root == NULL) ? "." : root) + 1);
  74. strcpy(rootDirectory, (root == NULL) ? "." : root);
  75. if (rootDirectory[strlen(rootDirectory)-1] == '/') rootDirectory[strlen(rootDirectory)-1] = '\0';
  76. if (stat(rootDirectory, &rootstat) < 0)
  77. {
  78. printf("ERROR: (%s) does not exist\n", rootDirectory);
  79. return (CHECK_DIR_ERROR);
  80. }
  81. if (!S_ISDIR(rootstat.st_mode))
  82. {
  83. printf("ERROR: (%s) exists, but isn't a directory\n", rootDirectory);
  84. return (CHECK_DIR_ERROR);
  85. }
  86. // initialize socket
  87. hServerSocket = socket(AF_INET, SOCK_STREAM, 0);
  88. if (hServerSocket == SOCKET_ERROR)
  89. {
  90. printf("ERROR: Failed to create socket\n");
  91. return (INIT_SERVER_ERROR);
  92. }
  93. // setup socket structure
  94. ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  95. ServerAddress.sin_port = htons(port);
  96. ServerAddress.sin_family = AF_INET;
  97. // bind to a port
  98. if (bind(hServerSocket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress)) == SOCKET_ERROR)
  99. {
  100. printf("ERROR: Failed to bind socket to port\n");
  101. return (INIT_SERVER_ERROR);
  102. }
  103. // establish a listen queue
  104. if (listen(hServerSocket, BACKLOG) == SOCKET_ERROR)
  105. {
  106. printf("ERROR: Server failed to listen\n");
  107. return (INIT_SERVER_ERROR);
  108. }
  109. // establish safeq (for passing connections to workers)
  110. if (ml_safeq_initialize())
  111. {
  112. printf("ERROR: Safeq failed to initialize\n");
  113. return (INIT_SERVER_ERROR);
  114. }
  115. // create and launch worker threads
  116. workers = (_workers == 0 ? ml_DEFAULT_WORKERS_NUMBER : _workers);
  117. assert(workers > 0 && workers <= ml_WORKERS_MAX);
  118. workerPool = (pthread_t*) malloc (workers * sizeof(pthread_t));
  119. workerArgs = (int*) malloc (workers * sizeof(int));
  120. for (i = 0; i < workers; ++i)
  121. {
  122. workerArgs[i] = i;
  123. if ((pthread_create(&workerPool[i], NULL, ml_worker, (void*)&workerArgs[i])) != SUCCESS)
  124. {
  125. printf("ERROR: Failed to create thread (%d)", i);
  126. return (INIT_SERVER_ERROR);
  127. }
  128. }
  129. // report setup results
  130. getsockname(hServerSocket, (struct sockaddr*)&ServerAddress, (socklen_t*)&nAddressSize);
  131. printf(" server_ip = %s\n", inet_ntoa(ServerAddress.sin_addr));
  132. printf(" port = %d\n", ntohs(ServerAddress.sin_port));
  133. printf(" directory = %s\n", rootDirectory);
  134. printf(" workers = %d\n", workers);
  135. printf("\n");
  136. return (SUCCESS);
  137. }
  138. static int run(void)
  139. {
  140. int hSocket;
  141. static struct sockaddr_in ClientAddress;
  142. int nAddressSize = sizeof(struct sockaddr_in);
  143. printf("RUNNING Server...\n");
  144. while(1)
  145. {
  146. hSocket = accept(hServerSocket, (struct sockaddr*)&ClientAddress, (socklen_t*)&nAddressSize);
  147. //printf("(socket %d) <- New connection from (machine %s) on (port %d)\n", hSocket, inet_ntoa(ClientAddress.sin_addr), ntohs(ClientAddress.sin_port));
  148. ml_safeq_put(hSocket);
  149. }
  150. return 0;
  151. }