Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ rpm/BUILDROOT/
*.rpm
*.deb

# Ignore files for clangd language server
.cache/
compile_commands.json

# Ignore per-project vim config
.vimrc

Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
1 change: 1 addition & 0 deletions doc/shadowsocks-c.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ The config file equivalent of command line options is listed as examples below.
- `--printable-salt`: `"printable_salt": true` (ss-local only)
- `--plugin "obfs-server"`: `"plugin": "obfs-server"`
- `--plugin-opts "obfs=http"`: `"plugin_opts": "obfs=http"`
- `--plugin-mode "tcp_only"`: `"plugin_mode": "tcp_only"`
- `-6`: `"ipv6_first": true`
- `-n 1024`: `"nofile": 1024`
- `-d "8.8.8.8"`: `"nameserver": "8.8.8.8"`
Expand Down
1 change: 1 addition & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enum {
GETOPT_VAL_MPTCP,
GETOPT_VAL_PLUGIN,
GETOPT_VAL_PLUGIN_OPTS,
GETOPT_VAL_PLUGIN_MODE,
GETOPT_VAL_PASSWORD,
GETOPT_VAL_KEY,
GETOPT_VAL_MANAGER_ADDRESS,
Expand Down
20 changes: 20 additions & 0 deletions src/jconf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,10 @@ read_jconf(const char *file)
}
} else if (strcmp(name, "plugin_opts") == 0) {
conf.plugin_opts = to_string(value);
} else if (strcmp(name, "plugin_mode") == 0) {
/* plugin_mode: "tcp_only", "udp_only" or "tcp_and_udp" */
char *mode_str = to_string(value);
conf.plugin_mode = parse_plugin_mode(mode_str);
} else if (strcmp(name, "fast_open") == 0) {
check_json_value_type(value, json_boolean,
"invalid config file: option 'fast_open' must be a boolean");
Expand Down Expand Up @@ -548,3 +552,19 @@ read_jconf(const char *file)
// The tree and the file text go with the scratch arena.
return &conf;
}

int
parse_plugin_mode(const char *mode_str)
{
if (mode_str == NULL)
return TCP_ONLY;
if (strcmp(mode_str, "tcp_only") == 0)
return TCP_ONLY;
if (strcmp(mode_str, "udp_only") == 0)
return UDP_ONLY;
if (strcmp(mode_str, "tcp_and_udp") == 0)
return TCP_AND_UDP;
/* default */
LOGI("ignore unknown plugin_mode: %s, use tcp_only as fallback", mode_str);
return TCP_ONLY;
}
21 changes: 21 additions & 0 deletions src/jconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ extern "C" {
#define TCP_AND_UDP 1
#define UDP_ONLY 3

static inline int
mode_has_tcp(int mode)
{
return mode != UDP_ONLY;
}

static inline int
mode_has_udp(int mode)
{
return mode != TCP_ONLY;
}

static inline int
plugin_mode_is_subset(int plugin_mode, int mode)
{
return (!mode_has_tcp(plugin_mode) || mode_has_tcp(mode))
&& (!mode_has_udp(plugin_mode) || mode_has_udp(mode));
}

typedef struct {
char *port;
char *password;
Expand Down Expand Up @@ -76,6 +95,7 @@ typedef struct {
char *user;
char *plugin;
char *plugin_opts;
int plugin_mode;
int fast_open;
int reuse_port;
int tcp_incoming_sndbuf;
Expand Down Expand Up @@ -107,6 +127,7 @@ void parse_addr(const char *str, ss_addr_t *addr);
void free_addr(ss_addr_t *addr);
int parse_server_endpoint(const char *str, ss_addr_t *addr);
int complete_server_ports(ss_addr_t *addr, int count, const char *fallback, int plugin);
int parse_plugin_mode(const char *mode_str);

#ifdef __cplusplus
}
Expand Down
29 changes: 24 additions & 5 deletions src/local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ main(int argc, char **argv)

char *plugin = NULL;
char *plugin_opts = NULL;
int plugin_mode = TCP_ONLY;
char *plugin_host = NULL;
char *plugin_port = NULL;
char tmp_port[8];
Expand Down Expand Up @@ -592,6 +593,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
\snippet{doc} utils.cpp cli_long_mptcp
\snippet{doc} utils.cpp cli_long_plugin
\snippet{doc} utils.cpp cli_long_plugin_opts
\snippet{doc} utils.cpp cli_long_plugin_mode
\snippet{doc} utils.cpp cli_long_password
\snippet{doc} utils.cpp cli_long_key
\snippet{doc} utils.cpp cli_long_server_url
Expand Down Expand Up @@ -637,6 +639,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
{ "plugin-mode", required_argument, NULL, GETOPT_VAL_PLUGIN_MODE },
{ "password", required_argument, NULL, GETOPT_VAL_PASSWORD },
{ "key", required_argument, NULL, GETOPT_VAL_KEY },
{ "server-url", required_argument, NULL, GETOPT_VAL_SERVER_URL },
Expand All @@ -645,6 +648,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
};

int mode_set = 0;
int plugin_mode_set = 0;
int ipv6first_set = 0;
opterr = 0;

Expand Down Expand Up @@ -719,6 +723,10 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
case GETOPT_VAL_PLUGIN_OPTS:
plugin_opts = optarg;
break;
case GETOPT_VAL_PLUGIN_MODE:
plugin_mode = parse_plugin_mode(optarg);
plugin_mode_set = 1;
break;
case GETOPT_VAL_KEY:
key = optarg;
break;
Expand Down Expand Up @@ -920,6 +928,9 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
if (plugin_opts == NULL) {
plugin_opts = conf->plugin_opts;
}
if (!plugin_mode_set) {
plugin_mode = conf->plugin_mode;
}
if (reuse_port == 0) {
reuse_port = conf->reuse_port;
}
Expand Down Expand Up @@ -1040,7 +1051,11 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
}

if (plugin != NULL) {
uint16_t port = get_local_port();
if (!plugin_mode_is_subset(plugin_mode, mode)) {
FATAL("plugin_mode must be a subset of mode");
}
int with_udp = mode_has_udp(mode) && mode_has_udp(plugin_mode);
uint16_t port = get_local_port(with_udp);
if (port == 0) {
FATAL("failed to find a free port");
}
Expand All @@ -1054,7 +1069,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.

#ifdef __MINGW32__
memset(&plugin_watcher, 0, sizeof(plugin_watcher));
plugin_watcher.port = get_local_port();
plugin_watcher.port = get_local_port(0);
if (plugin_watcher.port == 0) {
LOGE("failed to assign a control port for plugin");
}
Expand Down Expand Up @@ -1177,7 +1192,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
#ifdef __MINGW32__
plugin_watcher.port,
#endif
MODE_CLIENT);
ROLE_CLIENT);
if (err) {
ERROR("start_plugin");
FATAL("failed to start the plugin");
Expand All @@ -1203,7 +1218,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
char *host = remote_addr[i].host;
char *port = remote_addr[i].port == NULL ? remote_port :
remote_addr[i].port;
if (plugin != NULL) {
if (plugin != NULL && mode_has_tcp(plugin_mode)) {
host = plugin_host;
port = plugin_port;
}
Expand All @@ -1212,7 +1227,7 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
}
++remote_count;

if (plugin != NULL)
if (plugin != NULL && mode_has_tcp(plugin_mode))
break;
}
ss::relay::TcpConfig tcp_config;
Expand Down Expand Up @@ -1252,6 +1267,10 @@ Same behavior as `-S`; see that option for details. Short alias: `-S`.
LOGI("udprelay enabled");
char *host = remote_addr[0].host;
char *port = remote_addr[0].port == NULL ? remote_port : remote_addr[0].port;
if (plugin != NULL && mode_has_udp(plugin_mode)) {
host = plugin_host;
port = plugin_port;
}
struct sockaddr_storage udp_remote;
memset(&udp_remote, 0, sizeof(udp_remote));
if (get_sockaddr(host, port, &udp_remote, 1, ipv6first) == -1) {
Expand Down
33 changes: 33 additions & 0 deletions src/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,11 @@ build_config(char *prefix, struct manager_ctx *manager, struct server *server)
fprintf(f, ",\n\"plugin_opts\":");
write_json_string(f, server->plugin_opts);
}
if (server->plugin_mode != -1) {
fprintf(f, ",\n\"plugin_mode\":");
write_json_string(f, server->plugin_mode == UDP_ONLY ? "udp_only" :
server->plugin_mode == TCP_AND_UDP ? "tcp_and_udp" : "tcp_only");
}
fprintf(f, "\n}\n");
fclose(f);
ss_free(path);
Expand Down Expand Up @@ -628,6 +633,18 @@ start_server_process(struct manager_ctx *manager, struct server *server)
add_server_arg(argv, &argc, ARRAY_SIZE(argv), manager->plugin_opts) == -1)) {
goto ERROR;
}
if (server->plugin_mode == -1 && manager->plugin_mode == UDP_ONLY) {
if (add_server_arg(argv, &argc, ARRAY_SIZE(argv), (char *)"--plugin-mode") == -1 ||
add_server_arg(argv, &argc, ARRAY_SIZE(argv), (char *)"udp_only") == -1) {
goto ERROR;
}
}
if (server->plugin_mode == -1 && manager->plugin_mode == TCP_AND_UDP) {
if (add_server_arg(argv, &argc, ARRAY_SIZE(argv), (char *)"--plugin-mode") == -1 ||
add_server_arg(argv, &argc, ARRAY_SIZE(argv), (char *)"tcp_and_udp") == -1) {
goto ERROR;
}
}
if (manager->nameservers &&
(add_server_arg(argv, &argc, ARRAY_SIZE(argv), (char *)"-d") == -1 ||
add_server_arg(argv, &argc, ARRAY_SIZE(argv), manager->nameservers) == -1)) {
Expand Down Expand Up @@ -827,6 +844,10 @@ get_server(char *buf, int len)
if (value->type == json_string) {
server->plugin_opts = strdup(value->u.string.ptr);
}
} else if (strcmp(name, "plugin_mode") == 0) {
if (value->type == json_string) {
server->plugin_mode = parse_plugin_mode(value->u.string.ptr);
}
} else if (strcmp(name, "mode") == 0) {
if (value->type == json_string) {
server->mode = strdup(value->u.string.ptr);
Expand Down Expand Up @@ -1481,6 +1502,7 @@ main(int argc, char **argv)
char *manager_address = NULL;
char *plugin = NULL;
char *plugin_opts = NULL;
int plugin_mode = TCP_ONLY;
char *workdir = NULL;

int fast_open = 0;
Expand Down Expand Up @@ -1620,6 +1642,7 @@ Same behavior as `-d`; see that option for details. Short alias: `-d`.
\snippet{doc} utils.cpp cli_long_mtu
\snippet{doc} utils.cpp cli_long_plugin
\snippet{doc} utils.cpp cli_long_plugin_opts
\snippet{doc} utils.cpp cli_long_plugin_mode
\snippet{doc} utils.cpp cli_long_password
\snippet{doc} utils.cpp cli_long_workdir
\snippet{doc} utils.cpp cli_long_help
Expand Down Expand Up @@ -1652,13 +1675,15 @@ Same behavior as `-d`; see that option for details. Short alias: `-d`.
{ "mtu", required_argument, NULL, GETOPT_VAL_MTU },
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
{ "plugin-mode", required_argument, NULL, GETOPT_VAL_PLUGIN_MODE },
{ "password", required_argument, NULL, GETOPT_VAL_PASSWORD },
{ "workdir", required_argument, NULL, GETOPT_VAL_WORKDIR },
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
{ NULL, 0, NULL, 0 }
};

int mode_set = 0;
int plugin_mode_set = 0;
int ipv6first_set = 0;
opterr = 0;

Expand Down Expand Up @@ -1707,6 +1732,10 @@ Same behavior as `-d`; see that option for details. Short alias: `-d`.
case GETOPT_VAL_PLUGIN_OPTS:
plugin_opts = optarg;
break;
case GETOPT_VAL_PLUGIN_MODE:
plugin_mode = parse_plugin_mode(optarg);
plugin_mode_set = 1;
break;
case 's':
if (server_num < MAX_REMOTE_NUM) {
server_host[server_num++] = optarg;
Expand Down Expand Up @@ -1834,6 +1863,9 @@ Same behavior as `-d`; see that option for details. Short alias: `-d`.
if (plugin_opts == NULL) {
plugin_opts = conf->plugin_opts;
}
if (!plugin_mode_set) {
plugin_mode = conf->plugin_mode;
}
if (!ipv6first_set) {
ipv6first = conf->ipv6_first;
}
Expand Down Expand Up @@ -1992,6 +2024,7 @@ Same behavior as `-d`; see that option for details. Short alias: `-d`.
manager.mtu = mtu;
manager.plugin = plugin;
manager.plugin_opts = plugin_opts;
manager.plugin_mode = plugin_mode;
manager.ipv6first = ipv6first;
manager.workdir = workdir;
#ifdef HAVE_SETRLIMIT
Expand Down
2 changes: 2 additions & 0 deletions src/manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct manager_ctx {
char *user;
char *plugin;
char *plugin_opts;
int plugin_mode;
char *manager_address;
char **hosts;
int host_num;
Expand All @@ -73,6 +74,7 @@ struct server : ss::ListNode<> {
char *method = nullptr;
char *plugin = nullptr;
char *plugin_opts = nullptr;
int plugin_mode = -1;
uint64_t traffic = 0;
};

Expand Down
Loading