Выбрать главу

■ Функция module_close() закрывает совместно используемую библиотеку, соответствующую указанному модулю, и удаляет объект module.

В файле module.c определена также глобальная переменная module_dir. В ней записано имя каталога, в котором функция module_open() будет искать совместно используемые библиотеки.

11.2.3. Сервер

Файл server.c (листинг 11.4) представляет собой реализацию простейшего HTTP-сервера.

Листинг 11.4. (server.c) Реализация HTTP-сервера

#include <arpa/inet.h>

#include <assert.h>

#include <errno.h>

#include <netinet/in.h>

#include <signal.h>

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/wait.h>

#include <unistd.h>

#include "server.h"

/* HTTP-ответ и заголовок, возвращаемые в случае

   успешной обработки запроса. */

static char* ok_response =

 "HTTP/1.0 100 OK\n"

 "Content-type: text/html\n"

 "\n";

/* HTTP-ответ, заголовок и тело страницы на случай

   непонятного запроса. */

static char* bad_request_response =

 "HTTP/1.0 400 Bad Reguest\n"

 "Content-type: text/html\n"

 "\n"

 "<html>\n"

 " <body>\n"

 "  <h1>Bad Request</h1>\n"

 "  <p>This server did not understand your request.</p>\n"

 " </body>\n"

 "</html>\n";

/* HTTP-ответ, заголовок и шаблон страницы на случай,

   когда запрашиваемый документ не найден. */

static char* not_found_response_template =

 "HTTP/1.0 404 Not Found\n"

 "Content-type: text/html\n"

 "\n"

 "<html>\n"

 " <body>\n"

 "  <h1>Not Found</h1>\n"

 "  <p>The requested URL %s was not found on this server.</p>\n"

 " </body>\n"

 "</html>\n";

/* HTTP-ответ, заголовок к шаблон страницы на случай,

   когда запрашивается непонятный метод */

static char* bad_method_response_template =

 "HTTP/1.0 501 Method Not Implemented\n"

 "Content-type: text/html\n"

 "\n"

 "<html>\n"

 " <body>\n"

 "  <h1>Method Not Implemented</h1>\n"

 "  <p>The method %s is not implemented by this server.</p>\n"

 " </body>\n"

 "</html>\n";

/* Обработчик сигнала SIGCHLD, удаляющий завершившиеся

   дочерние процессы. */

static void clean_up_child_process(int signal_number) {

 int status;

 wait(&status);

}

/* Обработка HTTP-запроса "GET" к странице PAGE и

   запись результата в файл с дескриптором CONNECTION_FD. */

static void handle_get(int connection_fd, const char* page) {

 struct server_module* module = NULL;

 /* Убеждаемся, что имя страницы начинается с косой черты и

    не содержит других символов косой черты, так как

    подкаталоги не поддерживаются. */

 if (*page == '/' && strchr(page + 1, '/') == NULL) {

  char module_file_name[64];

  /* Имя страницы правильно. Формируем имя модуля, добавляя

     расширение ".so" к имени страницы. */

  snprintf(module_file_name, sizeof(module_file_name),

   "%s.so", page + 1);

  /* Попытка открытия модуля. */

  module = module_open(module_file_name);

 }

 if (module == NULL) {

  /* Имя страницы неправильно сформировано или не удалось

     открыть модуль с указанным именем. В любом случае

     возвращается HTTP-ответ "404. Not Found". */

  char response[1024];

  /* Формирование ответного сообщения. */

  snprintf(response, sizeof(response),

   not_found_response_template, page);

  /* Отправка его клиенту. */

  write(connection_fd, response, strlen(response));

 } else {

  /* Запрашиваемый модуль успешно загружен. */

  /* Выдача HTTP-ответа, обозначающего успешную обработку

     запроса, и HTTP-заголовка для HTML-страницы. */

  write(connection_fd, ok_response, strlen(ok_response));

  /* Вызов модуля, генерирующего HTML-код страницы и