ref: 9bf1eefe5c7c7aaef02fe75372fcdc33843a9c8e
parent: e8b9c92e4ff06afdd1e7bf4bd074ad3817b4d8ab
author: zamfofex <zamfofex@twdb.moe>
date: Wed Apr 3 21:24:52 EDT 2024
replace BearSSL with libtls
--- a/.build.yml
+++ b/.build.yml
@@ -6,8 +6,7 @@
- 72a028fc-f8df-43d3-a315-305d80720e45
packages:
- build-base
- - bearssl-dev
- - bearssl-static
+ - libressl-dev
- xz
- mingw-w64-gcc
- curl
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,5 @@
!/tools/ugi.c
!/tools/ugi-uci.c
!/tools/uci-ugi.c
+!/tools/https.h
+!/tools/https.c
--- a/makefile
+++ b/makefile
@@ -10,8 +10,8 @@
moonfish_cc := $(cc) -pthread -D_POSIX_C_SOURCE=199309L
tools_cc := $(cc) -pthread -D_POSIX_C_SOURCE=200809L
-lichess_cc := $(tools_cc) -std=c99
-lichess_libs := -lbearssl -lcjson
+tools_src := moonfish.h tools/tools.h tools/utils.c chess.c
+ugi_src := $(tools_src) tools/ugi.h tools/ugi.c tools/ugi-uci.c
.PHONY: all clean install uninstall
@@ -19,14 +19,17 @@
moonfish moonfish.exe moonfish.wasm: moonfish.h chess.c search.c main.c
$(moonfish_cc) -o $@ $(filter %.c,$^)
+
+%: $(tools_src) tools/%.c
+ $(tools_cc) -o $@ $(filter %.c,$^)
-%: moonfish.h tools/tools.h tools/%.c tools/utils.c chess.c
- $(or $($(@)_cc),$(tools_cc)) -o $@ $(filter %.c,$^) $($(@)_libs)
+lichess: $(tools_src) tools/lichess.c tools/https.c
+ $(tools_cc) -o $@ $(filter %.c,$^) -ltls -lssl -lcrypto -lcjson
-ugi-uci: moonfish.h tools/tools.h tools/ugi.h tools/utils.c tools/ugi.c tools/ugi-uci.c chess.c
+ugi-uci: $(ugi_src)
$(tools_cc) -o $@ $(filter %.c,$^)
-uci-ugi: tools/tools.h tools/ugi.h tools/utils.c tools/ugi.c tools/uci-ugi.c
+uci-ugi: $(ugi_src)
$(tools_cc) -o $@ $(filter %.c,$^)
clean:
--- /dev/null
+++ b/tools/https.c
@@ -1,0 +1,211 @@
+/* moonfish is licensed under the AGPL (v3 or later) */
+/* copyright 2024 zamfofex */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "https.h"
+
+int moonfish_read(char *argv0, struct tls *tls, void *data0, size_t length)
+{+ char *data;
+ ssize_t result;
+
+ data = data0;
+
+ while (length > 0)
+ {+ result = tls_read(tls, data, length);
+ if (result == 0) return 1;
+ if (result == TLS_WANT_POLLIN || result == TLS_WANT_POLLOUT) continue;
+ if (result == -1)
+ {+ fprintf(stderr, "%s: %s\n", argv0, tls_error(tls));
+ exit(1);
+ }
+
+ data += result;
+ length -= result;
+ }
+
+ return 0;
+}
+
+int moonfish_write(char *argv0, struct tls *tls, void *data0, size_t length)
+{+ char *data;
+ ssize_t result;
+
+ data = data0;
+
+ while (length > 0)
+ {+ result = tls_write(tls, data, length);
+ if (result == 0) return 1;
+ if (result == TLS_WANT_POLLIN || result == TLS_WANT_POLLOUT) continue;
+ if (result == -1)
+ {+ fprintf(stderr, "%s: %s\n", argv0, tls_error(tls));
+ exit(1);
+ }
+
+ data += result;
+ length -= result;
+ }
+
+ return 0;
+}
+
+int moonfish_write_text(char *argv0, struct tls *tls, char *text)
+{+ return moonfish_write(argv0, tls, text, strlen(text));
+}
+
+char *moonfish_read_line(char *argv0, struct tls *tls)
+{+ char *line;
+ size_t length;
+
+ line = NULL;
+ length = 0;
+
+ for (;;)
+ {+ line = realloc(line, length + 1);
+ if (line == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (moonfish_read(argv0, tls, line + length, 1))
+ {+ if (length == 0)
+ {+ free(line);
+ return NULL;
+ }
+ line[length] = 0;
+ return line;
+ }
+ if (line[length] == '\n')
+ {+ line[length] = 0;
+ return line;
+ }
+ if (line[length] != '\r') length++;
+ }
+}
+
+void moonfish_request(char *argv0, struct tls *tls, char *host, char *request, char *token, char *type, int length)
+{+ char length_string[64];
+
+ moonfish_write_text(argv0, tls, request);
+ moonfish_write_text(argv0, tls, " HTTP/1.0\r\n");
+
+ if (token != NULL)
+ {+ moonfish_write_text(argv0, tls, "Authorization: Bearer ");
+ moonfish_write_text(argv0, tls, token);
+ moonfish_write_text(argv0, tls, "\r\n");
+ }
+
+ moonfish_write_text(argv0, tls, "Connection: close\r\n");
+
+ moonfish_write_text(argv0, tls, "Host: ");
+ moonfish_write_text(argv0, tls, host);
+ moonfish_write_text(argv0, tls, "\r\n");
+
+ if (type != NULL)
+ {+ moonfish_write_text(argv0, tls, "Content-Type: ");
+ moonfish_write_text(argv0, tls, type);
+ moonfish_write_text(argv0, tls, "\r\n");
+
+ sprintf(length_string, "%d", length);
+
+ moonfish_write_text(argv0, tls, "Content-Length: ");
+ moonfish_write_text(argv0, tls, length_string);
+ moonfish_write_text(argv0, tls, "\r\n");
+ }
+
+ moonfish_write_text(argv0, tls, "User-Agent: moonfish/0\r\n\r\n");
+}
+
+int moonfish_response(char *argv0, struct tls *tls)
+{+ static char success0[] = "HTTP/1.0 2";
+ static char success1[] = "HTTP/1.1 2";
+
+ char *line;
+
+ line = moonfish_read_line(argv0, tls);
+
+ if (strncmp(line, success0, sizeof success0 - 1))
+ if (strncmp(line, success1, sizeof success1 - 1))
+ return 1;
+
+ for (;;)
+ {+ free(line);
+ line = moonfish_read_line(argv0, tls);
+ if (*line == 0)
+ {+ free(line);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+struct tls *moonfish_connect(char *argv0, char *host, char *port)
+{+ struct tls *tls;
+
+ tls = tls_client();
+ if (tls == NULL)
+ {+ fprintf(stderr, "%s: Could not create libtls client\n", argv0);
+ exit(1);
+ }
+
+ if (tls_connect(tls, host, port))
+ {+ fprintf(stderr, "%s: %s\n", argv0, tls_error(tls));
+ exit(1);
+ }
+
+ return tls;
+}
+
+void moonfish_close(char *argv0, struct tls *tls)
+{+ if (tls_close(tls) != 0)
+ {+ fprintf(stderr, "%s: %s\n", argv0, tls_error(tls));
+ exit(1);
+ }
+
+ tls_free(tls);
+}
+
+int moonfish_basic_request(char *argv0, char *host, char *port, char *request, char *token, char *type, char *body)
+{+ int status;
+ struct tls *tls;
+
+ tls = moonfish_connect(argv0, host, port);
+
+ if (type == NULL && body != NULL) type = "application/x-www-form-urlencoded";
+
+ moonfish_request(argv0, tls, host, token, request, type, body == NULL ? 0 : strlen(body));
+
+ if (body != NULL) moonfish_write_text(argv0, tls, body);
+
+ status = moonfish_response(argv0, tls);
+ moonfish_close(argv0, tls);
+ return status;
+}
--- /dev/null
+++ b/tools/https.h
@@ -1,0 +1,14 @@
+/* moonfish is licensed under the AGPL (v3 or later) */
+/* copyright 2024 zamfofex */
+
+#include <tls.h>
+
+int moonfish_read(char *argv0, struct tls *tls, void *data, size_t length);
+int moonfish_write(char *argv0, struct tls *tls, void *data, size_t length);
+int moonfish_write_text(char *argv0, struct tls *tls, char *text);
+char *moonfish_read_line(char *argv0, struct tls *tls);
+void moonfish_request(char *argv0, struct tls *tls, char *host, char *request, char *token, char *type, int length);
+int moonfish_response(char *argv0, struct tls *tls);
+int moonfish_basic_request(char *argv0, char *host, char *port, char *request, char *token, char *type, char *body);
+struct tls *moonfish_connect(char *argv0, char *host, char *port);
+void moonfish_close(char *argv0, struct tls *tls);
--- a/tools/lichess.c
+++ b/tools/lichess.c
@@ -1,27 +1,21 @@
/* moonfish is licensed under the AGPL (v3 or later) */
/* copyright 2023, 2024 zamfofex */
-#include <netdb.h>
#include <string.h>
-#include <unistd.h>
#include <stdlib.h>
-#include <errno.h>
#include <pthread.h>
#include <signal.h>
-#include <bearssl.h>
#include <cjson/cJSON.h>
#include "../moonfish.h"
#include "tools.h"
+#include "https.h"
-#define moonfish_write_text(io_ctx, text) br_sslio_write_all(io_ctx, text, strlen(text))
-#define moonfish_write_string(io_ctx, text) br_sslio_write_all(io_ctx, text, sizeof text - 1)
-
struct moonfish_game
{char *argv0;
- char *name;
+ char *host;
char *port;
char *token;
char id[512];
@@ -30,415 +24,6 @@
char fen[512];
};
-static int moonfish_tcp(char *argv0, char *name, char *port)
-{- int fd;
- int error;
- struct addrinfo hints = {0};- struct addrinfo *infos, *info;
-
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = 0;
- hints.ai_protocol = 0;
-
- error = getaddrinfo(name, port, &hints, &infos);
- if (error)
- {- fprintf(stderr, "%s: %s\n", argv0, gai_strerror(error));
- exit(1);
- }
-
- fd = -1;
-
- for (info = infos ; info != NULL ; info = info->ai_next)
- {- fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
- if (fd == -1) continue;
- if (connect(fd, info->ai_addr, info->ai_addrlen) != -1) break;
- close(fd);
- }
-
- freeaddrinfo(infos);
-
- if (info == NULL)
- {- fprintf(stderr, "%s: could not connect to [%s]:%s\n", argv0, name, port);
- exit(1);
- }
-
- return fd;
-}
-
-static int moonfish_read(void *data, unsigned char *buffer, size_t length)
-{- int fd, *fds;
- ssize_t read_length;
-
- fds = data;
- fd = *fds;
-
- for (;;)
- {- read_length = read(fd, buffer, length);
- if (read_length <= 0)
- {- if (read_length < 0 && errno == EINTR) continue;
- return -1;
- }
- return read_length;
- }
-}
-
-static int moonfish_write(void *data, const unsigned char *buffer, size_t length)
-{- int fd, *fds;
- ssize_t write_length;
-
- fds = data;
- fd = *fds;
-
- for (;;)
- {- write_length = write(fd, buffer, length);
- if (write_length <= 0)
- {- if (write_length < 0 && errno == EINTR) continue;
- return -1;
- }
- return write_length;
- }
-}
-
-static void moonfish_pem_data(void *data, const void *buffer, size_t length)
-{- br_x509_decoder_context *x509_ctx;
-
- if (length == 0) return;
-
- x509_ctx = data;
- br_x509_decoder_push(x509_ctx, buffer, length);
-}
-
-static void moonfish_x509_data(void *data, const void *buffer, size_t length)
-{- br_x500_name *dn;
-
- if (length == 0) return;
-
- dn = data;
- dn->len += length;
- dn->data = realloc(dn->data, dn->len);
-
- if (dn->data == NULL)
- {- perror(NULL);
- exit(1);
- }
-
- memcpy(dn->data + dn->len - length, buffer, length);
-}
-
-static void moonfish_copy_key(br_x509_pkey *to, br_x509_pkey *from)
-{- to->key_type = from->key_type;
-
- if (from->key_type == BR_KEYTYPE_RSA)
- {- to->key.rsa.nlen = from->key.rsa.nlen;
- to->key.rsa.n = malloc(to->key.rsa.nlen);
- if (to->key.rsa.n == NULL)
- {- perror(NULL);
- exit(1);
- }
- memcpy(to->key.rsa.n, from->key.rsa.n, to->key.rsa.nlen);
-
- to->key.rsa.elen = from->key.rsa.elen;
- to->key.rsa.e = malloc(to->key.rsa.elen);
- if (to->key.rsa.e == NULL)
- {- perror(NULL);
- exit(1);
- }
- memcpy(to->key.rsa.e, from->key.rsa.e, to->key.rsa.elen);
- }
-
- if (from->key_type == BR_KEYTYPE_EC)
- {- to->key.ec.curve = from->key.ec.curve;
- to->key.ec.qlen = from->key.ec.qlen;
- to->key.ec.q = malloc(to->key.ec.qlen);
- if (to->key.ec.q == NULL)
- {- perror(NULL);
- exit(1);
- }
- memcpy(to->key.ec.q, from->key.ec.q, to->key.ec.qlen);
- }
-}
-
-static void moonfish_load_pem(char *argv0, FILE *file, br_x509_trust_anchor **tas, size_t *count)
-{- size_t read_length, n;
- unsigned char buffer0[1024], *buffer;
- br_pem_decoder_context pem_ctx;
- br_x509_decoder_context x509_ctx;
- br_x509_trust_anchor *trust_anchors, *trust_anchor;
- size_t trust_anchor_count;
- br_x509_pkey *pkey;
-
- br_pem_decoder_init(&pem_ctx);
-
- read_length = 0;
- trust_anchors = NULL;
- trust_anchor_count = 0;
-
- for (;;)
- {- if (read_length == 0)
- {- if (feof(file)) break;
- read_length = fread(buffer0, 1, sizeof buffer0, file);
- if (ferror(file))
- {- fprintf(stderr, "%s: could not read certificat file\n", argv0);
- exit(1);
- }
- buffer = buffer0;
- }
-
- n = br_pem_decoder_push(&pem_ctx, buffer, read_length);
- buffer += n;
- read_length -= n;
-
- switch (br_pem_decoder_event(&pem_ctx))
- {- case 0:
- break;
- default:
- fprintf(stderr, "%s: PEM decoding failed\n", argv0);
- exit(1);
- case BR_PEM_BEGIN_OBJ:
- trust_anchors = realloc(trust_anchors, sizeof *trust_anchors * (trust_anchor_count + 1));
- if (trust_anchors == NULL)
- {- perror(argv0);
- exit(1);
- }
- trust_anchor = trust_anchors + trust_anchor_count;
- trust_anchor->dn.len = 0;
- trust_anchor->dn.data = NULL;
- br_x509_decoder_init(&x509_ctx, &moonfish_x509_data, &trust_anchor->dn);
- br_pem_decoder_setdest(&pem_ctx, &moonfish_pem_data, &x509_ctx);
- break;
- case BR_PEM_END_OBJ:
- trust_anchor = trust_anchors + trust_anchor_count;
- trust_anchor_count++;
- pkey = br_x509_decoder_get_pkey(&x509_ctx);
- if (pkey == NULL)
- {- fprintf(stderr, "%s: X509 decoding failed: %d\n", argv0, br_x509_decoder_last_error(&x509_ctx));
- exit(-1);
- }
- moonfish_copy_key(&trust_anchor->pkey, pkey);
- trust_anchor->flags = 0;
- if (br_x509_decoder_isCA(&x509_ctx)) trust_anchor->flags |= BR_X509_TA_CA;
- break;
- }
- }
-
- *tas = trust_anchors;
- *count = trust_anchor_count;
-}
-
-static void moonfish_request(
- br_ssl_client_context *ctx,
- br_sslio_context *io_ctx,
- br_x509_minimal_context *min_ctx,
- void *buffer,
- size_t size,
- char *argv0,
- char *name,
- char *port,
- char *token,
- char *request,
- char *type,
- int length,
- int *fd
-)
-{- char length_string[64];
-
- static FILE *certs;
- static br_x509_trust_anchor *tas = NULL;
- static size_t count;
-
- if (tas == NULL)
- {- certs = fopen("/etc/ssl/certs/ca-certificates.crt", "rb");- if (certs == NULL)
- {- perror(argv0);
- exit(1);
- }
-
- moonfish_load_pem(argv0, certs, &tas, &count);
- fclose(certs);
- }
-
- br_ssl_client_init_full(ctx, min_ctx, tas, count);
- br_ssl_engine_set_buffer(&ctx->eng, buffer, size, 1);
- br_ssl_client_reset(ctx, name, 0);
-
- *fd = moonfish_tcp(argv0, name, port);
- br_sslio_init(io_ctx, &ctx->eng, &moonfish_read, fd, &moonfish_write, fd);
-
- moonfish_write_text(io_ctx, request);
- moonfish_write_string(io_ctx, " HTTP/1.0\r\n");
-
- moonfish_write_string(io_ctx, "Authorization: Bearer ");
- moonfish_write_text(io_ctx, token);
- moonfish_write_string(io_ctx, "\r\n");
-
- moonfish_write_string(io_ctx, "Connection: close\r\n");
-
- moonfish_write_string(io_ctx, "Host: ");
- moonfish_write_text(io_ctx, name);
- moonfish_write_string(io_ctx, "\r\n");
-
- if (type[0])
- {- moonfish_write_string(io_ctx, "Content-Type: ");
- moonfish_write_text(io_ctx, type);
- moonfish_write_string(io_ctx, "\r\n");
-
- sprintf(length_string, "%d", length);
-
- moonfish_write_string(io_ctx, "Content-Length: ");
- moonfish_write_text(io_ctx, length_string);
- moonfish_write_string(io_ctx, "\r\n");
- }
-
- moonfish_write_string(io_ctx, "User-Agent: moonfish/0\r\n\r\n");
-}
-
-static int moonfish_response(br_ssl_engine_context *ctx, br_sslio_context *io_ctx, char *argv0)
-{- static char success[] = "HTTP/1.0 2";
- static char success1[] = "HTTP/1.1 2";
-
- char line[sizeof success];
- char prev, cur;
- int error;
-
- if (br_sslio_read_all(io_ctx, line, sizeof line - 1))
- {- fprintf(stderr, "%s: malformed HTTP status\n", argv0);
- exit(1);
- }
-
- if (strncmp(line, success, sizeof line - 1))
- if (strncmp(line, success1, sizeof line - 1))
- return 1;
-
- prev = 0;
- for (;;)
- {- if (br_sslio_read_all(io_ctx, &cur, 1))
- {- fprintf(stderr, "%s: malformed HTTP response\n", argv0);
- exit(1);
- }
- if (prev == '\n' && cur == '\r') break;
- if (prev == '\r' && cur == '\r') break;
- if (prev == '\n' && cur == '\n') return 0;
- prev = cur;
- }
-
- if (br_sslio_read_all(io_ctx, &cur, 1) || cur != '\n')
- {- fprintf(stderr, "%s: malformed HTTP header separator\n", argv0);
- exit(1);
- }
-
- error = br_ssl_engine_last_error(ctx);
- if (error)
- {- fprintf(stderr, "%s: BearSSL error: %d\n", argv0, error);
- exit(1);
- }
-
- return 0;
-}
-
-static int moonfish_basic_request(char *argv0, char *name, char *port, char *token, char *request, char *type, char *body)
-{- br_ssl_client_context ctx;
- br_sslio_context io_ctx;
- br_x509_minimal_context min_ctx;
- void *buffer;
- int fd;
- int status;
-
- buffer = malloc(BR_SSL_BUFSIZE_BIDI);
-
- if (type[0] == 0 && body[0] != 0) type = "application/x-www-form-urlencoded";
-
- moonfish_request(
- &ctx, &io_ctx, &min_ctx,
- buffer, BR_SSL_BUFSIZE_BIDI,
- argv0,
- name, port,
- token, request, type,
- strlen(body),
- &fd
- );
-
- moonfish_write_text(&io_ctx, body);
- br_sslio_flush(&io_ctx);
-
- status = moonfish_response(&ctx.eng, &io_ctx, argv0);
-
- close(fd);
- free(buffer);
-
- return status;
-}
-
-static int moonfish_tls_line(br_ssl_engine_context *ctx, br_sslio_context *io_ctx, char *argv0, char *line, int length)
-{- int error;
-
- if (length-- == 0) return 0;
-
- for (;;)
- {- if (!length--)
- {- fprintf(stderr, "%s: line too long\n", argv0);
- exit(1);
- }
- if (br_sslio_read_all(io_ctx, line, 1))
- {- error = br_ssl_engine_last_error(ctx);
- if (error)
- {- fprintf(stderr, "%s: BearSSL error: %d\n", argv0, error);
- exit(1);
- }
- *line = 0;
- return 1;
- }
- if (*line == '\n') break;
- line++;
- }
-
- *line = 0;
-
- return 0;
-}
-
static void moonfish_json_error(char *argv0)
{fprintf(stderr, "%s: malformed JSON\n", argv0);
@@ -447,9 +32,10 @@
static pthread_mutex_t moonfish_mutex = PTHREAD_MUTEX_INITIALIZER;
-static void moonfish_handle_game_events(br_ssl_engine_context *ctx, br_sslio_context *io_ctx, struct moonfish_game *game, FILE *in, FILE *out)
+static void moonfish_handle_game_events(struct tls *tls, struct moonfish_game *game, FILE *in, FILE *out)
{- char line[4096];
+ char request[2048];
+ char *line;
cJSON *root, *type, *state, *white_player, *id, *moves, *fen;
cJSON *wtime, *btime, *winc, *binc;
const char *end;
@@ -457,7 +43,6 @@
int move_count, count;
int i;
char *name, name0[6];
- int done;
int variant;
struct moonfish_chess chess;
struct moonfish_move move;
@@ -478,10 +63,9 @@
root = NULL;
white = -1;
move_count = -1;
- done = 0;
variant = 0;
- while (!done)
+ for (;;)
{pthread_mutex_unlock(&moonfish_mutex);
@@ -491,13 +75,21 @@
root = NULL;
}
- done = moonfish_tls_line(ctx, io_ctx, game->argv0, line, sizeof line);
+ line = moonfish_read_line(game->argv0, tls);
+ if (line == NULL) break;
+
pthread_mutex_lock(&moonfish_mutex);
- if (line[0] == 0) continue;
+ if (line[0] == 0)
+ {+ free(line);
+ continue;
+ }
+
end = NULL;
root = cJSON_ParseWithOpts(line, &end, 1);
if (end != line + strlen(line)) moonfish_json_error(game->argv0);
+ free(line);
if (!cJSON_IsObject(root)) moonfish_json_error(game->argv0);
@@ -633,12 +225,12 @@
}
}
- snprintf(line, sizeof line, "POST /api/bot/game/%s/move/%s", game->id, name);
- if (moonfish_basic_request(game->argv0, game->name, game->port, game->token, line, "", ""))
+ snprintf(request, sizeof request, "POST /api/bot/game/%s/move/%s", game->id, name);
+ if (moonfish_basic_request(game->argv0, game->host, game->port, game->token, request, NULL, NULL))
{fprintf(stderr, "%s: could not make move '%s' in game '%s'\n", game->argv0, name, game->id);
- snprintf(line, sizeof line, "POST /api/bot/game/%s/resign", game->id);
- if (moonfish_basic_request(game->argv0, game->name, game->port, game->token, line, "", ""))
+ snprintf(request, sizeof request, "POST /api/bot/game/%s/resign", game->id);
+ if (moonfish_basic_request(game->argv0, game->host, game->port, game->token, request, NULL, NULL))
fprintf(stderr, "%s: could not resign game '%s'\n", game->argv0, game->id);
break;
}
@@ -655,61 +247,37 @@
static void *moonfish_handle_game(void *data)
{- char request[4096];
+ char request[2048];
struct moonfish_game *game;
FILE *in, *out;
- br_ssl_client_context ctx;
- br_sslio_context io_ctx;
- br_x509_minimal_context min_ctx;
- void *buffer;
- int fd;
+ struct tls *tls;
game = data;
moonfish_spawn(game->argv0, game->argv, &in, &out);
+ tls = moonfish_connect(game->argv0, game->host, game->port);
- buffer = malloc(BR_SSL_BUFSIZE_BIDI);
-
snprintf(request, sizeof request, "GET /api/bot/game/stream/%s", game->id);
- moonfish_request(
- &ctx, &io_ctx, &min_ctx,
- buffer, BR_SSL_BUFSIZE_BIDI,
- game->argv0,
- game->name, game->port,
- game->token, request, "",
- 0, &fd
- );
+ moonfish_request(game->argv0, tls, game->host, request, game->token, NULL, 0);
- br_sslio_flush(&io_ctx);
-
- if (moonfish_response(&ctx.eng, &io_ctx, game->argv0))
+ if (moonfish_response(game->argv0, tls))
{fprintf(stderr, "%s: could not request game event stream\n", game->argv0);
exit(1);
}
- moonfish_handle_game_events(&ctx.eng, &io_ctx, game, in, out);
+ moonfish_handle_game_events(tls, game, in, out);
+ moonfish_close(game->argv0, tls);
free(game);
- free(buffer);
- close(fd);
-
return NULL;
}
-static void moonfish_handle_events(
- br_ssl_engine_context *ctx,
- br_sslio_context *io_ctx,
- char *argv0,
- char *name,
- char *port,
- char *token,
- char **argv,
- char *username
-)
+static void moonfish_handle_events(struct tls *tls, char *argv0, char *host, char *port, char *token, char **argv, char *username)
{- static char line[8192];
+ char request[2048];
+ char *line;
cJSON *root, *type, *challenge, *id, *variant, *speed, *fen;
const char *end;
struct moonfish_game *game;
@@ -728,17 +296,23 @@
root = NULL;
}
- if (moonfish_tls_line(ctx, io_ctx, argv0, line, sizeof line))
+ line = moonfish_read_line(argv0, tls);
+ if (line == NULL)
{fprintf(stderr, "%s: connection with Lichess closed\n", argv0);
exit(1);
}
- if (line[0] == 0) continue;
+ if (line[0] == 0)
+ {+ free(line);
+ continue;
+ }
end = NULL;
root = cJSON_ParseWithOpts(line, &end, 1);
if (end != line + strlen(line)) moonfish_json_error(argv0);
+ free(line);
if (!cJSON_IsObject(root)) moonfish_json_error(argv0);
@@ -767,7 +341,7 @@
}
game->argv0 = argv0;
- game->name = name;
+ game->host = host;
game->port = port;
game->token = token;
strcpy(game->id, id->valuestring);
@@ -822,8 +396,8 @@
if (invalid)
{- snprintf(line, sizeof line, "POST /api/challenge/%s/decline", id->valuestring);
- if (moonfish_basic_request(argv0, name, port, token, line, "", "reason=standard"))
+ snprintf(request, sizeof request, "POST /api/challenge/%s/decline", id->valuestring);
+ if (moonfish_basic_request(argv0, host, port, token, request, NULL, "reason=standard"))
fprintf(stderr, "%s: could not decline challenge '%s' (chess 960 FEN)\n", argv0, id->valuestring);
continue;
}
@@ -830,8 +404,8 @@
}
else if (strcmp(variant->valuestring, "standard"))
{- snprintf(line, sizeof line, "POST /api/challenge/%s/decline", id->valuestring);
- if (moonfish_basic_request(argv0, name, port, token, line, "", "reason=standard"))
+ snprintf(request, sizeof request, "POST /api/challenge/%s/decline", id->valuestring);
+ if (moonfish_basic_request(argv0, host, port, token, request, NULL, "reason=standard"))
fprintf(stderr, "%s: could not decline challenge '%s' (variant)\n", argv0, id->valuestring);
continue;
}
@@ -841,55 +415,42 @@
if (!strcmp(speed->valuestring, "correspondence"))
{- snprintf(line, sizeof line, "POST /api/challenge/%s/decline", id->valuestring);
- if (moonfish_basic_request(argv0, name, port, token, line, "", "reason=tooSlow"))
+ snprintf(request, sizeof request, "POST /api/challenge/%s/decline", id->valuestring);
+ if (moonfish_basic_request(argv0, host, port, token, request, NULL, "reason=tooSlow"))
fprintf(stderr, "%s: could not decline challenge '%s' (too slow)\n", argv0, id->valuestring);
continue;
}
- snprintf(line, sizeof line, "POST /api/challenge/%s/accept", id->valuestring);
- if (moonfish_basic_request(argv0, name, port, token, line, "", ""))
+ snprintf(request, sizeof request, "POST /api/challenge/%s/accept", id->valuestring);
+ if (moonfish_basic_request(argv0, host, port, token, request, NULL, NULL))
fprintf(stderr, "%s: could not accept challenge '%s'\n", argv0, id->valuestring);
}
}
-static char *moonfish_username(char *argv0, char *name, char *port, char *token)
+static char *moonfish_username(char *argv0, char *host, char *port, char *token)
{- static char line[8192];
- static char username[512];
-
- br_ssl_client_context ctx;
- br_sslio_context io_ctx;
- br_x509_minimal_context min_ctx;
- void *buffer;
- int fd;
+ char *line;
+ char *username;
const char *end;
cJSON *root, *id;
+ struct tls *tls;
- buffer = malloc(BR_SSL_BUFSIZE_BIDI);
+ tls = moonfish_connect(argv0, host, port);
- moonfish_request(
- &ctx, &io_ctx, &min_ctx,
- buffer, BR_SSL_BUFSIZE_BIDI,
- argv0,
- name, port,
- token, "GET /api/account",
- "", 0, &fd
- );
+ moonfish_request(argv0, tls, host, "GET /api/account", token, NULL, 0);
- br_sslio_flush(&io_ctx);
-
- if (moonfish_response(&ctx.eng, &io_ctx, argv0))
+ if (moonfish_response(argv0, tls))
{fprintf(stderr, "%s: could not request the Lichess username\n", argv0);
exit(1);
}
- moonfish_tls_line(&ctx.eng, &io_ctx, argv0, line, sizeof line);
+ line = moonfish_read_line(argv0, tls);
end = NULL;
root = cJSON_ParseWithOpts(line, &end, 1);
if (end != line + strlen(line)) moonfish_json_error(argv0);
+ free(line);
if (!cJSON_IsObject(root)) moonfish_json_error(argv0);
@@ -896,19 +457,20 @@
id = cJSON_GetObjectItem(root, "id");
if (!cJSON_IsString(id)) moonfish_json_error(argv0);
- strcpy(username, id->valuestring);
+ username = strdup(id->valuestring);
+ if (username == NULL)
+ {+ perror(argv0);
+ exit(0);
+ }
- br_sslio_close(&io_ctx);
+ moonfish_close(argv0, tls);
- free(buffer);
- close(fd);
-
return username;
}
int main(int argc, char **argv)
{- static unsigned char buffer[BR_SSL_BUFSIZE_BIDI];
static char *format = "<cmd> <args>...";
static struct moonfish_arg args[] =
{@@ -918,14 +480,11 @@
};
char *token;
- br_ssl_client_context ctx;
- br_sslio_context io_ctx;
- br_x509_minimal_context min_ctx;
- int fd;
int i;
- int error;
char **command;
int command_count;
+ struct tls *tls;
+ char *username;
command = moonfish_args(args, format, argc, argv);
command_count = argc - (command - argv);
@@ -949,31 +508,17 @@
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) return 1;
- moonfish_request(&ctx, &io_ctx, &min_ctx, buffer, sizeof buffer, argv[0], args[0].value, args[1].value, token, "GET /api/stream/event", "", 0, &fd);
- br_sslio_flush(&io_ctx);
- if (moonfish_response(&ctx.eng, &io_ctx, argv[0]))
+ tls = moonfish_connect(argv[0], args[0].value, args[1].value);
+ moonfish_request(argv[0], tls, args[0].value, "GET /api/stream/event", token, NULL, 0);
+ if (moonfish_response(argv[0], tls))
{fprintf(stderr, "%s: could not request event stream\n", argv[0]);
return 1;
}
- moonfish_handle_events(&ctx.eng, &io_ctx, argv[0], args[0].value, args[1].value, token, command, moonfish_username(argv[0], args[0].value, args[1].value, token));
+ username = moonfish_username(argv[0], args[0].value, args[1].value, token);
+ moonfish_handle_events(tls, argv[0], args[0].value, args[1].value, token, command, username);
- br_ssl_engine_close(&ctx.eng);
- close(fd);
-
- if (br_ssl_engine_current_state(&ctx.eng) != BR_SSL_CLOSED)
- {- fprintf(stderr,"%s: TLS connection closed improperly\n", argv[0]);
- return 1;
- }
-
- error = br_ssl_engine_last_error(&ctx.eng);
- if (error)
- {- fprintf(stderr, "%s: BearSSL error: %d\n", argv[0], error);
- return 1;
- }
-
- return 0;
+ fprintf(stderr, "%s: Unreachable\n", argv[0]);
+ return 1;
}
--
⑨