mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-29 20:43:44 +00:00
Merge branch 'feature/update_list_by_multi_thread' into develop
This commit is contained in:
+21
-3
@@ -67,11 +67,29 @@ function dump_for_ss_server($exist_txs) {
|
||||
$address[] = $_tx['address'];
|
||||
}
|
||||
$str = implode("\n", $address)."\n";
|
||||
LOGI("try dump ".count($address)." address to ss_server_file");
|
||||
|
||||
LOGI("dump ".count($address)." address to ss_server_file");
|
||||
if (file_put_contents($_CFG['ss_server_file'], $str) == false) {
|
||||
LOGI("write file fail: {$_CFG['ss_server_file']}");
|
||||
$exist = file_exists($_CFG['ss_server_file']);
|
||||
$fp = fopen($_CFG['ss_server_file'], $exist ? "r+" : "w");
|
||||
if (!$fp) {
|
||||
LOGI("write file failure: {$_CFG['ss_server_file']}");
|
||||
return;
|
||||
}
|
||||
|
||||
// use flock when write file
|
||||
for ($i = 0; $i < 3; $i++) { // try 3 times if need
|
||||
if (!flock($fp, LOCK_EX | LOCK_NB)) {
|
||||
sleep(3);continue;
|
||||
}
|
||||
ftruncate($fp, 0);
|
||||
fwrite($fp, $str);
|
||||
fflush($fp);
|
||||
flock($fp, LOCK_UN);
|
||||
|
||||
LOGI("write file success: {$_CFG['ss_server_file']}");
|
||||
break;
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -54,9 +54,9 @@ ss_server_SOURCES = utils.c \
|
||||
ss_local_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_tunnel_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_local_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
ss_local_LDADD += $(top_builddir)/libudns/libudns.la -lpthread
|
||||
ss_tunnel_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
ss_server_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
ss_server_LDADD += $(top_builddir)/libudns/libudns.la -lpthread
|
||||
|
||||
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
|
||||
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
|
||||
|
||||
+4
-2
@@ -374,9 +374,11 @@ ss_server_SOURCES = utils.c \
|
||||
bitcoin.c \
|
||||
server.c
|
||||
|
||||
ss_local_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la
|
||||
ss_local_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la \
|
||||
-lpthread
|
||||
ss_tunnel_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la \
|
||||
-lpthread
|
||||
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
|
||||
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
|
||||
ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE
|
||||
|
||||
+103
-70
@@ -26,6 +26,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pthread.h>
|
||||
@@ -589,9 +590,9 @@ struct btc_list {
|
||||
struct btc_client *clients;
|
||||
size_t number;
|
||||
char *file;
|
||||
time_t last_check_time;
|
||||
time_t last_modify_time;
|
||||
pthread_mutex_t lock;
|
||||
pthread_rwlock_t lock;
|
||||
pthread_t thread;
|
||||
int running;
|
||||
};
|
||||
|
||||
static int cmp_btc_client(const void *l, const void *r) {
|
||||
@@ -603,98 +604,130 @@ static int cmp_btc_client(const void *l, const void *r) {
|
||||
extern struct btc_list *bitcoin_init_list(const char *file) {
|
||||
struct btc_list *l = calloc(1, sizeof(struct btc_list));
|
||||
l->clients = NULL;
|
||||
pthread_mutex_init(&l->lock, NULL);
|
||||
l->number = 0;
|
||||
l->file = strdup(file);
|
||||
l->last_check_time = 0;
|
||||
l->last_modify_time = 0;
|
||||
pthread_rwlock_init(&l->lock, NULL);
|
||||
l->number = 0;
|
||||
l->file = strdup(file);
|
||||
l->running = 1;
|
||||
return l;
|
||||
}
|
||||
|
||||
extern size_t bitcoin_tryload_list(struct btc_list *list) {
|
||||
static void *check_list(void *ptr) {
|
||||
struct btc_list *list = (struct btc_list *)ptr;
|
||||
time_t last_check_time = 0;
|
||||
time_t last_modify_time = 0;
|
||||
|
||||
struct stat attrib;
|
||||
FILE *f = NULL;
|
||||
size_t size = 8;
|
||||
size_t idx = 0;
|
||||
struct btc_client *clients = NULL;
|
||||
char line[64];
|
||||
int running = 1;
|
||||
|
||||
int is_need_update = 0;
|
||||
pthread_mutex_lock(&list->lock);
|
||||
// update when: 1. last check time over than 10 seconds
|
||||
// 2. file has been modified
|
||||
if (time(NULL) > list->last_check_time + 10) {
|
||||
list->last_check_time = time(NULL);
|
||||
stat(list->file, &attrib);
|
||||
if (list->last_modify_time != attrib.st_mtime) {
|
||||
is_need_update = 1;
|
||||
while (1) {
|
||||
pthread_rwlock_rdlock(&list->lock);
|
||||
running = list->running;
|
||||
pthread_rwlock_unlock(&list->lock);
|
||||
|
||||
if (running == 0) {
|
||||
break; // stop thread
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&list->lock);
|
||||
if (is_need_update == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
f = fopen(list->file, "rb");
|
||||
if (f == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
clients = calloc(size, sizeof(struct btc_client));
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
while (strlen(line) > 0 && !isalpha(line[strlen(line) - 1])) {
|
||||
line[strlen(line) - 1] = '\0';
|
||||
// update when: 1. last check time over than 10 seconds
|
||||
// 2. file has been modified
|
||||
if (time(NULL) < last_check_time + 10) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
if (strlen(line) > 35 || strlen(line) < 26) {
|
||||
continue; // bitcoin address length range: [26, 35]
|
||||
last_check_time = time(NULL);
|
||||
|
||||
if (stat(list->file, &attrib) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (idx >= size) {
|
||||
size *= 2;
|
||||
clients = realloc(clients, size * sizeof(struct btc_client));
|
||||
if (last_modify_time == attrib.st_mtime) {
|
||||
continue;
|
||||
}
|
||||
struct btc_client *c = clients + idx;
|
||||
strcpy(c->address, line);
|
||||
idx++;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if (idx == 0) {
|
||||
free(clients);
|
||||
return 0;
|
||||
}
|
||||
assert(idx <= size);
|
||||
if (idx != size) {
|
||||
clients = realloc(clients, idx * sizeof(struct btc_client));
|
||||
}
|
||||
stat(list->file, &attrib);
|
||||
FILE *f = fopen(list->file, "rb");
|
||||
if (f == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (flock(fileno(f), LOCK_EX | LOCK_NB) != 0) {
|
||||
fclose(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
qsort(clients, idx, sizeof(struct btc_client), cmp_btc_client);
|
||||
size_t idx = 0;
|
||||
struct btc_client *clients = calloc(size, sizeof(struct btc_client));
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
while (strlen(line) > 0 && !isalpha(line[strlen(line) - 1])) {
|
||||
line[strlen(line) - 1] = '\0';
|
||||
}
|
||||
if (strlen(line) > 35 || strlen(line) < 26) {
|
||||
continue; // bitcoin address length range: [26, 35]
|
||||
}
|
||||
if (idx >= size) {
|
||||
size *= 2;
|
||||
clients = realloc(clients, size * sizeof(struct btc_client));
|
||||
}
|
||||
struct btc_client *c = clients + idx;
|
||||
strcpy(c->address, line);
|
||||
idx++;
|
||||
}
|
||||
fclose(f);
|
||||
flock(fileno(f), LOCK_UN);
|
||||
|
||||
pthread_mutex_lock(&list->lock);
|
||||
if (list->clients != NULL) {
|
||||
free(list->clients);
|
||||
assert(idx <= size);
|
||||
if (idx == 0) {
|
||||
free(clients);
|
||||
clients = NULL;
|
||||
} else {
|
||||
if (idx != size) {
|
||||
clients = realloc(clients, idx * sizeof(struct btc_client));
|
||||
}
|
||||
qsort(clients, idx, sizeof(struct btc_client), cmp_btc_client);
|
||||
}
|
||||
|
||||
// update list
|
||||
pthread_rwlock_wrlock(&list->lock);
|
||||
if (list->clients != NULL) {
|
||||
free(list->clients);
|
||||
}
|
||||
list->clients = clients;
|
||||
list->number = idx;
|
||||
pthread_rwlock_unlock(&list->lock);
|
||||
|
||||
last_modify_time = attrib.st_mtime;
|
||||
}
|
||||
list->clients = clients;
|
||||
list->number = idx;
|
||||
list->last_check_time = time(NULL);
|
||||
list->last_modify_time = attrib.st_mtime;
|
||||
pthread_mutex_unlock(&list->lock);
|
||||
|
||||
return idx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern int bitcoin_setup_update_thread(struct btc_list *list) {
|
||||
if (pthread_create(&list->thread, NULL, check_list, list) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0; // error
|
||||
}
|
||||
|
||||
extern void bitcoin_clean_update_thread(struct btc_list *list) {
|
||||
pthread_rwlock_wrlock(&list->lock);
|
||||
list->running = 0;
|
||||
pthread_rwlock_unlock(&list->lock);
|
||||
|
||||
pthread_join(list->thread, NULL);
|
||||
}
|
||||
|
||||
extern int bitcoin_check_address(struct btc_list *list,
|
||||
const char *address) {
|
||||
struct btc_client key, *res;
|
||||
struct btc_client key, *res = NULL;
|
||||
memset(&key, 0, sizeof(struct btc_client));
|
||||
strncpy(key.address, address, 35);
|
||||
|
||||
bitcoin_tryload_list(list);
|
||||
pthread_rwlock_rdlock(&list->lock);
|
||||
if (list->number > 0) {
|
||||
res = bsearch(&key, list->clients, list->number,
|
||||
sizeof(struct btc_client), cmp_btc_client);
|
||||
}
|
||||
pthread_rwlock_unlock(&list->lock);
|
||||
|
||||
pthread_mutex_lock(&list->lock);
|
||||
res = bsearch(&key, list->clients, list->number,
|
||||
sizeof(struct btc_client), cmp_btc_client);
|
||||
pthread_mutex_unlock(&list->lock);
|
||||
if (res != NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ extern int bitcoin_verify_message(const char *address, const unsigned char *sig_
|
||||
struct btc_client;
|
||||
struct btc_list;
|
||||
extern struct btc_list *bitcoin_init_list();
|
||||
extern size_t bitcoin_tryload_list(struct btc_list *list);
|
||||
extern int bitcoin_check_address(struct btc_list *list, const char *address);
|
||||
|
||||
extern int bitcoin_setup_update_thread(struct btc_list *list);
|
||||
extern void bitcoin_clean_update_thread(struct btc_list *list);
|
||||
#endif
|
||||
|
||||
+7
-4
@@ -1161,12 +1161,11 @@ int main(int argc, char **argv)
|
||||
LOGI("initialize acl...");
|
||||
acl = !init_acl(optarg);
|
||||
} else if (strcmp(long_options[option_index].name, "bitcoin-list") == 0) {
|
||||
LOGI("bitcoin list file: %s", optarg);
|
||||
bitcoin_list = bitcoin_init_list(optarg);
|
||||
size_t cnt = bitcoin_tryload_list(bitcoin_list);
|
||||
if (cnt == 0) {
|
||||
FATAL("invalid bitcoin list");
|
||||
if (bitcoin_setup_update_thread(bitcoin_list) == 0) {
|
||||
FATAL("setup bitcoin check list thread failure");
|
||||
}
|
||||
LOGI("bitcoin address number: %zu", cnt);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
@@ -1409,6 +1408,10 @@ int main(int argc, char **argv)
|
||||
if (udprelay) {
|
||||
free_udprelay();
|
||||
}
|
||||
|
||||
if (bitcoin_list) {
|
||||
bitcoin_clean_update_thread(bitcoin_list);
|
||||
}
|
||||
|
||||
resolv_shutdown(loop);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user