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_ChdirFail = 146,
LM_ERR_ExtractRootChdirFail = 147, LM_ERR_ExtractRootChdirFail = 147,
LM_ERR_ExtractOldChdirFail = 148, LM_ERR_ExtractOldChdirFail = 148,
LM_ERR_MPTPAcceptFail = 149,
} lm_error_t; } lm_error_t;
typedef struct lm_error_desc { 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); 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_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_verify(lm_mptp_t *packet);
bool lm_mptp_server_recv(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, struct sockaddr *addr); 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); bool lm_mptp_recvfile(int sock, char *path, lm_mptp_transfer_callback_t callback, void *data);

View File

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

View File

@ -12,93 +12,145 @@
#include <stdbool.h> #include <stdbool.h>
struct lm_ctx_serve_thread_arg { struct lm_ctx_serve_thread_arg {
lm_ctx_serve_callback_t callback;
int sock; int sock;
struct sockaddr addr; struct sockaddr addr;
lm_mptp_t packet; lm_ctx_t *ctx;
lm_pool_t *pool;
lm_ctx_serve_callback_t callback;
void *data; void *data;
}; };
void __lm_ctx_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockaddr *addr) { void __lm_ctx_serve_thread(void *_arg) {
switch (MPTP_FLAGS_CODE(packet)) { 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 // response PING with PONG
case MPTP_C2S_PING: case MPTP_C2S_PING:
pdebug(__func__, "(%s) PING: returning PONG", pool->name); pdebug(__func__, "(%x) PING %s: returning PONG", arg->addr, pool->name);
lm_mptp_init(packet, false, MPTP_S2C_PONG, true); lm_mptp_init(&packet, false, MPTP_S2C_PONG, true);
lm_mptp_server_send(sock, packet, addr); lm_mptp_server_send(arg->sock, &packet);
break; break;
// when INFO file is requested, send the file // when INFO file is requested, send the file
case MPTP_C2S_INFO: case MPTP_C2S_INFO:
pdebug(__func__, "(%s) INFO: attempting to send info", pool->name); pdebug(__func__, "(%x) INFO %s: attempting to send info", arg->addr, pool->name);
lm_mptp_sendfile(sock, addr, pool->info_file, NULL, NULL); lm_mptp_sendfile(arg->sock, pool->info_file, NULL, NULL);
break; break;
// when LIST file is requested, send the file // when LIST file is requested, send the file
case MPTP_C2S_LIST: case MPTP_C2S_LIST:
pdebug(__func__, "(%s) LIST: attempting to send list", pool->name); pdebug(__func__, "(%x) LIST %s: attempting to send list", arg->addr, pool->name);
lm_mptp_sendfile(sock, addr, pool->list_file, NULL, NULL); lm_mptp_sendfile(arg->sock, pool->list_file, NULL, NULL);
break; break;
// when the request code is PULL, send the requested package archive and // when the request code is PULL, send the requested package archive and
// requested package signature // requested package signature
case MPTP_C2S_PULL: case MPTP_C2S_PULL:
// PULL request should contain package path, // PULL request should contain package path,
// if path (stored in the data field) is empty it's an invalid request // if path (stored in the data field) is empty it's an invalid request
if(packet->header.data_size <= 0){ if(packet.header.data_size <= 0){
lm_mptp_init(packet, false, MPTP_S2C_WHAT, true); lm_mptp_init(&packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(sock, packet, addr); lm_mptp_server_send(arg->sock, &packet);
break; break;
} }
pdebug(__func__, "(%s) PULL: attempting to send package archive and signature", pool->name);
char path[packet->header.data_size + 1], *package = path;
if(!lm_mptp_get_data(packet, 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)){
// we should never be able to get here, if we do theres definetly a bug // 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; break;
} }
// if we can't get the package name, then theres something wrong with the request // if we can't get the package name, then theres something wrong with the request
if((package = basename(path)) == NULL){ if((package = basename(path)) == NULL){
lm_mptp_init(packet, false, MPTP_S2C_WHAT, true); lm_mptp_init(&packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(sock, packet, addr); lm_mptp_server_send(arg->sock, &packet);
break; break;
} }
size_t package_size = strlen(package); size_t package_size = strlen(package);
char name[package_size+1], version[package_size+1]; char name[package_size+1], version[package_size+1];
lm_pkg_t *pkg = NULL; lm_pkg_t *pkg = NULL;
// if we can't parse the package name, request is invalid // if we can't parse the package name, request is invalid
if(!package_parse(package, name, version)){ if(!package_parse(package, name, version)){
lm_mptp_init(packet, false, MPTP_S2C_WHAT, true); lm_mptp_init(&packet, false, MPTP_S2C_WHAT, true);
lm_mptp_server_send(sock, packet, addr); lm_mptp_server_send(arg->sock, &packet);
break; break;
} }
// if the package is not found in the pool, tell the client // if the package is not found in the pool, tell the client
if((pkg = lm_pool_package_find(pool, name, version)) == NULL){ if((pkg = lm_pool_package_find(pool, name, version)) == NULL){
lm_mptp_init(packet, false, MPTP_S2C_BRUH, true); lm_mptp_init(&packet, false, MPTP_S2C_BRUH, true);
lm_mptp_server_send(sock, packet, addr); lm_mptp_server_send(arg->sock, &packet);
break; break;
} }
// send package archive and the signature file // send package archive and the signature file
lm_mptp_sendfile(sock, addr, pkg->archive, NULL, NULL); lm_mptp_sendfile(arg->sock, pkg->archive, NULL, NULL);
lm_mptp_sendfile(sock, addr, pkg->signature, NULL, NULL); lm_mptp_sendfile(arg->sock, pkg->signature, NULL, NULL);
break; break;
} }
}
void __lm_ctx_serve_thread(void *_arg) { end:
struct lm_ctx_serve_thread_arg *arg = _arg; if(success && NULL != arg->callback)
if(NULL != arg->callback && !arg->callback(arg->pool, &arg->packet, &arg->addr, arg->data)) arg->callback(pool, &packet, &arg->addr, arg->data);
return free(arg);
__lm_ctx_serve(arg->pool, &arg->packet, arg->sock, &arg->addr);
free(arg); 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]; char host[strlen(addr)+1];
struct sockaddr saddr; struct sockaddr saddr;
lm_mptp_t packet;
uint16_t port; uint16_t port;
int sock; int sock = -1, c = -1;
lm_thpool_t tp; lm_thpool_t tp;
lm_thpool_init(&tp, threads); 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) if ((sock = lm_mptp_server_listen(host, port)) < 0)
return false; return false;
while (lm_mptp_server_recv(sock, &packet, &saddr)) { while ((c = lm_mptp_server_accept(sock, &saddr)) < 0) {
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;
}
struct lm_ctx_serve_thread_arg *arg = malloc(sizeof(struct lm_ctx_serve_thread_arg)); struct lm_ctx_serve_thread_arg *arg = malloc(sizeof(struct lm_ctx_serve_thread_arg));
memcpy(&arg->addr, &saddr, sizeof(struct sockaddr)); memcpy(&arg->addr, &saddr, sizeof(struct sockaddr));
lm_mptp_copy(&arg->packet, &packet);
arg->ctx = ctx;
arg->callback = callback; arg->callback = callback;
arg->data = data; arg->data = data;
arg->pool = pool; arg->sock = c;
arg->sock = sock;
pdebug(__func__, "adding new connection to the pool"); pdebug(__func__, "adding new connection to the pool");
lm_thpool_add(&tp, __lm_ctx_serve_thread, arg); 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_ChdirFail, .desc = _("failed change directory: %s") },
{.code = LM_ERR_ExtractRootChdirFail, .desc = _("failed to change directory to root during extraction") }, {.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_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; char *fmt = NULL;

View File

@ -108,7 +108,7 @@ int lm_mptp_socket(char *addr, uint16_t port, struct sockaddr *saddr) {
return -1; 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); lm_error_set(LM_ERR_MPTPSocketFail);
return -1; return -1;
} }

View File

@ -2,8 +2,10 @@
#include "../../include/mptp.h" #include "../../include/mptp.h"
#include "../../include/util.h" #include "../../include/util.h"
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <sys/socket.h>
int lm_mptp_server_listen(char *addr, uint16_t port) { int lm_mptp_server_listen(char *addr, uint16_t port) {
struct sockaddr saddr; struct sockaddr saddr;
@ -23,6 +25,22 @@ int lm_mptp_server_listen(char *addr, uint16_t port) {
return sock; 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) { bool lm_mptp_server_verify(lm_mptp_t *packet) {
if (!lm_mptp_verify(packet)) if (!lm_mptp_verify(packet))
return false; return false;
@ -45,20 +63,19 @@ bool lm_mptp_server_verify(lm_mptp_t *packet) {
return true; return true;
} }
bool lm_mptp_server_recv(int sock, lm_mptp_t *packet, struct sockaddr *addr) { bool lm_mptp_server_recv(int sock, lm_mptp_t *packet) {
if (NULL == packet || NULL == addr) { if (NULL == packet) {
lm_error_set(LM_ERR_ArgNULL); lm_error_set(LM_ERR_ArgNULL);
return false; return false;
} }
char buffer[sizeof(packet->header) + MPTP_HOST_MAX + MPTP_DATA_MAX]; char buffer[sizeof(packet->header) + MPTP_HOST_MAX + MPTP_DATA_MAX];
socklen_t socklen = sizeof(struct sockaddr);
ssize_t total = sizeof(buffer), used = 0; ssize_t total = sizeof(buffer), used = 0;
bzero(buffer, sizeof(buffer)); bzero(buffer, sizeof(buffer));
bzero(packet, sizeof(lm_mptp_t)); 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); lm_error_set(LM_ERR_MPTPRecvFail);
return false; return false;
} }
@ -77,7 +94,7 @@ bool lm_mptp_server_recv(int sock, lm_mptp_t *packet, struct sockaddr *addr) {
return true; 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) { if (NULL == packet) {
lm_error_set(LM_ERR_ArgNULL); lm_error_set(LM_ERR_ArgNULL);
return false; return false;
@ -98,7 +115,6 @@ bool lm_mptp_server_send(int sock, lm_mptp_t *packet, struct sockaddr *addr) {
return false; return false;
} }
socklen_t addrlen = sizeof(struct sockaddr);
char buffer[sizeof(packet->header) + packet->header.host_size + packet->header.data_size]; char buffer[sizeof(packet->header) + packet->header.host_size + packet->header.data_size];
ssize_t total = sizeof(buffer), used = 0; 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->host, packet->header.host_size, &total, &used);
copy_to_buffer(buffer, packet->data, packet->header.data_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); lm_error_set(LM_ERR_MPTPSendFail);
return false; return false;
} }

View File

@ -9,8 +9,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
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){
if (NULL == path || NULL == addr){ if (NULL == path){
lm_error_set(LM_ERR_ArgNULL); lm_error_set(LM_ERR_ArgNULL);
return false; 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; packet.header.data_size = size;
lm_mptp_server_send(sock, &packet, addr); lm_mptp_server_send(sock, &packet);
if(NULL != callback) if(NULL != callback)
if(!callback(path, current, total, data)) 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) { while ((read = fread(packet.data, 1, MPTP_DATA_MAX, file)) > 0) {
packet.header.data_size = read; packet.header.data_size = read;
if(!lm_mptp_server_send(sock, &packet, addr)) if(!lm_mptp_server_send(sock, &packet))
goto end; goto end;
current += read; current += read;
@ -68,7 +68,7 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_trans
if(NULL != callback) if(NULL != callback)
if(!callback(path, current, st.st_size, data)) if(!callback(path, current, st.st_size, data))
goto end; goto end;
lm_mptp_init(&packet, false, MPTP_S2C_COOL, false); lm_mptp_init(&packet, false, MPTP_S2C_COOL, false);
} }
@ -85,7 +85,7 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_trans
end: end:
if(NULL != file) if(NULL != file)
fclose(file); fclose(file);
lm_mptp_server_send(sock, &packet, addr); lm_mptp_server_send(sock, &packet);
return ret; return ret;
} }
@ -127,7 +127,7 @@ bool lm_mptp_recvfile(int sock, char *path, lm_mptp_transfer_callback_t callback
lm_error_set(LM_ERR_RecvBadSize); lm_error_set(LM_ERR_RecvBadSize);
goto end; goto end;
} }
if(NULL != callback) if(NULL != callback)
if(!callback(path, current, total, data)) if(!callback(path, current, total, data))
goto end; goto end;
@ -140,7 +140,7 @@ bool lm_mptp_recvfile(int sock, char *path, lm_mptp_transfer_callback_t callback
lm_error_set(LM_ERR_RecvBadCode); lm_error_set(LM_ERR_RecvBadCode);
goto end; goto end;
} }
if(MPTP_IS_LAST(&packet)) if(MPTP_IS_LAST(&packet))
break; break;