mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-24 00:54:02 +00:00
add clients bitcoin address list
This commit is contained in:
+127
-1
@@ -22,9 +22,13 @@
|
||||
#include "bitcoin.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
@@ -574,3 +578,125 @@ error:
|
||||
if (pkey) { EC_KEY_free(pkey); }
|
||||
return fOK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct btc_client {
|
||||
char address[36];
|
||||
};
|
||||
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;
|
||||
};
|
||||
|
||||
static int cmp_btc_client(const void *l, const void *r) {
|
||||
struct btc_client *pl = (struct btc_client *)l;
|
||||
struct btc_client *pr = (struct btc_client *)r;
|
||||
return strcmp(pl->address, pr->address);
|
||||
}
|
||||
|
||||
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;
|
||||
return l;
|
||||
}
|
||||
|
||||
extern size_t bitcoin_tryload_list(struct btc_list *list) {
|
||||
struct stat attrib;
|
||||
FILE *f = NULL;
|
||||
size_t size = 8;
|
||||
size_t idx = 0;
|
||||
struct btc_client *clients = NULL;
|
||||
char line[64];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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)) {
|
||||
line[strlen(line) - 1] = '\0'; // replace \n
|
||||
if (line[strlen(line) - 1] == '\r') {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
qsort(clients, idx, sizeof(struct btc_client), cmp_btc_client);
|
||||
|
||||
pthread_mutex_lock(&list->lock);
|
||||
if (list->clients != NULL) {
|
||||
free(list->clients);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
extern int bitcoin_check_address(struct btc_list *list,
|
||||
const char *address) {
|
||||
struct btc_client key, *res;
|
||||
memset(&key, 0, sizeof(struct btc_client));
|
||||
strncpy(key.address, address, 35);
|
||||
|
||||
bitcoin_tryload_list(list);
|
||||
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -31,4 +31,10 @@ extern int bitcoin_sign_message(unsigned char *buf_65,
|
||||
extern int bitcoin_verify_message(const char *address, const unsigned char *sig_65,
|
||||
const void *msg, const size_t msglen);
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
+29
-6
@@ -104,6 +104,7 @@ int acl = 0;
|
||||
int verbose = 0;
|
||||
int udprelay = 0;
|
||||
static int fast_open = 0;
|
||||
struct btc_list *bitcoin_list = NULL;
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
static int nofile = 0;
|
||||
#endif
|
||||
@@ -548,7 +549,14 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
LOGI("connect to: %s:%d", host, ntohs(port));
|
||||
}
|
||||
|
||||
if (atyp_btc) {
|
||||
if (bitcoin_list != NULL) {
|
||||
if (atyp_btc == 0) {
|
||||
if (verbose) {
|
||||
LOGE("client should carry with bitcoin information");
|
||||
}
|
||||
close_and_free_server(EV_A_ server);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* bitcoin information:
|
||||
* +-----------+-----------+----------+
|
||||
@@ -565,7 +573,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
int64_t ts_offset = (int64_t)time(NULL) - (int64_t)ts;
|
||||
if (labs(ts_offset) > 60 * 30) {
|
||||
if (verbose) {
|
||||
LOGI("Invalid timestamp: %u, offset too large: %d",
|
||||
LOGE("invalid timestamp: %u, offset too large: %d",
|
||||
ts, (int32_t)ts_offset);
|
||||
}
|
||||
close_and_free_server(EV_A_ server);
|
||||
@@ -573,7 +581,14 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
if (!bitcoin_verify_message(address, (uint8_t *)signature, t, 4)) {
|
||||
if (verbose) {
|
||||
LOGI("Invalid signature, address: %s", address);
|
||||
LOGE("invalid signature, address: %s", address);
|
||||
}
|
||||
close_and_free_server(EV_A_ server);
|
||||
return;
|
||||
}
|
||||
if (bitcoin_check_address(bitcoin_list, address) == 0) {
|
||||
if (verbose) {
|
||||
LOGE("address \"%s\" is NOT in list", address);
|
||||
}
|
||||
close_and_free_server(EV_A_ server);
|
||||
return;
|
||||
@@ -1126,9 +1141,10 @@ int main(int argc, char **argv)
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{ "fast-open", no_argument, 0, 0 },
|
||||
{ "acl", required_argument, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
{ "fast-open", no_argument, 0, 0 },
|
||||
{ "acl", required_argument, 0, 0 },
|
||||
{ "bitcoin-list", required_argument, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
opterr = 0;
|
||||
@@ -1144,6 +1160,13 @@ int main(int argc, char **argv)
|
||||
} else if (option_index == 1) {
|
||||
LOGI("initialize acl...");
|
||||
acl = !init_acl(optarg);
|
||||
} else if (strcmp(long_options[option_index].name, "bitcoin-list") == 0) {
|
||||
bitcoin_list = bitcoin_init_list(optarg);
|
||||
size_t cnt = bitcoin_tryload_list(bitcoin_list);
|
||||
if (cnt == 0) {
|
||||
FATAL("invalid bitcoin list");
|
||||
}
|
||||
LOGI("bitcoin address number: %zu", cnt);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
|
||||
+15
@@ -266,6 +266,21 @@ void usage()
|
||||
printf(
|
||||
" only available in local and server mode\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [--bitcoin-list <bitcoin_file>] config file of address list\n");
|
||||
printf(
|
||||
" only available in server mode\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [--bitcoin-adddress <address>] config file of bitcoin address\n");
|
||||
printf(
|
||||
" only available in local mode\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [--bitcoin-privkey <private_key>] config file of private key for above address\n");
|
||||
printf(
|
||||
" only available in local mode\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [-v] verbose mode\n");
|
||||
printf("\n");
|
||||
|
||||
Reference in New Issue
Block a user