paivana

HTTP paywall reverse proxy
Log | Files | Refs | README | LICENSE

commit 7d45401feda856622a440a5bb1b4404488a1b771
parent b97d08202347cbf5e3ac33e24d6f00f8ecf8c2ad
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 26 Nov 2025 23:40:51 +0100

complete trivial reverse proxy

Diffstat:
M.gitignore | 5+++++
Asrc/backend/.gitignore | 3+++
Msrc/backend/paivana-httpd.c | 54+++++++++++++-----------------------------------------
Asrc/backend/test.conf | 4++++
Asrc/include/Makefile.am | 7+++++++
Asrc/include/platform.h | 282+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 314 insertions(+), 41 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -14,3 +14,8 @@ ltmain.sh m4/ missing paivana_config.h.in +config.log +config.status +libtool +paivana_config.h +stamp-h1 diff --git a/src/backend/.gitignore b/src/backend/.gitignore @@ -0,0 +1,3 @@ +paivana-httpd +*.o +.deps/ diff --git a/src/backend/paivana-httpd.c b/src/backend/paivana-httpd.c @@ -329,9 +329,7 @@ curl_check_hdr (void *buffer, buffer, bytes); ndup[bytes] = '\0'; - hdr_type = strtok (ndup, ":"); - if (NULL == hdr_type) { GNUNET_free (ndup); @@ -354,11 +352,9 @@ curl_check_hdr (void *buffer, *tok = '\0'; if (NULL != (tok = strchr (hdr_val, '\t'))) *tok = '\0'; - PAIVANA_LOG_DEBUG ("Parsed line: '%s: %s'\n", hdr_type, hdr_val); - /* Skip "Content-length:" header as it will be wrong, given that we are man-in-the-middling the connection */ if (0 == strcasecmp (hdr_type, @@ -586,7 +582,6 @@ curl_upload_cb (void *buf, * Extract the hostname from a complete URL. * * @param url full fledged URL - * * @return pointer to the 0-terminated hostname, to be freed * by the caller. */ @@ -600,16 +595,14 @@ build_host_header (const char *url) char *hostname; char *dup = GNUNET_strdup (url); - hostname = strstr (dup, MARKER); + hostname = strstr (dup, + MARKER); hostname += 3; - end = strchrnul (hostname, '/'); *end = '\0'; - GNUNET_asprintf (&header, "Host: %s", hostname); - GNUNET_free (dup); return header; } @@ -842,7 +835,6 @@ curl_task_download (void *cls) break; } } - ; } while (mret == CURLM_CALL_MULTI_PERFORM); if (CURLM_OK != mret) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -996,10 +988,10 @@ create_response (void *cls, 0); curl_easy_setopt (hr->curl, CURLOPT_CONNECTTIMEOUT, - 600L); + 60L); curl_easy_setopt (hr->curl, CURLOPT_TIMEOUT, - 600L); + 60L); curl_easy_setopt (hr->curl, CURLOPT_NOSIGNAL, 1L); @@ -1013,7 +1005,6 @@ create_response (void *cls, curl_easy_setopt (hr->curl, CURLOPT_READFUNCTION, &curl_upload_cb); - curl_easy_setopt (hr->curl, CURLOPT_READDATA, hr); @@ -1021,7 +1012,6 @@ create_response (void *cls, curl_easy_setopt (hr->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); - curl_easy_setopt (hr->curl, CURLOPT_WRITEDATA, hr); @@ -1049,6 +1039,7 @@ create_response (void *cls, GNUNET_free (host_hdr); } + // FIXME: support PATCH, etc. if (0 == strcasecmp (meth, MHD_HTTP_METHOD_PUT)) { @@ -1059,7 +1050,6 @@ create_response (void *cls, CURLOPT_UPLOAD, 1L); hr->state = REQUEST_STATE_PROXY_UPLOAD_STARTED; - } else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) @@ -1073,7 +1063,6 @@ create_response (void *cls, CURLOPT_VERBOSE, 1L); hr->state = REQUEST_STATE_PROXY_UPLOAD_STARTED; - } else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD)) @@ -1109,29 +1098,9 @@ create_response (void *cls, return MHD_NO; } - if (0 == strcasecmp (ver, - MHD_HTTP_VERSION_1_0)) - { - curl_easy_setopt (hr->curl, - CURLOPT_HTTP_VERSION, - CURL_HTTP_VERSION_1_0); - } - else if (0 == strcasecmp (ver, - MHD_HTTP_VERSION_1_1)) - { - curl_easy_setopt (hr->curl, - CURLOPT_HTTP_VERSION, - CURL_HTTP_VERSION_1_1); - } - else - { - curl_easy_setopt (hr->curl, - CURLOPT_HTTP_VERSION, - CURL_HTTP_VERSION_NONE); - } - - if (CURLM_OK != curl_multi_add_handle (curl_multi, - hr->curl)) + if (CURLM_OK != + curl_multi_add_handle (curl_multi, + hr->curl)) { GNUNET_break (0); curl_easy_cleanup (hr->curl); @@ -1162,6 +1131,9 @@ create_response (void *cls, GNUNET_assert (REQUEST_STATE_PROXY_DOWNLOAD_DONE == hr->state); + hr->response + = MHD_create_response_from_buffer_copy (hr->io_len, + hr->io_buf); for (struct HttpResponseHeader *header = hr->header_head; NULL != header; header = header->next) @@ -1577,7 +1549,8 @@ open_unix_path (const char *path, * @param mode[out] mode string for @a path. * @return #GNUNET_SYSERR if the parsing didn't succeed. */ -static int +// FIXME: replace by helper function of Taler? +static enum GNUNET_GenericReturnValue parse_serving_mean (const struct GNUNET_CONFIGURATION_Handle *ccfg, uint16_t *port, char **path, @@ -1589,7 +1562,6 @@ parse_serving_mean (const struct GNUNET_CONFIGURATION_Handle *ccfg, char *modestring; unsigned long long port_ull; - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_choice (ccfg, "paivana", diff --git a/src/backend/test.conf b/src/backend/test.conf @@ -0,0 +1,4 @@ +[paivana] +DESTINATION_BASE_URL = https://grothoff.org/ +SERVE = tcp +HTTP_PORT = 8888 diff --git a/src/include/Makefile.am b/src/include/Makefile.am @@ -0,0 +1,7 @@ +# This Makefile.am is in the public domain +SUBDIRS = . + +paivanaincludedir = $(includedir)/paivana + +paivanainclude_HEADERS = \ + platform.h diff --git a/src/include/platform.h b/src/include/platform.h @@ -0,0 +1,282 @@ +/* + This file is part of GNUnet. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2012 GNUnet e.V. + Copyright (C) 2025 Taler Systems SA + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: AGPL3.0-or-later + */ + +/** + * @author Nils Durner + * @author Christian Grothoff + * + * @file gnunet/src/include/platform.h + * Platform specific includes and defines. + * + * This file should never be included by installed + * header files (those starting with "gnunet_"). + */ +#ifndef PLATFORM_H +#define PLATFORM_H + +#ifndef HAVE_USED_CONFIG_H +#define HAVE_USED_CONFIG_H +#if HAVE_CONFIG_H +#include "paivana_config.h" +#endif +#endif + +#define BREAKPOINT +#define GNUNET_SIGCHLD SIGCHLD + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <inttypes.h> + +#ifdef __clang__ +#undef HAVE_STATIC_ASSERT +#endif + +/** + * These may be expensive, but good for debugging... + */ +#define ALLOW_EXTRA_CHECKS GNUNET_YES + +/** + * For strptime (glibc2 needs this). + */ +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 499 +#endif + +#ifndef _REENTRANT +#define _REENTRANT +#endif + +/* configuration options */ + +#define VERBOSE_STATS 0 + +#include <netdb.h> +#include <sys/socket.h> +#include <sys/un.h> +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#if HAVE_NETINET_IP_H +#include <netinet/ip.h> /* superset of previous */ +#endif +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <pwd.h> +#include <sys/ioctl.h> +#include <sys/wait.h> +#include <grp.h> + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdarg.h> +#include <stdbool.h> +#include <errno.h> +#include <signal.h> +#include <libgen.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> /* for mallinfo on GNU */ +#endif +#include <unistd.h> /* KLB_FIX */ +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> /* KLB_FIX */ +#include <fcntl.h> +#include <math.h> +#if HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#include <time.h> +#ifdef BSD +#include <net/if.h> +#endif +#if defined(BSD) && defined(__FreeBSD__) && defined(__FreeBSD_kernel__) +#include <semaphore.h> +#endif +#ifdef DARWIN +#include <dlfcn.h> +#include <semaphore.h> +#include <net/if.h> +#include <xlocale.h> +#endif +#if defined(__linux__) || defined(GNU) +#include <net/if.h> +#endif +#ifdef SOLARIS +#include <sys/sockio.h> +#include <sys/filio.h> +#include <sys/loadavg.h> +#include <semaphore.h> +#endif +#if HAVE_UCRED_H +#include <ucred.h> +#endif +#if HAVE_SYS_UCRED_H +#include <sys/ucred.h> +#endif +#if HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif +#include <errno.h> +#include <limits.h> + +#if HAVE_VFORK_H +#include <vfork.h> +#endif + +#include <ctype.h> +#if HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +#if HAVE_ENDIAN_H +#include <endian.h> +#endif +#if HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#endif + +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_STR "/" +#define PATH_SEPARATOR ':' +#define PATH_SEPARATOR_STR ":" +#define NEWLINE "\n" + +#include <locale.h> +#include <sys/mman.h> + +/* FreeBSD_kernel is not defined on the now discontinued kFreeBSD */ +#if defined(BSD) && defined(__FreeBSD__) && defined(__FreeBSD_kernel__) +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#endif + +#ifdef DARWIN +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +/* not available on darwin, override configure */ +#undef HAVE_STAT64 +#undef HAVE_MREMAP +#endif + +#if ! HAVE_ATOLL +long long +atoll (const char *nptr); + +#endif + +#if ENABLE_NLS +#include "langinfo.h" +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) (-1)) +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +/** + * AI_NUMERICSERV not defined in windows. Then we just do without. + */ +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0 +#endif + + +#if defined(__sparc__) +#define MAKE_UNALIGNED(val) ({ __typeof__((val)) __tmp; memmove (&__tmp, &(val), \ + sizeof((val))); \ + __tmp; }) +#else +#define MAKE_UNALIGNED(val) val +#endif + +/** + * The termination signal + */ +#define GNUNET_TERM_SIG SIGTERM + + +#ifndef PATH_MAX +/** + * Assumed maximum path length. + */ +#define PATH_MAX 4096 +#endif + +#if HAVE_THREAD_LOCAL_GCC +#define GNUNET_THREAD_LOCAL __thread +#else +#define GNUNET_THREAD_LOCAL +#endif + + +/* LSB-style exit status codes */ +#ifndef EXIT_INVALIDARGUMENT +#define EXIT_INVALIDARGUMENT 2 +#endif + +#ifndef EXIT_NOTIMPLEMENTED +#define EXIT_NOTIMPLEMENTED 3 +#endif + +#ifndef EXIT_NOPERMISSION +#define EXIT_NOPERMISSION 4 +#endif + +#ifndef EXIT_NOTINSTALLED +#define EXIT_NOTINSTALLED 5 +#endif + +#ifndef EXIT_NOTCONFIGURED +#define EXIT_NOTCONFIGURED 6 +#endif + +#ifndef EXIT_NOTRUNNING +#define EXIT_NOTRUNNING 7 +#endif + +#ifndef EXIT_NO_RESTART +#define EXIT_NO_RESTART 9 +#endif + +/** + * clang et al do not have such an attribute + */ +#if __has_attribute (__nonstring__) +# define __nonstring __attribute__((__nonstring__)) +#else +# define __nonstring +#endif + +#endif