update: migrating MPTP to TCP

This commit is contained in:
ngn 2024-08-07 04:49:33 +03:00
parent 865141177a
commit 75fa38f1d7
8 changed files with 138 additions and 109 deletions

View File

@ -148,6 +148,7 @@ typedef enum lm_error {
LM_ERR_ChdirFail = 146,
LM_ERR_ExtractRootChdirFail = 147,
LM_ERR_ExtractOldChdirFail = 148,
LM_ERR_MPTPAcceptFail = 149,
} lm_error_t;
typedef struct lm_error_desc {

View File

@ -141,9 +141,11 @@ bool lm_mptp_client_send(int sock, lm_mptp_t *packet);
bool lm_mptp_client_recv(int sock, lm_mptp_t *packet);
int lm_mptp_server_listen(char *addr, uint16_t port);
int lm_mptp_server_accept(int sock, struct sockaddr *addr);
void lm_mptp_server_close(int sock);
bool lm_mptp_server_verify(lm_mptp_t *packet);
bool lm_mptp_server_recv(int sock, lm_mptp_t *packet, struct sockaddr *addr);
bool lm_mptp_server_send(int sock, lm_mptp_t *packet, struct sockaddr *addr);
bool lm_mptp_server_recv(int sock, lm_mptp_t *packet);
bool lm_mptp_server_send(int sock, lm_mptp_t *packet);
bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_transfer_callback_t callback, void *data);
bool lm_mptp_sendfile(int sock, char *path, lm_mptp_transfer_callback_t callback, void *data);
bool lm_mptp_recvfile(int sock, char *path, lm_mptp_transfer_callback_t callback, void *data);

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-07 01:28+0300\n"
"POT-Creation-Date: 2024-08-07 04:49+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -630,3 +630,8 @@ msgstr ""
#: src/error.c:167
msgid "failed to change directory back from root during extraction"
msgstr ""
#: src/error.c:168
#, c-format
msgid "failed to accept the MPTP connection: %s"
msgstr ""

View File

@ -12,34 +12,89 @@
#include <stdbool.h>
struct lm_ctx_serve_thread_arg {
lm_ctx_serve_callback_t callback;
int sock;
struct sockaddr addr;
lm_mptp_t packet;
lm_pool_t *pool;
lm_ctx_serve_callback_t callback;
lm_ctx_t *ctx;
void *data;
};
void __lm_ctx_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockaddr *addr) {
switch (MPTP_FLAGS_CODE(packet)) {
void __lm_ctx_serve_thread(void *_arg) {
struct lm_ctx_serve_thread_arg *arg = _arg;
bool success = false;
lm_mptp_t packet;
if(!lm_mptp_server_recv(arg->sock, &packet)){
pdebug(__func__, "%x: failed to receive packet (%s)", arg->addr, lm_strerror());
return lm_mptp_close(arg->sock);
}
if (!lm_mptp_server_verify(&packet)) {
pdebug(__func__, "%x: closing connection, failed to verify (%s)", arg->addr, lm_strerror());
return lm_mptp_close(arg->sock);
}
char hostname[packet.header.host_size + 1]; // +1 for NULL terminator
char path[packet.header.data_size + 1], *ppath = path;
if (!lm_mptp_get_host(&packet, hostname)) {
pdebug(__func__, "%x: closing connection, failed to get hostname (%s)", arg->addr, lm_strerror());
goto end;
}
if (!lm_mptp_get_data(&packet, path)) {
pdebug(__func__, "%x: closing connection, failed to get path (%s)", arg->addr, lm_strerror());
goto end;
}
if(MPTP_FLAGS_CODE(&packet) == MPTP_C2S_PULL && (ppath = dirname(path)) == NULL){
pdebug(__func__, "%x: closing connection, failed to get dirname (%s)", strerror(errno));
goto end;
}
lm_pool_t *pool = lm_ctx_pool_by_url(arg->ctx, hostname, ppath);
if (NULL == pool) {
pdebug(__func__, "%x: unknown pool (%s), closing connection", arg->addr, hostname);
lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(arg->sock, &packet);
goto end;
}
if(lm_pool_path_is_empty(pool)){
pdebug(__func__, "%x: requested pool (%s) have empty paths, closing connection", arg->addr, pool->name);
lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(arg->sock, &packet);
goto end;
}
if(!pool->loaded){
pdebug(__func__, "%x: requested pool (%s) is not loaded, closing connection", arg->addr, pool->name);
lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(arg->sock, &packet);
goto end;
}
success = true;
switch (MPTP_FLAGS_CODE(&packet)) {
// response PING with PONG
case MPTP_C2S_PING:
pdebug(__func__, "(%s) PING: returning PONG", pool->name);
lm_mptp_init(packet, false, MPTP_S2C_PONG, true);
lm_mptp_server_send(sock, packet, addr);
pdebug(__func__, "(%x) PING %s: returning PONG", arg->addr, pool->name);
lm_mptp_init(&packet, false, MPTP_S2C_PONG, true);
lm_mptp_server_send(arg->sock, &packet);
break;
// when INFO file is requested, send the file
case MPTP_C2S_INFO:
pdebug(__func__, "(%s) INFO: attempting to send info", pool->name);
lm_mptp_sendfile(sock, addr, pool->info_file, NULL, NULL);
pdebug(__func__, "(%x) INFO %s: attempting to send info", arg->addr, pool->name);
lm_mptp_sendfile(arg->sock, pool->info_file, NULL, NULL);
break;
// when LIST file is requested, send the file
case MPTP_C2S_LIST:
pdebug(__func__, "(%s) LIST: attempting to send list", pool->name);
lm_mptp_sendfile(sock, addr, pool->list_file, NULL, NULL);
pdebug(__func__, "(%x) LIST %s: attempting to send list", arg->addr, pool->name);
lm_mptp_sendfile(arg->sock, pool->list_file, NULL, NULL);
break;
// when the request code is PULL, send the requested package archive and
@ -47,25 +102,25 @@ void __lm_ctx_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockadd
case MPTP_C2S_PULL:
// PULL request should contain package path,
// if path (stored in the data field) is empty it's an invalid request
if(packet->header.data_size <= 0){
lm_mptp_init(packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(sock, packet, addr);
if(packet.header.data_size <= 0){
lm_mptp_init(&packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(arg->sock, &packet);
break;
}
pdebug(__func__, "(%s) PULL: attempting to send package archive and signature", pool->name);
char path[packet->header.data_size + 1], *package = path;
pdebug(__func__, "(%x) PULL %s: attempting to send package archive and signature", arg->addr, pool->name);
char path[packet.header.data_size + 1], *package = path;
if(!lm_mptp_get_data(packet, path)){
if(!lm_mptp_get_data(&packet, path)){
// we should never be able to get here, if we do theres definetly a bug
pdebug(__func__, "(%s) PULL: skipping, failed to get path: %s", pool->name, lm_strerror());
pdebug(__func__, "(%x) PULL %s: skipping, failed to get path: %s", arg->addr, pool->name, lm_strerror());
break;
}
// if we can't get the package name, then theres something wrong with the request
if((package = basename(path)) == NULL){
lm_mptp_init(packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(sock, packet, addr);
lm_mptp_init(&packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(arg->sock, &packet);
break;
}
@ -75,30 +130,27 @@ void __lm_ctx_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockadd
// if we can't parse the package name, request is invalid
if(!package_parse(package, name, version)){
lm_mptp_init(packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(sock, packet, addr);
lm_mptp_init(&packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(arg->sock, &packet);
break;
}
// if the package is not found in the pool, tell the client
if((pkg = lm_pool_package_find(pool, name, version)) == NULL){
lm_mptp_init(packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(sock, packet, addr);
lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(arg->sock, &packet);
break;
}
// send package archive and the signature file
lm_mptp_sendfile(sock, addr, pkg->archive, NULL, NULL);
lm_mptp_sendfile(sock, addr, pkg->signature, NULL, NULL);
lm_mptp_sendfile(arg->sock, pkg->archive, NULL, NULL);
lm_mptp_sendfile(arg->sock, pkg->signature, NULL, NULL);
break;
}
}
void __lm_ctx_serve_thread(void *_arg) {
struct lm_ctx_serve_thread_arg *arg = _arg;
if(NULL != arg->callback && !arg->callback(arg->pool, &arg->packet, &arg->addr, arg->data))
return free(arg);
__lm_ctx_serve(arg->pool, &arg->packet, arg->sock, &arg->addr);
end:
if(success && NULL != arg->callback)
arg->callback(pool, &packet, &arg->addr, arg->data);
free(arg);
}
@ -110,9 +162,8 @@ bool lm_ctx_serve(lm_ctx_t *ctx, char *addr, uint8_t threads, lm_ctx_serve_callb
char host[strlen(addr)+1];
struct sockaddr saddr;
lm_mptp_t packet;
uint16_t port;
int sock;
int sock = -1, c = -1;
lm_thpool_t tp;
lm_thpool_init(&tp, threads);
@ -128,61 +179,14 @@ bool lm_ctx_serve(lm_ctx_t *ctx, char *addr, uint8_t threads, lm_ctx_serve_callb
if ((sock = lm_mptp_server_listen(host, port)) < 0)
return false;
while (lm_mptp_server_recv(sock, &packet, &saddr)) {
if (!lm_mptp_server_verify(&packet)) {
pdebug(__func__, "skipping packet, failed to verify: %s", lm_strerror());
continue;
}
char hostname[packet.header.host_size + 1]; // +1 for NULL terminator
char path[packet.header.data_size + 1], *ppath = path;
if (!lm_mptp_get_host(&packet, hostname)) {
pdebug(__func__, "skipping packet, failed to get hostname: %s", lm_strerror());
continue;
}
if (!lm_mptp_get_data(&packet, path)) {
pdebug(__func__, "skipping packet, failed to get path: %s", lm_strerror());
continue;
}
if(MPTP_FLAGS_CODE(&packet) == MPTP_C2S_PULL && (ppath = dirname(path)) == NULL){
pdebug(__func__, "skipping packet, failed to get dirname: %s", strerror(errno));
continue;
}
lm_pool_t *pool = lm_ctx_pool_by_url(ctx, hostname, ppath);
if (NULL == pool) {
pdebug(__func__, "unknown pool (%s), closing connection", hostname);
lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(sock, &packet, &saddr);
continue;
}
if(lm_pool_path_is_empty(pool)){
pdebug(__func__, "requested pool (%s) have empty paths, closing connection", pool->name);
lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(sock, &packet, &saddr);
continue;
}
if(!pool->loaded){
pdebug(__func__, "requested pool (%s) is not loaded, closing connection", pool->name);
lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(sock, &packet, &saddr);
continue;
}
while ((c = lm_mptp_server_accept(sock, &saddr)) < 0) {
struct lm_ctx_serve_thread_arg *arg = malloc(sizeof(struct lm_ctx_serve_thread_arg));
memcpy(&arg->addr, &saddr, sizeof(struct sockaddr));
lm_mptp_copy(&arg->packet, &packet);
arg->ctx = ctx;
arg->callback = callback;
arg->data = data;
arg->pool = pool;
arg->sock = sock;
arg->sock = c;
pdebug(__func__, "adding new connection to the pool");
lm_thpool_add(&tp, __lm_ctx_serve_thread, arg);

View File

@ -165,6 +165,7 @@ void lm_error_set(lm_error_t code, ...) {
{.code = LM_ERR_ChdirFail, .desc = _("failed change directory: %s") },
{.code = LM_ERR_ExtractRootChdirFail, .desc = _("failed to change directory to root during extraction") },
{.code = LM_ERR_ExtractOldChdirFail, .desc = _("failed to change directory back from root during extraction")},
{.code = LM_ERR_MPTPAcceptFail, .desc = _("failed to accept the MPTP connection: %s") },
};
char *fmt = NULL;

View File

@ -108,7 +108,7 @@ int lm_mptp_socket(char *addr, uint16_t port, struct sockaddr *saddr) {
return -1;
}
if ((sock = socket(family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
if ((sock = socket(family, AF_INET, SOCK_STREAM)) < 0) {
lm_error_set(LM_ERR_MPTPSocketFail);
return -1;
}

View File

@ -2,8 +2,10 @@
#include "../../include/mptp.h"
#include "../../include/util.h"
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include <sys/socket.h>
int lm_mptp_server_listen(char *addr, uint16_t port) {
struct sockaddr saddr;
@ -23,6 +25,22 @@ int lm_mptp_server_listen(char *addr, uint16_t port) {
return sock;
}
int lm_mptp_server_accept(int sock, struct sockaddr *addr){
socklen_t sl = sizeof(struct sockaddr);
int s = -1;
if((s = accept(sock, addr, &sl) < 0)){
lm_error_set(LM_ERR_MPTPAcceptFail, strerror(errno));
s = -1;
}
return s;
}
void lm_mptp_server_close(int sock){
close(sock); // you didn't see that comming, did you?
}
bool lm_mptp_server_verify(lm_mptp_t *packet) {
if (!lm_mptp_verify(packet))
return false;
@ -45,20 +63,19 @@ bool lm_mptp_server_verify(lm_mptp_t *packet) {
return true;
}
bool lm_mptp_server_recv(int sock, lm_mptp_t *packet, struct sockaddr *addr) {
if (NULL == packet || NULL == addr) {
bool lm_mptp_server_recv(int sock, lm_mptp_t *packet) {
if (NULL == packet) {
lm_error_set(LM_ERR_ArgNULL);
return false;
}
char buffer[sizeof(packet->header) + MPTP_HOST_MAX + MPTP_DATA_MAX];
socklen_t socklen = sizeof(struct sockaddr);
ssize_t total = sizeof(buffer), used = 0;
bzero(buffer, sizeof(buffer));
bzero(packet, sizeof(lm_mptp_t));
if (recvfrom(sock, buffer, sizeof(buffer), 0, addr, &socklen) <= 0) {
if (recv(sock, buffer, sizeof(buffer), 0) <= 0) {
lm_error_set(LM_ERR_MPTPRecvFail);
return false;
}
@ -77,7 +94,7 @@ bool lm_mptp_server_recv(int sock, lm_mptp_t *packet, struct sockaddr *addr) {
return true;
}
bool lm_mptp_server_send(int sock, lm_mptp_t *packet, struct sockaddr *addr) {
bool lm_mptp_server_send(int sock, lm_mptp_t *packet) {
if (NULL == packet) {
lm_error_set(LM_ERR_ArgNULL);
return false;
@ -98,7 +115,6 @@ bool lm_mptp_server_send(int sock, lm_mptp_t *packet, struct sockaddr *addr) {
return false;
}
socklen_t addrlen = sizeof(struct sockaddr);
char buffer[sizeof(packet->header) + packet->header.host_size + packet->header.data_size];
ssize_t total = sizeof(buffer), used = 0;
@ -108,7 +124,7 @@ bool lm_mptp_server_send(int sock, lm_mptp_t *packet, struct sockaddr *addr) {
copy_to_buffer(buffer, packet->host, packet->header.host_size, &total, &used);
copy_to_buffer(buffer, packet->data, packet->header.data_size, &total, &used);
if (sendto(sock, buffer, sizeof(buffer), 0, addr, addrlen) < 0) {
if (send(sock, buffer, sizeof(buffer), 0) < 0) {
lm_error_set(LM_ERR_MPTPSendFail);
return false;
}

View File

@ -9,8 +9,8 @@
#include <stdlib.h>
#include <unistd.h>
bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_transfer_callback_t callback, void *data){
if (NULL == path || NULL == addr){
bool lm_mptp_sendfile(int sock, char *path, lm_mptp_transfer_callback_t callback, void *data){
if (NULL == path){
lm_error_set(LM_ERR_ArgNULL);
return false;
}
@ -49,7 +49,7 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_trans
}
packet.header.data_size = size;
lm_mptp_server_send(sock, &packet, addr);
lm_mptp_server_send(sock, &packet);
if(NULL != callback)
if(!callback(path, current, total, data))
@ -60,7 +60,7 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_trans
while ((read = fread(packet.data, 1, MPTP_DATA_MAX, file)) > 0) {
packet.header.data_size = read;
if(!lm_mptp_server_send(sock, &packet, addr))
if(!lm_mptp_server_send(sock, &packet))
goto end;
current += read;
@ -85,7 +85,7 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_trans
end:
if(NULL != file)
fclose(file);
lm_mptp_server_send(sock, &packet, addr);
lm_mptp_server_send(sock, &packet);
return ret;
}