From 75fa38f1d77b9a3cbd875c12cbb4da13f9e4e17e Mon Sep 17 00:00:00 2001 From: ngn Date: Wed, 7 Aug 2024 04:49:33 +0300 Subject: [PATCH] update: migrating MPTP to TCP --- include/error.h | 1 + include/mptp.h | 8 +- locale/tr/LC_MESSAGES/libmp.po | 7 +- src/ctx/serve.c | 182 +++++++++++++++++---------------- src/error.c | 1 + src/mptp/mptp.c | 2 +- src/mptp/server.c | 30 ++++-- src/mptp/util.c | 16 +-- 8 files changed, 138 insertions(+), 109 deletions(-) diff --git a/include/error.h b/include/error.h index 016866d..75b2879 100644 --- a/include/error.h +++ b/include/error.h @@ -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 { diff --git a/include/mptp.h b/include/mptp.h index 0813367..edd78a0 100644 --- a/include/mptp.h +++ b/include/mptp.h @@ -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); diff --git a/locale/tr/LC_MESSAGES/libmp.po b/locale/tr/LC_MESSAGES/libmp.po index c3a2b56..d2c7aa0 100644 --- a/locale/tr/LC_MESSAGES/libmp.po +++ b/locale/tr/LC_MESSAGES/libmp.po @@ -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 \n" "Language-Team: LANGUAGE \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 "" diff --git a/src/ctx/serve.c b/src/ctx/serve.c index e20d768..d49a49d 100644 --- a/src/ctx/serve.c +++ b/src/ctx/serve.c @@ -12,93 +12,145 @@ #include 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 // requested package signature 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; - 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 - 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; } 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; // 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); diff --git a/src/error.c b/src/error.c index a1fc9ad..5965a10 100644 --- a/src/error.c +++ b/src/error.c @@ -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; diff --git a/src/mptp/mptp.c b/src/mptp/mptp.c index d1f9680..11e9499 100644 --- a/src/mptp/mptp.c +++ b/src/mptp/mptp.c @@ -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; } diff --git a/src/mptp/server.c b/src/mptp/server.c index 6b05344..3d6d8de 100644 --- a/src/mptp/server.c +++ b/src/mptp/server.c @@ -2,8 +2,10 @@ #include "../../include/mptp.h" #include "../../include/util.h" +#include #include #include +#include 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; } diff --git a/src/mptp/util.c b/src/mptp/util.c index 899be9b..39e30fe 100644 --- a/src/mptp/util.c +++ b/src/mptp/util.c @@ -9,8 +9,8 @@ #include #include -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; @@ -68,7 +68,7 @@ bool lm_mptp_sendfile(int sock, struct sockaddr *addr, char *path, lm_mptp_trans if(NULL != callback) if(!callback(path, current, st.st_size, data)) goto end; - + 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: if(NULL != file) fclose(file); - lm_mptp_server_send(sock, &packet, addr); + lm_mptp_server_send(sock, &packet); 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); goto end; } - + if(NULL != callback) if(!callback(path, current, total, data)) 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); goto end; } - + if(MPTP_IS_LAST(&packet)) break;