1 Commits

Author SHA1 Message Date
staylightblow8
da2830c31e msg: fix some problem
Type: fix

Signed-off-by: staylightblow8 <liudf0716@gmail.com>
2023-11-04 11:51:43 +08:00
15 changed files with 97 additions and 12429 deletions

View File

@@ -80,14 +80,11 @@ set(src_xfrpc
proxy.c
tcpmux.c
tcp_redir.c
mongoose.c
)
set(src_xfrpc_plugins
plugins/telnetd.c
plugins/instaloader.c
plugins/httpd.c
plugins/youtubedl.c)
plugins/instaloader.c)
set(libs
ssl

View File

@@ -106,8 +106,6 @@ struct proxy_service {
char *plugin_user;
char *plugin_pwd;
char *s_root_dir;
// private arguments
UT_hash_handle hh;
};

View File

@@ -194,8 +194,6 @@ new_proxy_service(const char *name)
ps->plugin_user = NULL;
ps->plugin_pwd = NULL;
ps->s_root_dir = NULL;
return ps;
}
@@ -325,32 +323,16 @@ process_plugin_conf(struct proxy_service *ps)
if (ps->local_port == 0)
ps->local_port = XFRPC_PLUGIN_INSTALOADER_PORT;
if (ps->remote_port == 0)
ps->remote_port = XFRPC_PLUGIN_INSTALOADER_REMOTE_PORT;
ps->remote_port = XFRPC_PLUGIN_INSTALOADER_ROMOTE_PORT;
if (ps->local_ip == NULL)
ps->local_ip = strdup("127.0.0.1");
} else if (strcmp(ps->plugin, "instaloader_client") == 0) {
if (ps->local_port == 0)
ps->local_port = XFRPC_PLUGIN_INSTALOADER_PORT;
if (ps->remote_port == 0)
ps->remote_port == XFRPC_PLUGIN_INSTALOADER_REMOTE_PORT;
ps->remote_port == XFRPC_PLUGIN_INSTALOADER_ROMOTE_PORT;
if (ps->local_ip == NULL)
ps->local_ip = strdup("0.0.0.0");
} else if (strcmp(ps->plugin, "youtubedl") == 0) {
if (ps->local_port == 0)
ps->local_port = XFRPC_PLUGIN_YOUTUBEDL_PORT;
if (ps->remote_port == 0)
ps->remote_port = XFRPC_PLUGIN_YOUTUBEDL_REMOTE_PORT;
if (ps->local_ip == NULL)
ps->local_ip = strdup("127.0.0.1");
} else if (strcmp(ps->plugin, "httpd") == 0) {
if (ps->local_port == 0)
ps->local_port = XFRPC_PLUGIN_HTTPD_PORT;
if (ps->local_ip == NULL)
ps->local_ip = strdup("127.0.0.1");
if (ps->remote_port == 0)
ps->remote_port = XFRPC_PLUGIN_HTTPD_REMOTE_PORT;
if (ps->s_root_dir == NULL)
ps->s_root_dir = strdup("/var/www/html");
} else {
debug(LOG_INFO, "plugin %s is not supportted", ps->plugin);
}
@@ -430,8 +412,6 @@ proxy_service_handler(void *user, const char *sect, const char *nm, const char *
ps->plugin_user = strdup(value);
} else if (MATCH_NAME("plugin_pwd")) {
ps->plugin_pwd = strdup(value);
} else if (MATCH_NAME("root_dir")) {
ps->s_root_dir = strdup(value);
} else {
debug(LOG_ERR, "unknown option %s in section %s", nm, section);
SAFE_FREE(section);

View File

@@ -33,11 +33,7 @@
#define DEFAULT_SOCKS5_PORT 1980
#define XFRPC_PLUGIN_TELNETD_PORT 23
#define XFRPC_PLUGIN_INSTALOADER_PORT 10000
#define XFRPC_PLUGIN_INSTALOADER_REMOTE_PORT 10001
#define XFRPC_PLUGIN_YOUTUBEDL_PORT 20002
#define XFRPC_PLUGIN_YOUTUBEDL_REMOTE_PORT 20003
#define XFRPC_PLUGIN_HTTPD_PORT 8000
#define XFRPC_PLUGIN_HTTPD_REMOTE_PORT 8001
#define XFRPC_PLUGIN_INSTALOADER_ROMOTE_PORT 10001
#define FTP_RMT_CTL_PROXY_SUFFIX "_ftp_remote_ctl_proxy"

View File

@@ -72,8 +72,7 @@ void init_login()
struct utsname uname_buf;
if (uname(&uname_buf)) {
debug(LOG_ERR, "error: get system info failed!");
exit(0);
return;
}
c_login->version = strdup(PROTOCOL_VERESION);

View File

@@ -31,7 +31,6 @@
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <time.h>
#include "uthash.h"
@@ -42,7 +41,7 @@ struct login {
char *arch;
char *user;
char *privilege_key;
time_t timestamp;
long int timestamp;
char *run_id;
char *metas;
int pool_count;

10039
mongoose.c

File diff suppressed because it is too large Load Diff

1915
mongoose.h

File diff suppressed because it is too large Load Diff

137
msg.c
View File

@@ -138,7 +138,8 @@ login_request_marshal(char **msg)
return 0;
struct login *lg = get_common_login_config();
if (!lg) {
if (!lg)
{
json_object_put(j_login_req);
return 0;
}
@@ -156,18 +157,15 @@ login_request_marshal(char **msg)
JSON_MARSHAL_TYPE(j_login_req, "user", string, SAFE_JSON_STRING(lg->user));
JSON_MARSHAL_TYPE(j_login_req, "privilege_key", string, SAFE_JSON_STRING(lg->privilege_key));
if (sizeof(time_t) == 4) {
JSON_MARSHAL_TYPE(j_login_req, "timestamp", int, lg->timestamp);
} else {
JSON_MARSHAL_TYPE(j_login_req, "timestamp", int64, lg->timestamp);
}
JSON_MARSHAL_TYPE(j_login_req, "timestamp", int64, lg->timestamp);
JSON_MARSHAL_TYPE(j_login_req, "run_id", string, SAFE_JSON_STRING(lg->run_id));
JSON_MARSHAL_TYPE(j_login_req, "pool_count", int, lg->pool_count);
json_object_object_add(j_login_req, "metas", NULL);
const char *tmp = NULL;
tmp = json_object_to_json_string(j_login_req);
if (tmp && strlen(tmp) > 0) {
if (tmp && strlen(tmp) > 0)
{
nret = strlen(tmp);
*msg = strdup(tmp);
assert(*msg);
@@ -190,9 +188,12 @@ int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
JSON_MARSHAL_TYPE(j_np_req, "proxy_name", string, np_req->proxy_name);
// if proxy_type is socks5, set the proxy_type to tcp
if (strcmp(np_req->proxy_type, "socks5") == 0 || strcmp(np_req->proxy_type, "mstsc") == 0) {
if (strcmp(np_req->proxy_type, "socks5") == 0 || strcmp(np_req->proxy_type, "mstsc") == 0)
{
JSON_MARSHAL_TYPE(j_np_req, "proxy_type", string, "tcp");
} else {
}
else
{
JSON_MARSHAL_TYPE(j_np_req, "proxy_type", string, np_req->proxy_type);
}
JSON_MARSHAL_TYPE(j_np_req, "use_encryption", boolean, np_req->use_encryption);
@@ -202,28 +203,38 @@ int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
if (strcmp(np_req->proxy_type, "tcp") == 0 ||
strcmp(np_req->proxy_type, "http") == 0 ||
strcmp(np_req->proxy_type, "https") == 0 ||
strcmp(np_req->proxy_type, "socks5") == 0) {
strcmp(np_req->proxy_type, "socks5") == 0)
{
if (np_req->group) {
if (np_req->group)
{
JSON_MARSHAL_TYPE(j_np_req, "group", string, np_req->group);
}
if (np_req->group_key) {
}
if (np_req->group_key)
{
JSON_MARSHAL_TYPE(j_np_req, "group_key", string, np_req->group_key);
}
}
if (is_ftp_proxy(np_req)) {
if (is_ftp_proxy(np_req))
{
JSON_MARSHAL_TYPE(j_np_req, "remote_data_port", int, np_req->remote_data_port);
}
if (np_req->custom_domains) {
if (np_req->custom_domains)
{
fill_custom_domains(j_np_req, np_req->custom_domains);
json_object_object_add(j_np_req, "remote_port", NULL);
} else {
}
else
{
json_object_object_add(j_np_req, "custom_domains", NULL);
if (np_req->remote_port != -1) {
if (np_req->remote_port != -1)
{
JSON_MARSHAL_TYPE(j_np_req, "remote_port", int, np_req->remote_port);
} else {
}
else
{
json_object_object_add(j_np_req, "remote_port", NULL);
}
}
@@ -231,14 +242,18 @@ int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
JSON_MARSHAL_TYPE(j_np_req, "subdomain", string, SAFE_JSON_STRING(np_req->subdomain));
json_object *j_location_array = json_object_new_array();
if (np_req->locations) {
if (np_req->locations)
{
json_object_object_add(j_np_req, "locations", j_location_array);
path = strtok_r(np_req->locations, delimiter, &save);
while (path) {
while (path)
{
json_object_array_add(j_location_array, json_object_new_string(path));
path = strtok_r(NULL, delimiter, &save);
}
} else {
}
else
{
json_object_object_add(j_np_req, "locations", NULL);
}
@@ -247,7 +262,8 @@ int new_proxy_service_marshal(const struct proxy_service *np_req, char **msg)
JSON_MARSHAL_TYPE(j_np_req, "http_pwd", string, SAFE_JSON_STRING(np_req->http_pwd));
tmp = json_object_to_json_string(j_np_req);
if (tmp && strlen(tmp) > 0) {
if (tmp && strlen(tmp) > 0)
{
nret = strlen(tmp);
*msg = strdup(tmp);
assert(*msg);
@@ -267,7 +283,8 @@ int new_work_conn_marshal(const struct work_conn *work_c, char **msg)
JSON_MARSHAL_TYPE(j_new_work_conn, "run_id", string, SAFE_JSON_STRING(work_c->run_id));
tmp = json_object_to_json_string(j_new_work_conn);
if (tmp && strlen(tmp) > 0) {
if (tmp && strlen(tmp) > 0)
{
nret = strlen(tmp);
*msg = strdup(tmp);
assert(*msg);
@@ -294,7 +311,8 @@ new_proxy_resp_unmarshal(const char *jres)
npr->run_id = strdup(json_object_get_string(npr_run_id));
struct json_object *npr_proxy_remote_addr = NULL;
if (!json_object_object_get_ex(j_np_res, "remote_addr", &npr_proxy_remote_addr)) {
if (!json_object_object_get_ex(j_np_res, "remote_addr", &npr_proxy_remote_addr))
{
free(npr->run_id);
free(npr);
npr = NULL;
@@ -303,13 +321,15 @@ new_proxy_resp_unmarshal(const char *jres)
const char *remote_addr = json_object_get_string(npr_proxy_remote_addr);
char *port = strrchr(remote_addr, ':');
if (port) {
if (port)
{
port++;
npr->remote_port = atoi(port);
}
struct json_object *npr_proxy_name = NULL;
if (!json_object_object_get_ex(j_np_res, "proxy_name", &npr_proxy_name)) {
if (!json_object_object_get_ex(j_np_res, "proxy_name", &npr_proxy_name))
{
free(npr->run_id);
free(npr);
npr = NULL;
@@ -320,7 +340,8 @@ new_proxy_resp_unmarshal(const char *jres)
assert(npr->proxy_name);
struct json_object *npr_error = NULL;
if (!json_object_object_get_ex(j_np_res, "error", &npr_error)) {
if (!json_object_object_get_ex(j_np_res, "error", &npr_error))
{
free(npr->run_id);
free(npr->proxy_name);
free(npr);
@@ -347,7 +368,8 @@ login_resp_unmarshal(const char *jres)
assert(lr);
struct json_object *l_version = NULL;
if (!json_object_object_get_ex(j_lg_res, "version", &l_version)) {
if (!json_object_object_get_ex(j_lg_res, "version", &l_version))
{
free(lr);
lr = NULL;
goto END_ERROR;
@@ -357,7 +379,8 @@ login_resp_unmarshal(const char *jres)
assert(lr->version);
struct json_object *l_run_id = NULL;
if (!json_object_object_get_ex(j_lg_res, "run_id", &l_run_id)) {
if (!json_object_object_get_ex(j_lg_res, "run_id", &l_run_id))
{
free(lr->version);
free(lr);
lr = NULL;
@@ -368,7 +391,8 @@ login_resp_unmarshal(const char *jres)
assert(lr->run_id);
struct json_object *l_error = NULL;
if (!json_object_object_get_ex(j_lg_res, "error", &l_error)) {
if (!json_object_object_get_ex(j_lg_res, "error", &l_error))
{
free(lr->version);
free(lr->run_id);
free(lr);
@@ -395,7 +419,8 @@ start_work_conn_resp_unmarshal(const char *resp_msg)
assert(sr);
struct json_object *pn = NULL;
if (!json_object_object_get_ex(j_start_w_res, "proxy_name", &pn)) {
if (!json_object_object_get_ex(j_start_w_res, "proxy_name", &pn))
{
free(sr);
sr = NULL;
goto START_W_C_R_END;
@@ -419,7 +444,8 @@ control_response_unmarshal(const char *jres)
assert(ctl_res);
struct json_object *jtype = NULL;
if (!json_object_object_get_ex(j_ctl_res, "type", &jtype)) {
if (!json_object_object_get_ex(j_ctl_res, "type", &jtype))
{
free(ctl_res);
ctl_res = NULL;
goto END_ERROR;
@@ -427,7 +453,8 @@ control_response_unmarshal(const char *jres)
ctl_res->type = json_object_get_int(jtype);
struct json_object *jcode = NULL;
if (!json_object_object_get_ex(j_ctl_res, "code", &jcode)) {
if (!json_object_object_get_ex(j_ctl_res, "code", &jcode))
{
free(ctl_res);
ctl_res = NULL;
goto END_ERROR;
@@ -436,7 +463,8 @@ control_response_unmarshal(const char *jres)
ctl_res->code = json_object_get_int(jcode);
struct json_object *jmsg = NULL;
if (!json_object_object_get_ex(j_ctl_res, "msg", &jmsg)) {
if (!json_object_object_get_ex(j_ctl_res, "msg", &jmsg))
{
free(ctl_res);
ctl_res = NULL;
goto END_ERROR;
@@ -471,7 +499,8 @@ new_udp_packet_marshal(const struct udp_packet *udp, char **msg)
assert(content);
json_object_object_add(j_udp, "c", content);
if (udp->laddr) {
if (udp->laddr)
{
// laddr is a struct, parse it to json object and add to j_udp
struct json_object *j_laddr = json_object_new_object();
assert(j_laddr);
@@ -485,14 +514,17 @@ new_udp_packet_marshal(const struct udp_packet *udp, char **msg)
json_object *j_laddr_zone = json_object_new_string("");
assert(j_laddr_zone);
json_object_object_add(j_laddr, "Zone", j_laddr_zone);
} else {
}
else
{
// laddr is NULL, add null to j_udp
struct json_object *j_laddr = json_object_new_object();
assert(j_laddr);
json_object_object_add(j_udp, "l", j_laddr);
}
if (udp->raddr) {
if (udp->raddr)
{
// raddr is a struct, parse it to json object and add to j_udp
struct json_object *j_raddr = json_object_new_object();
assert(j_raddr);
@@ -506,7 +538,9 @@ new_udp_packet_marshal(const struct udp_packet *udp, char **msg)
json_object *j_raddr_zone = json_object_new_string("");
assert(j_raddr_zone);
json_object_object_add(j_raddr, "Zone", j_raddr_zone);
} else {
}
else
{
// raddr is NULL, add null to j_udp
struct json_object *j_raddr = json_object_new_object();
assert(j_raddr);
@@ -549,7 +583,8 @@ udp_packet_unmarshal(const char *msg)
assert(udp);
struct json_object *j_content = NULL;
if (!json_object_object_get_ex(j_udp, "c", &j_content)) {
if (!json_object_object_get_ex(j_udp, "c", &j_content))
{
goto END_ERROR;
}
@@ -557,21 +592,25 @@ udp_packet_unmarshal(const char *msg)
assert(udp->content);
struct json_object *j_laddr = NULL;
if (!json_object_object_get_ex(j_udp, "l", &j_laddr)) {
if (!json_object_object_get_ex(j_udp, "l", &j_laddr))
{
goto END_ERROR;
}
struct json_object *j_laddr_ip = NULL;
if (!json_object_object_get_ex(j_laddr, "IP", &j_laddr_ip)) {
if (!json_object_object_get_ex(j_laddr, "IP", &j_laddr_ip))
{
goto END_ERROR;
}
struct json_object *j_laddr_port = NULL;
if (!json_object_object_get_ex(j_laddr, "Port", &j_laddr_port)) {
if (!json_object_object_get_ex(j_laddr, "Port", &j_laddr_port))
{
goto END_ERROR;
}
struct json_object *j_laddr_zone = NULL;
if (!json_object_object_get_ex(j_laddr, "Zone", &j_laddr_zone)) {
if (!json_object_object_get_ex(j_laddr, "Zone", &j_laddr_zone))
{
goto END_ERROR;
}
@@ -584,22 +623,26 @@ udp_packet_unmarshal(const char *msg)
assert(udp->laddr->zone);
struct json_object *j_raddr = NULL;
if (!json_object_object_get_ex(j_udp, "r", &j_raddr)) {
if (!json_object_object_get_ex(j_udp, "r", &j_raddr))
{
goto END_ERROR;
}
struct json_object *j_raddr_ip = NULL;
if (!json_object_object_get_ex(j_raddr, "IP", &j_raddr_ip)) {
if (!json_object_object_get_ex(j_raddr, "IP", &j_raddr_ip))
{
goto END_ERROR;
}
struct json_object *j_raddr_port = NULL;
if (!json_object_object_get_ex(j_raddr, "Port", &j_raddr_port)) {
if (!json_object_object_get_ex(j_raddr, "Port", &j_raddr_port))
{
goto END_ERROR;
}
struct json_object *j_raddr_zone = NULL;
if (!json_object_object_get_ex(j_raddr, "Zone", &j_raddr_zone)) {
if (!json_object_object_get_ex(j_raddr, "Zone", &j_raddr_zone))
{
goto END_ERROR;
}

View File

@@ -1,81 +0,0 @@
#include <pthread.h>
#include "../debug.h"
#include "../mongoose.h"
#include "httpd.h"
static const char *s_root_dir = ".";
static const char *s_listening_address = "http://0.0.0.0:8000";
static void
httpd_handler(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
{
if (ev == MG_EV_HTTP_MSG)
{
struct mg_http_message *hm = ev_data, tmp = {0};
struct mg_str unknown = mg_str_n("?", 1), *cl;
struct mg_http_serve_opts opts = {0};
opts.root_dir = s_root_dir;
mg_http_serve_dir(c, hm, &opts);
mg_http_parse((char *)c->send.buf, c->send.len, &tmp);
cl = mg_http_get_header(&tmp, "Content-Length");
if (cl == NULL)
cl = &unknown;
debug(LOG_INFO, "HTTP: %.*s %.*s %.*s %.*s\n",
(int)hm->method.len, hm->method.ptr,
(int)hm->uri.len, hm->uri.ptr,
(int)tmp.uri.len, tmp.uri.ptr,
(int)cl->len, cl->ptr);
}
(void)fn_data;
}
static void *
httpd_thread(void *arg)
{
char path[MG_PATH_MAX] = ".";
struct mg_mgr mgr;
struct mg_connection *c;
struct proxy_service *ps = (struct proxy_service *)arg;
mg_mgr_init(&mgr);
if ((c = mg_http_listen(&mgr, s_listening_address, httpd_handler, &mgr)) == NULL)
{
debug(LOG_ERR, "Cannot listen on %s. Use http://ADDR:PORT or :PORT",
s_listening_address);
exit(EXIT_FAILURE);
}
// Root directory must not contain double dots. Make it absolute
// Do the conversion only if the root dir spec does not contain overrides
if (strchr(ps->s_root_dir, ',') == NULL)
{
realpath(ps->s_root_dir, path);
s_root_dir = path;
}
debug(LOG_INFO, "Listening on : %s", s_listening_address);
debug(LOG_INFO, "Web root : [%s]", s_root_dir);
while (1)
mg_mgr_poll(&mgr, 1000);
mg_mgr_free(&mgr);
return NULL;
}
void start_httpd_service(struct proxy_service *ps)
{
// start a httpd service in a new thread
pthread_t thread;
if (pthread_create(&thread, NULL, httpd_thread, ps) != 0)
{
debug(LOG_ERR, "Failed to create thread\n");
exit(-1);
}
//detach thread
pthread_detach(thread);
return;
}

View File

@@ -1,8 +0,0 @@
#ifndef _HTTPD_H
#define _HTTPD_H
#include "../client.h"
void start_httpd_service(struct proxy_service *ps);
#endif

View File

@@ -1,289 +0,0 @@
#include <json-c/json.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <event2/http.h>
#include "../common.h"
#include "../debug.h"
#include "../config.h"
#include "youtubedl.h"
struct yt_dlp_param {
char action[10];
char profile[100];
};
// define yt-dlp worker function
static void *
yt_dlp_worker(void *param)
{
struct yt_dlp_param *p = (struct yt_dlp_param *)param;
debug(LOG_DEBUG, "yt-dlp: action: %s, url: %s\n", p->action, p->profile);
char cmd[512] = {0};
// create directory yt-dlp and change current directory to it
snprintf(cmd, sizeof(cmd), "mkdir -p yt-dlp && cd yt-dlp");
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
system(cmd);
if (strcmp(p->action, "download") == 0) {
// download profile
snprintf(cmd, sizeof(cmd), "yt-dlp %s", p->profile);
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
// use popen to execute cmd and get its output
FILE *fp = popen(cmd, "r");
if (fp == NULL) {
debug(LOG_ERR, "yt-dlp: popen failed\n");
free(param);
return NULL;
}
char buf[512] = {0};
while (fgets(buf, sizeof(buf), fp) != NULL) {
debug(LOG_DEBUG, "yt-dlp: %s", buf);
memset(buf, 0, sizeof(buf));
}
pclose(fp);
} else {
debug(LOG_ERR, "yt-dlp: unknown action: %s\n", p->action);
}
// free param
free(param);
return 0;
}
static int
parse_yt_dlp_command(char *json_data, struct yt_dlp_param *param)
{
// parse json data with json-c to param
json_object *jobj = json_tokener_parse(json_data);
if (jobj == NULL) {
debug(LOG_ERR, "yt-dlp: json_tokener_parse failed\n");
return -1;
}
// get action
json_object *jaction = NULL;
if (!json_object_object_get_ex(jobj, "action", &jaction)) {
debug(LOG_ERR, "yt-dlp: json_object_object_get_ex failed\n");
json_object_put(jobj);
return -1;
}
strcpy(param->action, json_object_get_string(jaction));
if (strcmp(param->action, "stop") == 0) {
json_object_put(jobj);
return 0;
}
// get profile
json_object *jprofile = NULL;
if (!json_object_object_get_ex(jobj, "profile", &jprofile)) {
debug(LOG_ERR, "yt-dlp: json_object_object_get_ex failed\n");
json_object_put(jobj);
return -1;
}
strcpy(param->profile, json_object_get_string(jprofile));
// free json object
json_object_put(jobj);
return 0;
}
static void
yt_dlp_response(struct evhttp_request *req, char *result)
{
struct evbuffer *resp = evbuffer_new();
evbuffer_add_printf(resp, "{\"status\": \"%s\"}", result);
evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "application/json");
evhttp_send_reply(req, HTTP_OK, "OK", resp);
}
// define yt-dlp read callback function
static void
yt_dlp_read_cb(struct evhttp_request *req, void *args)
{
#define BUFF_LEN 4096
// read data from bufferevent
char data[BUFF_LEN] = {0};
struct evbuffer *input = evhttp_request_get_input_buffer(req);
size_t len = evbuffer_get_length(input);
assert(len < BUFF_LEN);
if (len >= BUFF_LEN) {
debug(LOG_ERR, "yt-dlp: data length is too long\n");
yt_dlp_response(req, "data length is too long");
return;
}
debug(LOG_DEBUG, "yt-dlp: data: %s\n", data);
// parse http post and get its json data
evbuffer_copyout(input, data, len);
debug(LOG_DEBUG, "yt-dlp: data: %s\n", data);
struct yt_dlp_param *param = (struct yt_dlp_param *)malloc(sizeof(struct yt_dlp_param));
assert(param != NULL);
memset(param, 0, sizeof(struct yt_dlp_param));
int nret = parse_yt_dlp_command (data, param);
if (nret != 0) {
debug(LOG_ERR, "yt-dlp: parse_command failed\n");
free(param);
yt_dlp_response(req, "failed to parse command");
return;
}
// create a thread
pthread_t thread;
// create a thread attribute
pthread_attr_t attr;
// initialize thread attribute
pthread_attr_init(&attr);
// set thread attribute to detach
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// create a thread
pthread_create(&thread, &attr, yt_dlp_worker, param);
// destroy thread attribute
pthread_attr_destroy(&attr);
yt_dlp_response(req, "ok");
}
// define yt-dlp http post callback function
static void
http_post_cb(struct evhttp_request *req, void *arg)
{
// check http request method
if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) {
debug(LOG_ERR, "yt-dlp: http request method is not POST\n");
evhttp_send_error(req, HTTP_BADMETHOD, "Method Not Allowed");
return;
}
// Check the HTTP request content type
const char *content_type = evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type");
if (content_type == NULL || strcmp(content_type, "application/json") != 0) {
debug(LOG_ERR, "yt-dlp: http request content type is not application/json\n");
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
return;
}
// get json data from http request
yt_dlp_read_cb(req, arg);
}
static int
install_yt_dlp()
{
// if yt-dlp exists, return
if (access("/usr/local/bin/yt-dlp", F_OK) == 0) {
debug(LOG_DEBUG, "yt-dlp: yt-dlp exists\n");
return 0;
}
// install yt-dlp to /usr/local/bin
// download yt-dlp through curl or wget if any of them exists
char cmd[512] = {0};
if (access("/usr/bin/curl", F_OK) == 0) {
snprintf(cmd, sizeof(cmd), "sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp");
} else if (access("/usr/bin/wget", F_OK) == 0) {
snprintf(cmd, sizeof(cmd), "sudo wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O /usr/local/bin/yt-dlp");
} else {
debug(LOG_ERR, "yt-dlp: curl and wget are not installed\n");
return -1;
}
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
int nret = system(cmd);
if (nret != 0) {
debug(LOG_ERR, "yt-dlp: system failed\n");
return -1;
}
// change yt-dlp to executable
snprintf(cmd, sizeof(cmd), "sudo chmod a+rx /usr/local/bin/yt-dlp");
debug(LOG_DEBUG, "yt-dlp: cmd: %s\n", cmd);
nret = system(cmd);
if (nret != 0) {
debug(LOG_ERR, "yt-dlp: system failed\n");
return -1;
}
return 0;
}
// define yt-dlp service
static void *
yt_dlp_service(void *local_port)
{
// install yt-dlp
int nret = install_yt_dlp();
if (nret != 0) {
debug(LOG_ERR, "yt-dlp: install_yt_dlp failed\n");
return NULL;
}
uint16_t port = *(uint16_t *)local_port;
free(local_port);
// Initialize libevent
struct event_base *base = event_base_new();
if (!base) {
debug(LOG_ERR, "yt-dlp: Failed to initialize libevent\n");
return NULL;
}
// Create a new HTTP server
struct evhttp *http = evhttp_new(base);
if (!http) {
debug(LOG_ERR, "yt-dlp: Failed to create HTTP server\n");
return NULL;
}
if (evhttp_bind_socket(http, "0.0.0.0", port) != 0) {
debug(LOG_ERR, "yt-dlp: Failed to bind HTTP server to port %d\n", port);
return NULL;
}
debug(LOG_DEBUG, "yt-dlp: start youtube download service on port %d\n", port);
// Set up a callback function for handling HTTP requests
evhttp_set_cb(http, "/", http_post_cb, NULL);
// Start the event loop
event_base_dispatch(base);
// Clean up
evhttp_free(http);
event_base_free(base);
return NULL;
}
int
start_youtubedl_service(uint16_t local_port)
{
uint16_t *p = (uint16_t *)malloc(sizeof(uint16_t));
assert(p != NULL);
*p = local_port;
// create a thread
pthread_t thread;
// create a thread attribute
pthread_attr_t attr;
// initialize thread attribute
pthread_attr_init(&attr);
// set thread attribute to detach
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// create a thread
pthread_create(&thread, &attr, yt_dlp_service, (void *)p);
// destroy thread attribute
pthread_attr_destroy(&attr);
return 0;
}

View File

@@ -1,6 +0,0 @@
#ifndef _YOUTUBE_DL_H_
#define _YOUTUBE_DL_H_
int start_youtubedl_service(uint16_t local_port);
#endif

View File

@@ -1,7 +1,7 @@
#ifndef _VERSION_H_
#define _VERSION_H_
#define VERSION "2.12.656"
#define VERSION "2.9.644"
#define PROTOCOL_VERESION "0.43.0"
#define CLIENT_V 1

View File

@@ -50,7 +50,6 @@
#include "plugins/telnetd.h"
#include "plugins/instaloader.h"
#include "plugins/httpd.h"
static void start_xfrpc_local_service()
{
@@ -65,13 +64,8 @@ static void start_xfrpc_local_service()
} else if (strcmp(ps->plugin, "instaloader") == 0) {
// start instaloader service
start_instaloader_service(ps->local_port);
} else if (strcmp(ps->plugin, "youtubedl") == 0) {
// start youtubedl service
start_youtubedl_service(ps->local_port);
} else if (strcmp(ps->plugin, "instaloader_redir") == 0) {
start_tcp_redir_service(ps);
} else if (strcmp(ps->plugin, "httpd") == 0) {
start_httpd_service(ps);
} else {
debug(LOG_ERR, "start_xfrpc_local_service: unknown plugin %s\n", ps->plugin);
}