194 lines
6.0 KiB
C
194 lines
6.0 KiB
C
#include "../../include/thpool.h"
|
|
#include "../../include/error.h"
|
|
#include "../../include/pool.h"
|
|
#include "../../include/util.h"
|
|
#include "../../include/ctx.h"
|
|
|
|
#include <errno.h>
|
|
#include <libgen.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
struct lm_ctx_serve_thread_arg {
|
|
int sock;
|
|
struct sockaddr addr;
|
|
lm_mptp_t packet;
|
|
lm_pool_t *pool;
|
|
lm_ctx_serve_callback_t callback;
|
|
void *data;
|
|
};
|
|
|
|
void __lm_ctx_serve(lm_pool_t *pool, lm_mptp_t *packet, int sock, struct sockaddr *addr) {
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
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)){
|
|
// 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());
|
|
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);
|
|
break;
|
|
}
|
|
|
|
size_t package_size = strlen(package);
|
|
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);
|
|
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);
|
|
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);
|
|
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);
|
|
free(arg);
|
|
}
|
|
|
|
bool lm_ctx_serve(lm_ctx_t *ctx, char *addr, uint8_t threads, lm_ctx_serve_callback_t callback, void *data){
|
|
if (NULL == addr || threads < 0) {
|
|
lm_error_set(LM_ERR_ArgNULL);
|
|
return false;
|
|
}
|
|
|
|
char host[strlen(addr)+1];
|
|
struct sockaddr saddr;
|
|
lm_mptp_t packet;
|
|
uint16_t port;
|
|
int sock;
|
|
lm_thpool_t tp;
|
|
|
|
lm_thpool_init(&tp, threads);
|
|
|
|
if (!parse_host(addr, host, &port))
|
|
return false;
|
|
|
|
if (port == 0) {
|
|
lm_error_set(LM_ERR_NoPort);
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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->callback = callback;
|
|
arg->data = data;
|
|
arg->pool = pool;
|
|
arg->sock = sock;
|
|
|
|
pdebug(__func__, "adding new connection to the pool");
|
|
lm_thpool_add(&tp, __lm_ctx_serve_thread, arg);
|
|
}
|
|
|
|
lm_thpool_stop(&tp);
|
|
return true;
|
|
}
|