Browse Source

update: shadowsocks params decode

master
dnomd343 2 years ago
parent
commit
c4a35d4236
  1. 40
      include/common.h
  2. 564
      src/common.c
  3. 7
      src/local.c
  4. 5
      src/log.c
  5. 7
      src/server.c

40
include/common.h

@ -4,19 +4,33 @@
#define RANDOM_PORT_START 41952 #define RANDOM_PORT_START 41952
#define RANDOM_PORT_END 65535 #define RANDOM_PORT_END 65535
extern int is_udp_proxy; //extern int is_udp_proxy;
extern char *server_addr, *client_addr; //extern char *server_addr, *client_addr;
extern char *server_port, *client_port; //extern char *server_port, *client_port;
extern char *password; //extern char *password;
extern char *method; //extern char *method;
extern char *timeout; //extern char *timeout;
extern int fastopen; //extern int fastopen;
extern char *plugin; //extern char *plugin;
extern char *plugin_opts; //extern char *plugin_opts;
extern char *shadowsocks; //extern char *shadowsocks;
extern char **shadowsocks_opts; //extern char **shadowsocks_opts;
void params_load(char *ss_default); typedef struct {
void args_decode(int argc, char **argv); int is_debug, is_udp_proxy;
char *server_addr, *client_addr;
char *server_port, *client_port;
char *password;
char *method;
char *timeout;
int fastopen;
char *plugin;
char *plugin_opts;
char *shadowsocks;
char **shadowsocks_opts;
} bootstrap_info;
void params_load(char *ss_default, bootstrap_info *info);
void args_decode(int argc, char **argv, bootstrap_info *info);
#endif #endif

564
src/common.c

@ -5,38 +5,39 @@
#include "common.h" #include "common.h"
#include "network.h" #include "network.h"
#include "process.h" #include "process.h"
#include "log.h"
int is_udp_proxy; //int is_udp_proxy = 1;
char *server_addr, *client_addr; //char *server_addr = NULL, *client_addr = NULL;
char *server_port, *client_port; //char *server_port = NULL, *client_port = NULL;
char *password; //char *password = NULL;
char *method; //char *method = NULL;
char *timeout; //char *timeout = NULL;
int fastopen; //int fastopen = 0;
char *plugin; //char *plugin = NULL;
char *plugin_opts; //char *plugin_opts = NULL;
char *shadowsocks; //char *shadowsocks = NULL;
char **shadowsocks_opts; //char **shadowsocks_opts; // init before usage
void args_dump(); void args_dump();
void args_init(); //void error_exit(char *msg);
void error_exit(char *msg);
char* int_to_string(int num); char* int_to_string(int num);
void pack_shadowsocks_params(); void pack_shadowsocks_params(bootstrap_info *info);
char* read_file(char *file_name); char* read_file(char *file_name);
void json_decode(char *json_content); //void json_decode(char *json_content);
void add_shadowsocks_option(char *option); void add_shadowsocks_option(char *option, char **opts);
void extra_options_decode(char *extra_opts); void extra_options_decode(char *extra_opts, char **opts);
//void params_load(char *ss_default, bootstrap_info *info);
void error_exit(char *msg) { // throw error message with exit-code 1 //void error_exit(char *msg) { // throw error message with exit-code 1
printf("[Shadowsocks Bootstrap] ERROR: %s.\n", msg); // printf("[Shadowsocks Bootstrap] ERROR: %s.\n", msg);
printf("[Shadowsocks Bootstrap] exit with error.\n"); // printf("[Shadowsocks Bootstrap] exit with error.\n");
exit(1); // exit(1);
} //}
char* int_to_string(int num) { // int -> string char* int_to_string(int num) { // int -> string
if (num < 0) { if (num < 0) {
error_exit("number must be positive"); log_fatal("number must be positive");
} }
int count = 0; int count = 0;
int temp = num; int temp = num;
@ -49,69 +50,67 @@ char* int_to_string(int num) { // int -> string
return str; return str;
} }
void params_load(char *ss_default) { // load shadowsocks and plugin params void params_load(char *ss_default, bootstrap_info *info) { // load shadowsocks and plugin params
if (shadowsocks == NULL) { if (info->shadowsocks == NULL) {
shadowsocks = ss_default; info->shadowsocks = ss_default;
} }
shadowsocks_opts[0] = shadowsocks; // fill with file name info->shadowsocks_opts[0] = info->shadowsocks; // fill with file name
if (plugin != NULL) { // with plugin if (info->plugin != NULL) { // with plugin
char *rand_port = int_to_string(get_available_port(RANDOM_PORT_START, RANDOM_PORT_END)); char *rand_port = int_to_string(get_available_port(RANDOM_PORT_START, RANDOM_PORT_END));
SS_REMOTE_HOST = server_addr; SS_REMOTE_HOST = info->server_addr;
SS_REMOTE_PORT = server_port; SS_REMOTE_PORT = info->server_port;
SS_LOCAL_HOST = "127.0.0.1"; SS_LOCAL_HOST = "127.0.0.1";
SS_LOCAL_PORT = rand_port; SS_LOCAL_PORT = rand_port;
server_addr = SS_LOCAL_HOST; info->server_addr = SS_LOCAL_HOST;
server_port = SS_LOCAL_PORT; info->server_port = SS_LOCAL_PORT;
SS_PLUGIN_OPTIONS = plugin_opts; SS_PLUGIN_OPTIONS = info->plugin_opts;
} }
pack_shadowsocks_params(); pack_shadowsocks_params(info);
shadowsocks_args = shadowsocks_opts; shadowsocks_args = info->shadowsocks_opts;
if (plugin == NULL) { if (info->plugin == NULL) {
plugin_file = NULL; plugin_file = NULL;
} else { } else {
plugin_file = plugin; plugin_file = info->plugin;
} }
} }
void args_init() { // init arguments //void args_init() { // init bootstrap arguments
is_udp_proxy = 1; // udp proxy in default // is_udp_proxy = 1; // enable udp proxy in default
server_addr = client_addr = NULL; // server_addr = client_addr = NULL;
server_port = client_port = NULL; // server_port = client_port = NULL;
password = NULL; // password = NULL;
method = NULL; // method = NULL;
timeout = NULL; // timeout = NULL;
fastopen = 0; // fastopen = 0;
plugin = NULL; // plugin = NULL;
plugin_opts = NULL; // plugin_opts = NULL;
shadowsocks = NULL; // shadowsocks = NULL;
shadowsocks_opts = (char**)malloc(sizeof(char*) * 2); // shadowsocks_opts = (char**)malloc(sizeof(char*) * 2);
shadowsocks_opts[0] = ""; // reserved for program name // shadowsocks_opts[0] = ""; // reserved for program name
shadowsocks_opts[1] = NULL; // shadowsocks_opts[1] = NULL;
} //}
char* read_file(char *file_name) { // read file content char* read_file(char *file_name) { // read file content
log_debug("Read file content -> %s", file_name);
FILE *pfile = fopen(file_name, "rb"); FILE *pfile = fopen(file_name, "rb");
if (pfile == NULL) { // open failed if (pfile == NULL) { // file open failed
char *msg_prefix = "File `"; log_fatal("File `%s` open failed", file_name);
char *msg_suffix = "` open failed";
char *msg = (char*)malloc(strlen(msg_prefix) + strlen(file_name) + strlen(msg_suffix) + 1);
strcpy(msg, msg_prefix);
error_exit(strcat(strcat(msg, file_name), msg_suffix)); // merge error message
} }
fseek(pfile, 0, SEEK_END); fseek(pfile, 0, SEEK_END);
long file_length = ftell(pfile); // get file length long file_length = ftell(pfile); // get file length
char *file_content = (char*)malloc(file_length + 1); // malloc new memory char *file_content = (char*)malloc(file_length + 1); // malloc new memory
if (file_content == NULL) { if (file_content == NULL) {
error_exit("no enough memory"); // file too large log_fatal("No enough memory for reading file"); // file too large
} }
rewind(pfile); rewind(pfile);
fread(file_content, 1, file_length, pfile); // read file stream fread(file_content, 1, file_length, pfile); // read file stream
file_content[file_length] = '\0'; // set end flag file_content[file_length] = '\0'; // set end flag
fclose(pfile); fclose(pfile);
log_debug("File `%s` read success ->\n%s", file_name, file_content);
return file_content; return file_content;
} }
void extra_options_decode(char *extra_opts) { // decode shadowsocks extra options void extra_options_decode(char *extra_opts, char **opts) { // decode shadowsocks extra options
int num, i; int num, i;
char *tmp = (char*)calloc(strlen(extra_opts) + 1, 1); // new memory and set as 0x00 char *tmp = (char*)calloc(strlen(extra_opts) + 1, 1); // new memory and set as 0x00
num = i = 0; num = i = 0;
@ -119,7 +118,7 @@ void extra_options_decode(char *extra_opts) { // decode shadowsocks extra option
if (extra_opts[num] == '\0' || extra_opts[num] == ' ') { // string end or find a space if (extra_opts[num] == '\0' || extra_opts[num] == ' ') { // string end or find a space
tmp[i] = '\0'; tmp[i] = '\0';
if (i) { // ignore empty string if (i) { // ignore empty string
add_shadowsocks_option(tmp); add_shadowsocks_option(tmp, opts);
} }
if (extra_opts[num] == '\0') { // string end if (extra_opts[num] == '\0') { // string end
break; break;
@ -135,319 +134,334 @@ void extra_options_decode(char *extra_opts) { // decode shadowsocks extra option
} }
} }
void add_shadowsocks_option(char *option) { // add shadowsocks options void add_shadowsocks_option(char *option, char **opts) { // add shadowsocks options
int opt_num = 0; int opt_num = 0;
while(shadowsocks_opts[opt_num++] != NULL); // get options number while(opts[opt_num++] != NULL); // get options number
shadowsocks_opts = (char**)realloc(shadowsocks_opts, sizeof(char**) * (opt_num + 1)); opts = (char**)realloc(opts, sizeof(char**) * (opt_num + 1));
shadowsocks_opts[opt_num - 1] = strcpy((char*)malloc(strlen(option) + 1), option); opts[opt_num - 1] = strcpy((char*)malloc(strlen(option) + 1), option);
shadowsocks_opts[opt_num] = NULL; // end sign opts[opt_num] = NULL; // end sign
} }
void pack_shadowsocks_params() { // packaging shadowsocks parameters void pack_shadowsocks_params(bootstrap_info *info) { // packaging shadowsocks parameters
if (server_addr != NULL) { if (info->server_addr != NULL) {
add_shadowsocks_option("-s"); add_shadowsocks_option("-s", info->shadowsocks_opts);
add_shadowsocks_option(server_addr); add_shadowsocks_option(info->server_addr, info->shadowsocks_opts);
} }
if (client_addr != NULL) { if (info->client_addr != NULL) {
add_shadowsocks_option("-b"); add_shadowsocks_option("-b", info->shadowsocks_opts);
add_shadowsocks_option(client_addr); add_shadowsocks_option(info->client_addr, info->shadowsocks_opts);
} }
if (server_port != NULL) { if (info->server_port != NULL) {
add_shadowsocks_option("-p"); add_shadowsocks_option("-p", info->shadowsocks_opts);
add_shadowsocks_option(server_port); add_shadowsocks_option(info->server_port, info->shadowsocks_opts);
} }
if (client_port != NULL) { if (info->client_port != NULL) {
add_shadowsocks_option("-l"); add_shadowsocks_option("-l", info->shadowsocks_opts);
add_shadowsocks_option(client_port); add_shadowsocks_option(info->client_port, info->shadowsocks_opts);
} }
if (password != NULL) { if (info->password != NULL) {
add_shadowsocks_option("-k"); add_shadowsocks_option("-k", info->shadowsocks_opts);
add_shadowsocks_option(password); add_shadowsocks_option(info->password, info->shadowsocks_opts);
} }
if (method != NULL) { if (info->method != NULL) {
add_shadowsocks_option("-m"); add_shadowsocks_option("-m", info->shadowsocks_opts);
add_shadowsocks_option(method); add_shadowsocks_option(info->method, info->shadowsocks_opts);
} }
if (timeout != NULL) { if (info->timeout != NULL) {
add_shadowsocks_option("-t"); add_shadowsocks_option("-t", info->shadowsocks_opts);
add_shadowsocks_option(timeout); add_shadowsocks_option(info->timeout, info->shadowsocks_opts);
} }
if (fastopen) { if (info->fastopen) {
add_shadowsocks_option("--fast-open"); add_shadowsocks_option("--fast-open", info->shadowsocks_opts);
} }
} }
void json_decode(char *json_content) { // decode JSON content void json_decode(char *json_content, bootstrap_info *info) { // decode JSON content
cJSON* json = NULL; cJSON* json = NULL;
json = cJSON_Parse(json_content); json = cJSON_Parse(json_content);
if (json == NULL) { if (json == NULL) {
error_exit("JSON format error.\n"); log_fatal("JSON format error.");
} }
json = json->child; json = json->child;
while (json != NULL) { while (json != NULL) {
if (!strcmp(json->string, "no_udp")) { // no_udp => without udp proxy if (!strcmp(json->string, "no_udp")) { // no_udp => without udp proxy
if (!cJSON_IsBool(json)) { if (!cJSON_IsBool(json)) {
error_exit("`no_udp` must be a bool.\n"); log_fatal("`no_udp` must be a bool.");
} }
if (json->valueint) { // is_udp_proxy = ~(json->valueint) if (json->valueint) { // is_udp_proxy = ~(json->valueint)
is_udp_proxy = 0; info->is_udp_proxy = 0;
} else { } else {
is_udp_proxy = 1; info->is_udp_proxy = 1;
} }
} else if (!strcmp(json->string, "server")) { // server => server_addr } else if (!strcmp(json->string, "server")) { // server => server_addr
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`server` must be a string.\n"); log_fatal("`server` must be a string.");
} }
if (server_addr != NULL) { if (info->server_addr != NULL) {
free(server_addr); free(info->server_addr);
} }
server_addr = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->server_addr = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else if (!strcmp(json->string, "local_address")) { // local_address => client_addr } else if (!strcmp(json->string, "local_address")) { // local_address => client_addr
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`local_address` must be a string.\n"); log_fatal("`local_address` must be a string.");
} }
if (client_addr != NULL) { if (info->client_addr != NULL) {
free(client_addr); free(info->client_addr);
} }
client_addr = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->client_addr = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else if (!strcmp(json->string, "server_port")) { // server_port => server_port } else if (!strcmp(json->string, "server_port")) { // server_port => server_port
if (server_port != NULL) { if (info->server_port != NULL) {
free(server_port); free(info->server_port);
} }
if (cJSON_IsNumber(json)) { if (cJSON_IsNumber(json)) {
server_port = int_to_string(json->valueint); info->server_port = int_to_string(json->valueint);
} else if (cJSON_IsString(json)) { } else if (cJSON_IsString(json)) {
server_port = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->server_port = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else { } else {
error_exit("`server_port` must be a number or string.\n"); log_fatal("`server_port` must be a number or string.");
} }
} else if (!strcmp(json->string, "local_port")) { // local_port => client_port } else if (!strcmp(json->string, "local_port")) { // local_port => client_port
if (client_port != NULL) { if (info->client_port != NULL) {
free(client_port); free(info->client_port);
} }
if (cJSON_IsNumber(json)) { if (cJSON_IsNumber(json)) {
client_port = int_to_string(json->valueint); info->client_port = int_to_string(json->valueint);
} else if (cJSON_IsString(json)) { } else if (cJSON_IsString(json)) {
client_port = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->client_port = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else { } else {
error_exit("`local_port` must be a number or string.\n"); log_fatal("`local_port` must be a number or string.");
} }
} else if (!strcmp(json->string, "password")) { // password => password } else if (!strcmp(json->string, "password")) { // password => password
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`password` must be a string.\n"); log_fatal("`password` must be a string.");
} }
if (password != NULL) { if (info->password != NULL) {
free(password); free(info->password);
} }
password = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->password = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else if (!strcmp(json->string, "timeout")) { // timeout => timeout } else if (!strcmp(json->string, "timeout")) { // timeout => timeout
if (timeout != NULL) { if (info->timeout != NULL) {
free(timeout); free(info->timeout);
} }
if (cJSON_IsNumber(json)) { if (cJSON_IsNumber(json)) {
timeout = int_to_string(json->valueint); info->timeout = int_to_string(json->valueint);
} else if (cJSON_IsString(json)) { } else if (cJSON_IsString(json)) {
timeout = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->timeout = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else { } else {
error_exit("`timeout` must be a number or string.\n"); log_fatal("`timeout` must be a number or string.");
} }
} else if (!strcmp(json->string, "method")) { // method => method } else if (!strcmp(json->string, "method")) { // method => method
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`method` must be a string.\n"); log_fatal("`method` must be a string.");
} }
if (method != NULL) { if (info->method != NULL) {
free(method); free(info->method);
} }
method = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->method = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else if (!strcmp(json->string, "fast_open")) { // fast_open => fastopen } else if (!strcmp(json->string, "fast_open")) { // fast_open => fastopen
if (!cJSON_IsBool(json)) { if (!cJSON_IsBool(json)) {
error_exit("`fast_open` must be a bool.\n"); log_fatal("`fast_open` must be a bool.");
} }
fastopen = json->valueint; info->fastopen = json->valueint;
} else if (!strcmp(json->string, "plugin")) { // plugin => plugin } else if (!strcmp(json->string, "plugin")) { // plugin => plugin
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`plugin` must be a string.\n"); log_fatal("`plugin` must be a string.");
} }
if (plugin != NULL) { if (info->plugin != NULL) {
free(plugin); free(info->plugin);
} }
plugin = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->plugin = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else if (!strcmp(json->string, "plugin_opts")) { // plugin_opts => plugin_opts } else if (!strcmp(json->string, "plugin_opts")) { // plugin_opts => plugin_opts
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`plugin_opts` must be a string.\n"); log_fatal("`plugin_opts` must be a string.");
} }
if (plugin_opts != NULL) { if (info->plugin_opts != NULL) {
free(plugin_opts); free(info->plugin_opts);
} }
plugin_opts = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->plugin_opts = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else if (!strcmp(json->string, "shadowsocks")) { // shadowsocks => shadowsocks } else if (!strcmp(json->string, "shadowsocks")) { // shadowsocks => shadowsocks
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`shadowsocks` must be a string.\n"); log_fatal("`shadowsocks` must be a string.");
} }
if (shadowsocks != NULL) { if (info->shadowsocks != NULL) {
free(shadowsocks); free(info->shadowsocks);
} }
shadowsocks = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring); info->shadowsocks = strcpy((char*)malloc(strlen(json->valuestring) + 1), json->valuestring);
} else if (!strcmp(json->string, "extra_opts")) { // extra_opts => DECODE => shadowsocks_opts } else if (!strcmp(json->string, "extra_opts")) { // extra_opts => DECODE => shadowsocks_opts
if (!cJSON_IsString(json)) { if (!cJSON_IsString(json)) {
error_exit("`extra_opts` must be a string.\n"); log_fatal("`extra_opts` must be a string.");
} }
extra_options_decode(json->valuestring); extra_options_decode(json->valuestring, info->shadowsocks_opts);
} else { // unknown field => ERROR } else { // unknown field => ERROR
char *msg_prefix = "Unknown JSON field `"; char *msg_prefix = "Unknown JSON field `";
char *msg_suffix = "`.\n"; char *msg_suffix = "`.\n";
char *msg = (char*)malloc(strlen(msg_prefix) + strlen(json->string) + strlen(msg_suffix) + 1); char *msg = (char*)malloc(strlen(msg_prefix) + strlen(json->string) + strlen(msg_suffix) + 1);
strcpy(msg, msg_prefix); strcpy(msg, msg_prefix);
error_exit(strcat(strcat(msg, json->string), msg_suffix)); log_fatal(strcat(strcat(msg, json->string), msg_suffix));
} }
json = json->next; // next field json = json->next; // next field
} }
cJSON_free(json); // free JSON struct cJSON_free(json); // free JSON struct
} }
void args_decode(int argc, char **argv) { // decode the input parameters void args_init(bootstrap_info *info) {
args_init(); info->is_debug = 0; // disable debug mode
int i; info->is_udp_proxy = 1; // enable udp proxy
int debug_flag = 0; info->server_addr = info->client_addr = NULL;
for (i = 1; i < argc; ++i) { info->server_port = info->client_port = NULL;
if (!strcmp(argv[i], "--debug")) { // --debug => dump args info->password = NULL;
debug_flag = 1; info->method = NULL;
} else if (!strcmp(argv[i], "--no-udp")) { // --no-udp => without udp proxy info->timeout = NULL;
is_udp_proxy = 0; info->fastopen = 0;
} else if (!strcmp(argv[i], "-c")) { // -c => CONFIG_JSON info->plugin = NULL;
if (i + 1 == argc) { info->plugin_opts = NULL;
error_exit("`-c` require a parameter"); info->shadowsocks = NULL;
} info->shadowsocks_opts = (char**)malloc(sizeof(char*) * 2); // 2 arguments
json_decode(read_file(argv[++i])); info->shadowsocks_opts[0] = ""; // reserved for program name
} else if (!strcmp(argv[i], "-s")) { // -s => server_addr info->shadowsocks_opts[1] = NULL;
if (i + 1 == argc) {
error_exit("`-s` require a parameter");
}
if (server_addr != NULL) {
free(server_addr);
}
++i;
server_addr = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "-p")) { // -p => server_port
if (i + 1 == argc) {
error_exit("`-p` require a parameter");
}
if (server_port != NULL) {
free(server_port);
}
++i;
server_port = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "-b")) { // -b => client_addr
if (i + 1 == argc) {
error_exit("`-b` require a parameter");
}
if (client_addr != NULL) {
free(client_addr);
}
++i;
client_addr = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "-l")) { // -l => client_port
if (i + 1 == argc) {
error_exit("`-l` require a parameter");
}
if (client_port != NULL) {
free(client_port);
}
++i;
client_port = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "-k")) { // -k => password
if (i + 1 == argc) {
error_exit("`-k` require a parameter");
}
if (password != NULL) {
free(password);
}
++i;
password = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "-m")) { // -m => method
if (i + 1 == argc) {
error_exit("`-m` require a parameter");
}
if (method != NULL) {
free(method);
}
++i;
method = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "-t")) { // -t => timeout
if (i + 1 == argc) {
error_exit("`-t` require a parameter");
}
if (timeout != NULL) {
free(timeout);
}
++i;
timeout = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "--fast-open")) { // --fast-open
fastopen = 1;
} else if (!strcmp(argv[i], "--plugin")) { // --plugin => plugin
if (i + 1 == argc) {
error_exit("`--plugin` require a parameter");
} }
if (plugin != NULL) {
free(plugin); char* new_string(char *str) {
return strcpy((char*)malloc(strlen(str) + 1), str);
} }
++i;
plugin = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]); void args_debug(bootstrap_info *info) {
} else if (!strcmp(argv[i], "--plugin-opts")) { // --plugin-opts => plugin_opts if (info->is_udp_proxy) {
if (i + 1 == argc) { log_debug("is_udp_proxy = true");
error_exit("`--plugin-opts` require a parameter"); } else {
log_debug("is_udp_proxy = false");
}
printf("server_addr = %s\n", info->server_addr);
printf("client_addr = %s\n", info->client_addr);
printf("server_port = %s\n", info->server_port);
printf("client_port = %s\n", info->client_port);
printf("password = %s\n", info->password);
printf("method = %s\n", info->method);
printf("timeout = %s\n", info->timeout);
if (info->fastopen) {
printf("fastopen = true\n");
} else {
printf("fastopen = false\n");
} }
if (plugin_opts != NULL) { printf("shadowsocks = %s\n", info->shadowsocks);
free(plugin_opts); printf("plugin = %s\n", info->plugin);
printf("plugin_opts = %s\n", info->plugin_opts);
int num = 0;
printf("options:\n");
while(info->shadowsocks_opts[num] != NULL) {
printf(" '%s'\n", info->shadowsocks_opts[num]);
num++;
} }
++i;
plugin_opts = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]);
} else if (!strcmp(argv[i], "--shadowsocks")) { // --shadowsocks => shadowsocks
if (i + 1 == argc) {
error_exit("`--shadowsocks` require a parameter");
} }
if (shadowsocks != NULL) {
free(shadowsocks); void args_decode(int argc, char **argv, bootstrap_info *info) { // decode the input parameters
args_init(info);
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--debug")) { // --debug ==> debug mode
info->is_debug = 1;
} else if (!strcmp(argv[i], "--no-udp")) { // --no-udp ==> without udp proxy
info->is_udp_proxy = 0;
} else if (!strcmp(argv[i], "-c")) { // -c ==> CONFIG_JSON
if (++i == argc) {
log_fatal("`-c` require a parameter");
}
char *json_content = read_file(argv[i]);
json_decode(json_content, info); // decode json content
free(json_content);
} else if (!strcmp(argv[i], "-s")) { // -s ==> server_addr
if (++i == argc) {
log_fatal("`-s` require a parameter");
}
if (info->server_addr != NULL) {
free(info->server_addr); // override server address
}
info->server_addr = new_string(argv[i]);
} else if (!strcmp(argv[i], "-p")) { // -p ==> server_port
if (++i == argc) {
log_fatal("`-p` require a parameter");
}
if (info->server_port != NULL) {
free(info->server_port); // override server port
}
info->server_port = new_string(argv[i]);
} else if (!strcmp(argv[i], "-b")) { // -b ==> client_addr
if (++i == argc) {
log_fatal("`-b` require a parameter");
}
if (info->client_addr != NULL) {
free(info->client_addr); // override client address
}
info->client_addr = new_string(argv[i]);
} else if (!strcmp(argv[i], "-l")) { // -l ==> client_port
if (++i == argc) {
log_fatal("`-l` require a parameter");
}
if (info->client_port != NULL) {
free(info->client_port); // override client port
}
info->client_port = new_string(argv[i]);
} else if (!strcmp(argv[i], "-k")) { // -k ==> password
if (++i == argc) {
log_fatal("`-k` require a parameter");
}
if (info->password != NULL) {
free(info->password); // override password
}
info->password = new_string(argv[i]);
} else if (!strcmp(argv[i], "-m")) { // -m ==> method
if (++i == argc) {
log_fatal("`-m` require a parameter");
}
if (info->method != NULL) {
free(info->method); // override method
}
info->method = new_string(argv[i]);
} else if (!strcmp(argv[i], "-t")) { // -t ==> timeout
if (++i == argc) {
log_fatal("`-t` require a parameter");
}
if (info->timeout != NULL) {
free(info->timeout); // override timeout
}
info->timeout = new_string(argv[i]);
} else if (!strcmp(argv[i], "--fast-open")) { // --fast-open
info->fastopen = 1;
} else if (!strcmp(argv[i], "--plugin")) { // --plugin ==> plugin
if (++i == argc) {
log_fatal("`--plugin` require a parameter");
} }
++i; if (info->plugin != NULL) {
shadowsocks = strcpy((char*)malloc(strlen(argv[i]) + 1), argv[i]); free(info->plugin); // override plugin
} else { // unknown option => archive
add_shadowsocks_option(argv[i]); // archive unknown options
} }
info->plugin = new_string(argv[i]);
} else if (!strcmp(argv[i], "--plugin-opts")) { // --plugin-opts ==> plugin_opts
if (++i == argc) {
log_fatal("`--plugin-opts` require a parameter");
} }
if (server_addr == NULL) { // default server address (bind address in server mode) if (info->plugin_opts != NULL) {
server_addr = "127.0.0.1"; free(info->plugin_opts);
} }
if (debug_flag) { // show args for debug info->plugin_opts = new_string(argv[i]);
args_dump(); } else if (!strcmp(argv[i], "--shadowsocks")) { // --shadowsocks ==> shadowsocks
if (++i == argc) {
log_fatal("`--shadowsocks` require a parameter");
} }
if (info->shadowsocks != NULL) {
free(info->shadowsocks);
} }
info->shadowsocks = new_string(argv[i]);
void args_dump() { // show parameter's content } else { // unknown option ==> archive
if (is_udp_proxy) { add_shadowsocks_option(argv[i], info->shadowsocks_opts); // archive unknown options
printf("is_udp_proxy = true\n");
} else {
printf("is_udp_proxy = false\n");
}
printf("server_addr = %s\n", server_addr);
printf("client_addr = %s\n", client_addr);
printf("server_port = %s\n", server_port);
printf("client_port = %s\n", client_port);
printf("password = %s\n", password);
printf("method = %s\n", method);
printf("timeout = %s\n", timeout);
if (fastopen) {
printf("fastopen = true\n");
} else {
printf("fastopen = false\n");
} }
printf("shadowsocks = %s\n", shadowsocks);
printf("plugin = %s\n", plugin);
printf("plugin_opts = %s\n", plugin_opts);
int num = 0;
printf("options:\n");
while(shadowsocks_opts[num] != NULL) {
printf(" '%s'\n", shadowsocks_opts[num]);
num++;
} }
if (info->server_addr == NULL) { // default server address (bind address in server mode)
info->server_addr = "127.0.0.1";
}
args_debug(info);
} }
//void args_dump() { // show parameter's content
//
//}

7
src/local.c

@ -10,8 +10,9 @@ int main(int argc, char *argv[]) {
is_show_help(argc, argv, local_help_msg); is_show_help(argc, argv, local_help_msg);
log_info("Shadowsocks bootstrap local (%s)", VERSION); log_info("Shadowsocks bootstrap local (%s)", VERSION);
args_decode(argc, argv); bootstrap_info info;
params_load("sslocal"); // default file name args_decode(argc, argv, &info);
start_bootstrap("sslocal", is_udp_proxy); // local or server mode // params_load("sslocal"); // default file name
// start_bootstrap("sslocal", is_udp_proxy); // local or server mode
return 0; return 0;
} }

5
src/log.c

@ -1,3 +1,4 @@
#include <stdlib.h>
#include "log.h" #include "log.h"
int log_level = LOG_DEBUG; // default log level int log_level = LOG_DEBUG; // default log level
@ -34,4 +35,8 @@ void log_printf(int level, const char *fmt, ...) {
fprintf(stderr, "\n"); // add LF after line fprintf(stderr, "\n"); // add LF after line
fflush(stderr); fflush(stderr);
va_end(ap); va_end(ap);
if (level == LOG_FATAL) {
exit(1);
}
} }

7
src/server.c

@ -10,8 +10,9 @@ int main(int argc, char *argv[]) {
is_show_help(argc, argv, server_help_msg); is_show_help(argc, argv, server_help_msg);
log_info("Shadowsocks bootstrap server (%s)", VERSION); log_info("Shadowsocks bootstrap server (%s)", VERSION);
args_decode(argc, argv); bootstrap_info info;
params_load("ssserver"); // default file name args_decode(argc, argv, &info);
start_bootstrap("ssserver", is_udp_proxy); // local or server mode // params_load("ssserver"); // default file name
// start_bootstrap("ssserver", is_udp_proxy); // local or server mode
return 0; return 0;
} }

Loading…
Cancel
Save