Advertisement
SirNickolas

OS 7 server.c

Nov 28th, 2014
547
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.64 KB | None | 0 0
  1. /*
  2.     Сервер, адаптированный под задание седьмой лаборатораторной работы.
  3.     Добавлены команды delay (префиксная) и calc.
  4.     За счет параллельной обработки запросов способен обслуживать нескольких клиентов одновременно.
  5.  
  6.     ЮБ сказал: увидит еще один многопоточный сервер - будет знать, что списали.
  7.     Так что если не уверены в своих силах, берите более примитивную версию сервера.
  8. */
  9.  
  10. #include <errno.h>
  11. #include <pthread.h>
  12. #include <stdbool.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #include <sys/iomsg.h>
  18. #include <sys/neutrino.h>
  19. #include "httpd_pid.h"
  20.  
  21. const char HELP_MESSAGE[ ] = "\
  22. OS Lab 5 Server v1.2\n\
  23. \n\
  24. Available commands:\n\
  25.  help\n\
  26.  ls\n\
  27.  cat\n\
  28.  cp\n\
  29.  rm\n\
  30.  echo\n\
  31.  delay\n\
  32.  calc\n\
  33. ";
  34.  
  35. const char ERROR_MESSAGE[ ] = "Invalid command; use 'help' for more information\n"
  36.  
  37. const size_t BUFFER_SIZE   = 65535;
  38. const size_t RESPONSE_SIZE = 65535;
  39.  
  40. enum {
  41.     CMD_ERROR,
  42.     CMD_SHELL,
  43.     CMD_HELP,
  44.     CMD_ECHO,
  45.     CMD_DELAY,
  46.     CMD_CALC,
  47. };
  48.  
  49. short CheckCommand(const char cmd[ ]) {
  50.     switch (cmd[0]) {
  51.         case 'c': {
  52.             if (cmd[1] == 'a') {
  53.                 if (cmd[2] == 'l') {
  54.                     if (!strncmp(cmd + 3, "c ", 2))
  55.                         return CMD_CALC;
  56.                 } else if (!strncmp(cmd + 2, "t ", 2))
  57.                     return CMD_SHELL;
  58.             } else if (!strncmp(cmd + 1, "p ", 2))
  59.                 return CMD_SHELL;
  60.             break;
  61.         }
  62.  
  63.         case 'd': {
  64.             if (!strncmp(cmd + 1, "elay ", 5))
  65.                 return CMD_DELAY;
  66.             break;
  67.         }
  68.  
  69.         case 'e': {
  70.             if (!strncmp(cmd + 1, "cho ", 4))
  71.                 return CMD_ECHO;
  72.             break;
  73.         }
  74.  
  75.         case 'h': {
  76.             if (!strcmp(cmd + 1, "elp"))
  77.                 return CMD_HELP;
  78.             break;
  79.         }
  80.  
  81.         case 'l': {
  82.             if (cmd[1] == 's' && (cmd[2] == ' ' || !cmd[2]))
  83.                 return CMD_SHELL;
  84.             break;
  85.         }
  86.  
  87.         case 'r': {
  88.             if (!strncmp(cmd + 1, "m ", 2))
  89.                 return CMD_SHELL;
  90.         }
  91.     }
  92.     return CMD_ERROR;
  93. }
  94.  
  95. void ProcessClient(int clientId, const char _msg[ ], char* buffer, size_t maxLength) {
  96.     const char* response = buffer;
  97.     size_t responseSize;
  98.     const char* msg = _msg;
  99.     short cmd;
  100.     while ((cmd = CheckCommand(msg)) == CMD_DELAY) {
  101.         double delay;
  102.         int offset;
  103.         msg += 6;
  104.         if (sscanf(msg, "%lf%n", &delay, &offset) != 1) {
  105.             cmd = CMD_ERROR;
  106.             break;
  107.         }
  108.         usleep((useconds_t)(delay * 1e6));
  109.         msg += offset + 1;
  110.     }
  111.     switch (cmd) {
  112.         case CMD_ERROR: {
  113.             response = ERROR_MESSAGE;
  114.             responseSize = sizeof ERROR_MESSAGE;
  115.             break;
  116.         }
  117.  
  118.         case CMD_SHELL: {
  119.             FILE* p = popen(msg, "r");
  120.             responseSize = fread(buffer, sizeof(char), maxLength, p);
  121.             buffer[responseSize / sizeof(char)] = '\0';
  122.             responseSize += sizeof(char);
  123.             pclose(p);
  124.             break;
  125.         }
  126.  
  127.         case CMD_HELP: {
  128.             response = HELP_MESSAGE;
  129.             responseSize = sizeof HELP_MESSAGE;
  130.             break;
  131.         }
  132.  
  133.         case CMD_ECHO: {
  134.             puts(msg + 5);
  135.             *buffer = '\0';
  136.             responseSize = sizeof(char);
  137.             break;
  138.         }
  139.  
  140.         case CMD_CALC: {
  141.             double a, b;
  142.             char op, guard;
  143.             if (sscanf(msg + 5, "%lf %1[-+*/] %lf %c", &a, &op, &b, &guard) == 3) {
  144.                 switch (op) {
  145.                     case '+': { a += b; break; }
  146.                     case '-': { a -= b; break; }
  147.                     case '*': { a *= b; break; }
  148.                     case '/': { a /= b; break; }
  149.                 }
  150.                 if (a == (int)a)
  151.                     responseSize = sprintf(buffer, "%d", (int)a);
  152.                 else
  153.                     responseSize = sprintf(buffer, "%lf", a);
  154.                 responseSize = (responseSize + 1) * sizeof(char);
  155.             } else {
  156.                 response = ERROR_MESSAGE;
  157.                 responseSize = sizeof ERROR_MESSAGE;
  158.             }
  159.         }
  160.     }
  161.     MsgReply(clientId, EOK, response, responseSize);
  162. }
  163.  
  164. typedef struct {
  165.     int clientId;
  166.     char* msg;
  167. } ClientInfo;
  168.  
  169. void* AsyncProcessClient(void* _arg) {
  170.     ClientInfo* arg = (ClientInfo*)_arg;
  171.     char* response = (char*)malloc(RESPONSE_SIZE * sizeof(char));
  172.     ProcessClient(arg->clientId, arg->msg, response, RESPONSE_SIZE);
  173.     free(response);
  174.     free(arg->msg);
  175.     free(arg);
  176.     return NULL;
  177. }
  178.  
  179. int main(void) {
  180.     int channelId = ChannelCreate(0);
  181.     FILE* f = fopen(HTTPD_PID, "w");
  182.     if (!f) {
  183.         fputs("Cannot open \"" HTTPD_PID "\"\n", stderr);
  184.         return 1;
  185.     }
  186.     fprintf(f, "0/%d/%d\n", getpid(), channelId);
  187.     fclose(f);
  188.     fputs(HELP_MESSAGE, stdout);
  189.     while (true) {
  190.         ClientInfo* info = (ClientInfo*)malloc(sizeof(ClientInfo));
  191.         info->msg = (char*)malloc(BUFFER_SIZE * sizeof(char));
  192.         info->clientId = MsgReceive(channelId, info->msg, BUFFER_SIZE * sizeof(char), NULL);
  193.         info->msg = (char*)realloc(info->msg, (strlen(info->msg) + 1) * sizeof(char));
  194.         pthread_create(NULL, NULL, AsyncProcessClient, info);
  195.     }
  196.     return 0;
  197. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement