Browse Source

add clients bitcoin address list

pull/286/head
kevin 10 years ago
parent
commit
6df063be37
4 changed files with 177 additions and 7 deletions
  1. 128
      src/bitcoin.c
  2. 6
      src/bitcoin.h
  3. 35
      src/server.c
  4. 15
      src/utils.c

128
src/bitcoin.c

@ -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;
}

6
src/bitcoin.h

@ -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

35
src/server.c

@ -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
src/utils.c

@ -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");

Loading…
Cancel
Save