Add basis for gemini requests

This commit is contained in:
Romain de Laage 2021-02-18 12:09:41 +01:00
parent 2ca1648ee2
commit 52cac2c063
Signed by: rdelaage
GPG Key ID: 534845FADDF0C329
3 changed files with 144 additions and 0 deletions

View File

@ -20,3 +20,7 @@ testgemparse:
testurllib:
mkdir -p $(BUILD_DIR)/test
$(CC) -o $(BUILD_DIR)/test/urllib-$(OS) -D TESTURLLIB lib/url.c
testgemini:
mkdir -p $(BUILD_DIR)/test
$(CC) -o $(BUILD_DIR)/test/gemini-$(OS) -Iinclude lib/gemini.c -lssl -lcrypto -D TESTGEMLIB

7
include/gemini.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef _GEMLIB_H
#define _GEMLIB_H
int GEM_send_request (const char *request, const char *host, FILE *answerFile);
void GEM_init (void);
#endif

133
lib/gemini.c Normal file
View File

@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <gemini.h>
#ifdef TESTGEMLIB
int
main (int argc,
char **argv)
{
GEM_init ();
if (argc >= 3)
{
char request[1030];
sprintf(request, "%s\r\n", argv[1]);
return GEM_send_request (request, argv[2], stdout);
}
return 1;
}
#endif
void GEM_init (void)
{
SSL_load_error_strings();
SSL_library_init();
}
int GEM_send_request (const char *request, const char *host, FILE *answerFile)
{
const SSL_METHOD *method = TLS_client_method();
SSL *ssl = NULL;
SSL_CTX *ctx = NULL;
BIO *bio = NULL;
int n;
int code_init = 0;
int meta_init = 0;
char answer_code[3] = {'\0'};
char answer_meta[1024] = {'\0'};
char buffer[1024] = {'\0'};
if (method == NULL)
{
perror("Method");
ERR_print_errors_fp(stderr);
return 1;
}
ctx = SSL_CTX_new(method);
if (ctx == NULL)
{
perror("ctx");
ERR_print_errors_fp(stderr);
return 1;
}
bio = BIO_new_ssl_connect(ctx);
if (bio == NULL)
{
perror("bio");
ERR_print_errors_fp(stderr);
SSL_CTX_free(ctx);
return 1;
}
BIO_get_ssl(bio, &ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
BIO_set_conn_hostname(bio, host);
if (BIO_do_connect(bio) <= 0)
{
BIO_free_all(bio);
SSL_CTX_free(ctx);
perror("bio connect");
ERR_print_errors_fp(stderr);
return 1;
}
BIO_puts(bio, request);
n = BIO_read(bio, buffer, 1);
while (n > 0 && code_init == 0)
{
if (answer_code[0] == '\0')
answer_code[0] = *buffer;
else
{
answer_code[1] = *buffer;
code_init = 1;
}
n = BIO_read(bio, buffer, 1);
}
while (n > 0 && meta_init == 0)
{
if (*buffer != '\n')
answer_meta[strlen (answer_meta)] = *buffer;
else if (answer_meta[strlen (answer_meta) - 1] == '\r')
{
answer_meta[strlen (answer_meta) - 1] = '\0';
meta_init = 1;
}
else
{
fprintf (stderr, "Gemlib : Invalid answer header (should be CRLF terminated");
meta_init = 1;
}
n = BIO_read(bio, buffer, 1);
}
while (n > 0)
{
buffer[n] = '\0';
fwrite(buffer, sizeof(char), n, answerFile);
n = BIO_read(bio, buffer, 1024);
}
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}