Ivan Polyakov
2 years ago
18 changed files with 232 additions and 37 deletions
@ -1,11 +1,11 @@
@@ -1,11 +1,11 @@
|
||||
/** |
||||
|
||||
\mainpage Rapida Manual |
||||
\mainpage Manual |
||||
|
||||
Web framework written in C and C++. |
||||
|
||||
Table of contents: |
||||
1. \subpage get_started |
||||
2. \subpage development |
||||
[TOC] |
||||
- \subpage get_started |
||||
- \subpage development |
||||
|
||||
*/ |
||||
|
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later */ |
||||
/* Copyright 2022 Ivan Polyakov */ |
||||
|
||||
/*!
|
||||
* \file tcp.h |
||||
* \brief Rapida TCP server |
||||
*/ |
||||
#ifndef RAPIDA_SERVERS_TCP_H_ENTRY |
||||
#define RAPIDA_SERVERS_TCP_H_ENTRY |
||||
|
||||
#include "../app.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/*!
|
||||
* \brief Starts Rapida TCP server. |
||||
* \param app Application instance. |
||||
* \param addr URL address to listen. |
||||
* |
||||
* \return Status. 0 is success. |
||||
*/ |
||||
int rpd_tcp_server_start(rpd_app *app, const char *addr); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* RAPIDA_SERVERS_TCP_H_ENTRY */ |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later */ |
||||
/* Copyright 2022 Ivan Polyakov */ |
||||
|
||||
#include "servers/tcp.h" |
||||
#include "../c/utils.h" |
||||
#include <mongoose.h> |
||||
#include <signal.h> |
||||
|
||||
/* Handle interrupts, like Ctrl-C */ |
||||
static int s_signo; |
||||
static void signal_handler(int signo) |
||||
{ |
||||
s_signo = signo; |
||||
} |
||||
|
||||
static int mg_str_alloc(char **dest, const struct mg_str str) |
||||
{ |
||||
*dest = (char *) realloc(*dest, sizeof(char) * (str.len + 1)); |
||||
if (!*dest) { |
||||
perror("realloc"); |
||||
return 1; |
||||
} |
||||
memcpy(*dest, str.ptr, str.len); |
||||
(*dest)[str.len] = '\0'; |
||||
return 0; |
||||
} |
||||
|
||||
static int mg_to_rpd_req(rpd_req *req, struct mg_http_message *msg) |
||||
{ |
||||
char *tmp = NULL; |
||||
if (mg_str_alloc(&tmp, msg->method)) |
||||
return 1; |
||||
req->method = rpd_req_smethod(tmp); |
||||
|
||||
req->body = msg->body.len ? rpd_strdup(msg->body.ptr) : NULL; |
||||
|
||||
if (mg_str_alloc(&tmp, msg->uri)) |
||||
return 1; |
||||
rpd_url_parse(&req->path, tmp); |
||||
|
||||
rpd_keyval_init(&req->query, 0); |
||||
if (msg->query.len) { |
||||
if (mg_str_alloc(&tmp, msg->query)) |
||||
return 1; |
||||
rpd_query_parse(&req->query, tmp); |
||||
} |
||||
|
||||
free(tmp); |
||||
return 0; |
||||
} |
||||
|
||||
static void handle_request(struct mg_connection *conn, int ev, void *ev_data, void *app) |
||||
{ |
||||
if (ev == MG_EV_HTTP_MSG) { |
||||
rpd_req *req; |
||||
rpd_res *res; |
||||
char *headers_buff; |
||||
|
||||
req = (rpd_req *) malloc(sizeof(rpd_req)); |
||||
res = (rpd_res *) malloc(sizeof(rpd_res)); |
||||
|
||||
mg_to_rpd_req(req, (struct mg_http_message *) ev_data); |
||||
rpd_res_init(res); |
||||
|
||||
rpd_app_handle_request((rpd_app *) app, req, res); |
||||
rpd_res_headers_str(&headers_buff, res); |
||||
mg_http_reply(conn, res->status, headers_buff, res->body ? res->body : ""); |
||||
|
||||
free(headers_buff); |
||||
rpd_req_cleanup(req); |
||||
rpd_res_cleanup(res); |
||||
free(req); |
||||
free(res); |
||||
} |
||||
} |
||||
|
||||
int rpd_tcp_server_start(rpd_app *app, const char *addr) |
||||
{ |
||||
struct mg_mgr mgr; |
||||
struct mg_connection *c; |
||||
app->running = 1; |
||||
|
||||
/* setup signals handler */ |
||||
signal(SIGINT, signal_handler); |
||||
signal(SIGTERM, signal_handler); |
||||
mg_mgr_init(&mgr); |
||||
|
||||
if ((c = mg_http_listen(&mgr, addr, handle_request, app)) == NULL) { |
||||
MG_ERROR(("Cannot listen on %s. Use http://ADDR:PORT or :PORT", addr)); |
||||
return EXIT_FAILURE; |
||||
} |
||||
MG_INFO(("Mongoose version : v%s", MG_VERSION)); |
||||
MG_INFO(("Rapida version : v%s", RPD_VERSION)); |
||||
MG_INFO(("Listening on : %s", addr)); |
||||
while (s_signo == 0 && app->running) |
||||
mg_mgr_poll(&mgr, 1000); |
||||
|
||||
app->running = 0; |
||||
MG_INFO(("Exiting on signal %d", s_signo)); |
||||
mg_mgr_free(&mgr); |
||||
return 0; |
||||
} |
Loading…
Reference in new issue