ByeDPIAndroid/app/src/main/cpp/native-lib.c
dovecoteescapee 88e1b75dd5
Improvements and fixes (#96)
Improvements and fixes:
- Added Hosts to UI editor
- Allowed not to specify DNS
- Changed the level of saved logs to Debug
- Fixed bug with Reset button
2024-08-19 01:09:08 +03:00

295 lines
7.6 KiB
C

#include <string.h>
#include <netdb.h>
#include <jni.h>
#include <android/log.h>
#include "byedpi/error.h"
#include "byedpi/proxy.h"
#include "byedpi/params.h"
#include "byedpi/packets.h"
#include "main.h"
#include "utils.h"
const enum demode DESYNC_METHODS[] = {
DESYNC_NONE,
DESYNC_SPLIT,
DESYNC_DISORDER,
DESYNC_FAKE,
DESYNC_OOB,
};
enum hosts_mode {
HOSTS_DISABLE,
HOSTS_BLACKLIST,
HOSTS_WHITELIST,
};
JNIEXPORT jint JNI_OnLoad(
__attribute__((unused)) JavaVM *vm,
__attribute__((unused)) void *reserved) {
default_params = params;
return JNI_VERSION_1_6;
}
JNIEXPORT jint JNICALL
Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocketWithCommandLine(
JNIEnv *env,
__attribute__((unused)) jobject thiz,
jobjectArray args) {
int argc = (*env)->GetArrayLength(env, args);
char *argv[argc];
for (int i = 0; i < argc; i++) {
jstring arg = (jstring) (*env)->GetObjectArrayElement(env, args, i);
const char *arg_str = (*env)->GetStringUTFChars(env, arg, 0);
argv[i] = strdup(arg_str);
(*env)->ReleaseStringUTFChars(env, arg, arg_str);
}
int res = parse_args(argc, argv);
if (res < 0) {
uniperror("parse_args");
return -1;
}
int fd = listen_socket((struct sockaddr_ina *)&params.laddr);
if (fd < 0) {
uniperror("listen_socket");
return -1;
}
LOG(LOG_S, "listen_socket, fd: %d", fd);
return fd;
}
JNIEXPORT jint JNICALL
Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
JNIEnv *env,
__attribute__((unused)) jobject thiz,
jstring ip,
jint port,
jint max_connections,
jint buffer_size,
jint default_ttl,
jboolean custom_ttl,
jboolean no_domain,
jboolean desync_http,
jboolean desync_https,
jboolean desync_udp,
jint desync_method,
jint split_position,
jboolean split_at_host,
jint fake_ttl,
jstring fake_sni,
jstring custom_oob_data,
jboolean host_mixed_case,
jboolean domain_mixed_case,
jboolean host_remove_spaces,
jboolean tls_record_split,
jint tls_record_split_position,
jboolean tls_record_split_at_sni,
jint hosts_mode,
jstring hosts) {
struct sockaddr_ina s;
const char *address = (*env)->GetStringUTFChars(env, ip, 0);
int res = get_addr(address, &s);
(*env)->ReleaseStringUTFChars(env, ip, address);
if (res < 0) {
uniperror("get_addr");
return -1;
}
s.in.sin_port = htons(port);
params.max_open = max_connections;
params.bfsize = buffer_size;
params.resolve = !no_domain;
if (custom_ttl) {
params.def_ttl = default_ttl;
params.custom_ttl = 1;
}
if (!params.def_ttl) {
if ((params.def_ttl = get_default_ttl()) < 1) {
uniperror("get_default_ttl");
reset_params();
return -1;
}
}
if (hosts_mode == HOSTS_WHITELIST) {
struct desync_params *dp = add(
(void *) &params.dp,
&params.dp_count,
sizeof(struct desync_params)
);
if (!dp) {
uniperror("add");
reset_params();
return -1;
}
const char *str = (*env)->GetStringUTFChars(env, hosts, 0);
dp->file_ptr = parse_cform(str, &dp->file_size);
(*env)->ReleaseStringUTFChars(env, hosts, str);
dp->hosts = parse_hosts(dp->file_ptr, dp->file_size);
if (!dp->hosts) {
perror("parse_hosts");
clear_params();
return -1;
}
}
struct desync_params *dp = add(
(void *) &params.dp,
&params.dp_count,
sizeof(struct desync_params)
);
if (!dp) {
uniperror("add");
reset_params();
return -1;
}
if (hosts_mode == HOSTS_BLACKLIST) {
const char *str = (*env)->GetStringUTFChars(env, hosts, 0);
dp->file_ptr = parse_cform(str, &dp->file_size);
(*env)->ReleaseStringUTFChars(env, hosts, str);
dp->hosts = parse_hosts(dp->file_ptr, dp->file_size);
if (!dp->hosts) {
perror("parse_hosts");
clear_params();
return -1;
}
}
dp->ttl = fake_ttl;
dp->proto =
IS_HTTP * desync_http |
IS_HTTPS * desync_https |
IS_UDP * desync_udp;
dp->mod_http =
MH_HMIX * host_mixed_case |
MH_DMIX * domain_mixed_case |
MH_SPACE * host_remove_spaces;
struct part *part = add(
(void *) &dp->parts,
&dp->parts_n,
sizeof(struct part)
);
if (!part) {
uniperror("add");
reset_params();
return -1;
}
enum demode mode = DESYNC_METHODS[desync_method];
int offset_flag = dp->proto || desync_https ? OFFSET_SNI : OFFSET_HOST;
part->flag = split_at_host ? offset_flag : 0;
part->pos = split_position;
part->m = mode;
if (tls_record_split) {
struct part *tlsrec_part = add(
(void *) &dp->tlsrec,
&dp->tlsrec_n,
sizeof(struct part)
);
if (!tlsrec_part) {
uniperror("add");
reset_params();
return -1;
}
tlsrec_part->flag = tls_record_split_at_sni ? offset_flag : 0;
tlsrec_part->pos = tls_record_split_position;
}
if (mode == DESYNC_FAKE) {
const char *sni = (*env)->GetStringUTFChars(env, fake_sni, 0);
LOG(LOG_S, "fake_sni: %s", sni);
res = change_tls_sni(sni, fake_tls.data, fake_tls.size);
(*env)->ReleaseStringUTFChars(env, fake_sni, sni);
if (res) {
fprintf(stderr, "error chsni\n");
return -1;
}
}
if (mode == DESYNC_OOB) {
const char *oob = (*env)->GetStringUTFChars(env, custom_oob_data, 0);
const size_t oob_len = strlen(oob);
oob_data.size = oob_len;
oob_data.data = malloc(oob_len);
if (oob_data.data == NULL) {
uniperror("malloc");
return -1;
}
memcpy(oob_data.data, oob, oob_len);
(*env)->ReleaseStringUTFChars(env, custom_oob_data, oob);
}
if (dp->proto) {
dp = add((void *)&params.dp,
&params.dp_count, sizeof(struct desync_params));
if (!dp) {
uniperror("add");
clear_params();
return -1;
}
}
params.mempool = mem_pool(0);
if (!params.mempool) {
uniperror("mem_pool");
clear_params();
return -1;
}
int fd = listen_socket(&s);
if (fd < 0) {
uniperror("listen_socket");
return -1;
}
LOG(LOG_S, "listen_socket, fd: %d", fd);
return fd;
}
JNIEXPORT jint JNICALL
Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniStartProxy(
__attribute__((unused)) JNIEnv *env,
__attribute__((unused)) jobject thiz,
jint fd) {
LOG(LOG_S, "start_proxy, fd: %d", fd);
NOT_EXIT = 1;
if (event_loop(fd) < 0) {
uniperror("event_loop");
return get_e();
}
return 0;
}
JNIEXPORT jint JNICALL
Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniStopProxy(
__attribute__((unused)) JNIEnv *env,
__attribute__((unused)) jobject thiz,
jint fd) {
LOG(LOG_S, "stop_proxy, fd: %d", fd);
int res = shutdown(fd, SHUT_RDWR);
reset_params();
if (res < 0) {
uniperror("shutdown");
return get_e();
}
return 0;
}