diff --git a/src/addr.c b/src/addr.c index 9fac9a5a..2b559666 100644 --- a/src/addr.c +++ b/src/addr.c @@ -375,7 +375,7 @@ hsk_addr_from_string(hsk_addr_t *addr, const char *src, uint16_t port) { uint16_t sin_port = port; - if (port && port_s) { + if (port_s) { int i = 0; uint32_t word = 0; char *s = port_s; @@ -396,8 +396,10 @@ hsk_addr_from_string(hsk_addr_t *addr, const char *src, uint16_t port) { } sin_port = (uint16_t)word; - } else if (!port && port_s) { - return false; + } else if (!port) { + sin_port = at ? HSK_BRONTIDE_PORT : HSK_PORT; + } else { + sin_port = port; } uint8_t sin_addr[16]; @@ -446,8 +448,7 @@ hsk_addr_to_string( if (!port) port = fb; - // XXX Not thread safe. - static char tmp[HSK_MAX_HOST]; + char tmp[HSK_MAX_HOST]; if (af == AF_INET6) { assert(len + need < HSK_MAX_HOST); @@ -487,8 +488,7 @@ hsk_addr_to_full( char b32[54]; hsk_base32_encode(addr->key, 33, b32, false); - // XXX Not thread safe. - static char tmp[HSK_MAX_HOST]; + char tmp[HSK_MAX_HOST]; sprintf(tmp, "%s@%s", b32, dst); strcpy(dst, tmp); @@ -515,8 +515,7 @@ hsk_addr_to_at(const hsk_addr_t *addr, char *dst, size_t dst_len, uint16_t fb) { if (!port) port = fb; - // XXX Not thread safe. - static char tmp[HSK_MAX_HOST]; + char tmp[HSK_MAX_HOST]; sprintf(tmp, "%s@%u", dst, port); strcpy(dst, tmp); } @@ -940,7 +939,11 @@ hsk_addr_print(const hsk_addr_t *addr, const char *prefix) { char host[HSK_MAX_HOST]; assert(hsk_addr_to_string(addr, host, HSK_MAX_HOST, HSK_BRONTIDE_PORT)); + char b32[54]; + hsk_base32_encode(addr->key, 33, b32, false); + printf("%saddr\n", prefix); + printf("%skey=%s\n", prefix, b32); printf("%s type=%d\n", prefix, addr->type); printf("%s host=%s\n", prefix, host); } diff --git a/src/addrmgr.c b/src/addrmgr.c index 950863ba..929e3a09 100644 --- a/src/addrmgr.c +++ b/src/addrmgr.c @@ -57,7 +57,7 @@ hsk_addrman_init(hsk_addrman_t *am, const hsk_timedata_t *td) { const char **seed; for (seed = hsk_seeds; *seed; seed++) { hsk_addr_t addr; - assert(hsk_addr_from_string(&addr, *seed, HSK_BRONTIDE_PORT)); + assert(hsk_addr_from_string(&addr, *seed, 0)); assert(hsk_addrman_add_addr(am, &addr)); } diff --git a/src/pool.c b/src/pool.c index 5d239d97..818ca49a 100644 --- a/src/pool.c +++ b/src/pool.c @@ -53,7 +53,7 @@ typedef struct hsk_write_data_s { */ static hsk_peer_t * -hsk_peer_alloc(hsk_pool_t *pool); +hsk_peer_alloc(hsk_pool_t *pool, bool encrypted); static void hsk_peer_free(hsk_peer_t *peer); @@ -91,6 +91,9 @@ hsk_peer_send_ping(hsk_peer_t *peer, uint64_t nonce); static int hsk_peer_send_getheaders(hsk_peer_t *peer, const uint8_t *stop); +static int +hsk_peer_send_getaddr(hsk_peer_t *peer); + static int hsk_peer_send_getproof( hsk_peer_t *peer, @@ -260,20 +263,23 @@ hsk_pool_set_seeds(hsk_pool_t *pool, const char *seeds) { continue; } - if (size >= HSK_MAX_HOST) - return false; + if (size >= HSK_MAX_HOST) { + hsk_pool_log(pool, "seed address exceeds maximum length allowed.\n"); + continue; + } memcpy(&seed[0], &seeds[start], size); seed[size] = '\0'; - if (!hsk_addr_from_string(&addr, seed, HSK_BRONTIDE_PORT)) - return false; - - if (!hsk_addr_has_key(&addr)) - return false; + if (!hsk_addr_from_string(&addr, seed, 0)) { + hsk_pool_log(pool, "could not parse seed from string: %s\n", seed); + continue; + } - if (!hsk_addrman_add_addr(&pool->am, &addr)) - return false; + if (!hsk_addrman_add_addr(&pool->am, &addr)) { + hsk_pool_log(pool, "could not add seed: %s\n", seed); + continue; + } start = i + 1; } @@ -377,20 +383,20 @@ hsk_pool_getaddr(hsk_pool_t *pool, hsk_addr_t *addr) { static int hsk_pool_refill(hsk_pool_t *pool) { - while (pool->size < pool->max_size) { + if (pool->size < pool->max_size) { hsk_addr_t addr; if (!hsk_pool_getaddr(pool, &addr)) { hsk_pool_debug(pool, "could not find suitable addr\n"); - break; + return HSK_SUCCESS; } - if (!hsk_ec_verify_pubkey(pool->ec, addr.key)) { + if (hsk_addr_has_key(&addr) && !hsk_ec_verify_pubkey(pool->ec, addr.key)) { hsk_addrman_remove_addr(&pool->am, &addr); - continue; + return HSK_SUCCESS; } - hsk_peer_t *peer = hsk_peer_alloc(pool); + hsk_peer_t *peer = hsk_peer_alloc(pool, hsk_addr_has_key(&addr)); if (!peer) { hsk_pool_log(pool, "could not allocate peer\n"); @@ -782,7 +788,7 @@ hsk_pool_timer(hsk_pool_t *pool) { */ static int -hsk_peer_init(hsk_peer_t *peer, hsk_pool_t *pool) { +hsk_peer_init(hsk_peer_t *peer, hsk_pool_t *pool, bool encrypted) { if (!peer || !pool) return HSK_EBADARGS; @@ -793,13 +799,17 @@ hsk_peer_init(hsk_peer_t *peer, hsk_pool_t *pool) { peer->loop = pool->loop; // peer->socket; - hsk_brontide_init(&peer->brontide, pool->ec); - peer->brontide.connect_cb = after_brontide_connect; - peer->brontide.connect_arg = (void *)peer; - peer->brontide.write_cb = brontide_do_write; - peer->brontide.write_arg = (void *)peer; - peer->brontide.read_cb = after_brontide_read; - peer->brontide.read_arg = (void *)peer; + peer->brontide = NULL; + if (encrypted) { + peer->brontide = malloc(sizeof(hsk_brontide_t)); + hsk_brontide_init(peer->brontide, pool->ec); + peer->brontide->connect_cb = after_brontide_connect; + peer->brontide->connect_arg = (void *)peer; + peer->brontide->write_cb = brontide_do_write; + peer->brontide->write_arg = (void *)peer; + peer->brontide->read_cb = after_brontide_read; + peer->brontide->read_arg = (void *)peer; + } peer->id = pool->peer_id++; memset(peer->host, 0, sizeof(peer->host)); @@ -846,7 +856,8 @@ hsk_peer_uninit(hsk_peer_t *peer) { if (!peer) return; - hsk_brontide_uninit(&peer->brontide); + if (peer->brontide != NULL) + hsk_brontide_uninit(peer->brontide); hsk_map_uninit(&peer->names); @@ -857,13 +868,13 @@ hsk_peer_uninit(hsk_peer_t *peer) { } static hsk_peer_t * -hsk_peer_alloc(hsk_pool_t *pool) { +hsk_peer_alloc(hsk_pool_t *pool, bool encrypted) { hsk_peer_t *peer = malloc(sizeof(hsk_peer_t)); if (!peer) return NULL; - if (hsk_peer_init(peer, pool) != HSK_SUCCESS) { + if (hsk_peer_init(peer, pool, encrypted) != HSK_SUCCESS) { hsk_peer_free(peer); return NULL; } @@ -885,6 +896,8 @@ hsk_peer_open(hsk_peer_t *peer, const hsk_addr_t *addr) { assert(peer && addr); assert(peer->pool && peer->loop && peer->state == HSK_STATE_DISCONNECTED); + peer->state = HSK_STATE_CONNECTING; + hsk_pool_t *pool = (hsk_pool_t *)peer->pool; uv_loop_t *loop = pool->loop; @@ -908,14 +921,22 @@ hsk_peer_open(hsk_peer_t *peer, const hsk_addr_t *addr) { assert(hsk_addr_to_sa(addr, sa)); - assert(hsk_brontide_connect(&peer->brontide, pool->key, addr->key) == 0); + if (peer->brontide != NULL) + assert(hsk_brontide_connect(peer->brontide, pool->key, addr->key) == 0); if (uv_tcp_connect(conn, &peer->socket, sa, on_connect) != 0) { free(conn); return HSK_EFAILURE; } - peer->state = HSK_STATE_CONNECTING; + hsk_peer_t *peerIter, *next; + uint64_t active = 0; + for (peerIter = pool->head; peerIter; peerIter = next) { + next = peerIter->next; + if (peerIter->state == HSK_STATE_HANDSHAKE) + active++; + } + hsk_pool_log(pool, "size: %d active: %d\n", pool->size, active); return HSK_SUCCESS; } @@ -926,7 +947,8 @@ hsk_peer_close(hsk_peer_t *peer) { case HSK_STATE_DISCONNECTING: return HSK_SUCCESS; case HSK_STATE_HANDSHAKE: - hsk_brontide_destroy(&peer->brontide); + if (peer->brontide != NULL) + hsk_brontide_destroy(peer->brontide); case HSK_STATE_READING: assert(uv_read_stop((uv_stream_t *)&peer->socket) == 0); case HSK_STATE_CONNECTED: @@ -1032,21 +1054,6 @@ hsk_peer_remove(hsk_peer_t *peer) { assert(hsk_map_del(&pool->peers, &peer->addr)); } -static int -hsk_peer_write( - hsk_peer_t *peer, - uint8_t *data, - size_t data_len, - bool should_free -) { - if (peer->state != HSK_STATE_HANDSHAKE) - return HSK_SUCCESS; - - assert(should_free); - - return hsk_brontide_write(&peer->brontide, data, data_len); -} - static int hsk_peer_write_raw( hsk_peer_t *peer, @@ -1113,6 +1120,27 @@ hsk_peer_write_raw( return rc; } +static int +hsk_peer_write( + hsk_peer_t *peer, + uint8_t *data, + size_t data_len, + bool should_free +) { + if (peer->state != HSK_STATE_HANDSHAKE) + return HSK_SUCCESS; + + assert(should_free); + + int rc; + if (peer->brontide != NULL) { + rc = hsk_brontide_write(peer->brontide, data, data_len); + } else { + rc = hsk_peer_write_raw(peer, data, data_len, true); + } + return rc; +} + static int hsk_peer_send(hsk_peer_t *peer, const hsk_msg_t *msg) { int msg_size = hsk_msg_size(msg); @@ -1203,6 +1231,13 @@ hsk_peer_send_sendheaders(hsk_peer_t *peer) { return hsk_peer_send(peer, (hsk_msg_t *)&msg); } +static int +hsk_peer_send_getaddr(hsk_peer_t *peer) { + hsk_peer_log(peer, "sending getaddr\n"); + hsk_version_msg_t msg = { .cmd = HSK_MSG_GETADDR }; + return hsk_peer_send(peer, (hsk_msg_t *)&msg); +} + static int hsk_peer_send_getheaders(hsk_peer_t *peer, const uint8_t *stop) { hsk_peer_log(peer, "sending getheaders\n"); @@ -1255,6 +1290,13 @@ hsk_peer_handle_version(hsk_peer_t *peer, const hsk_version_msg_t *msg) { if (rc != HSK_SUCCESS) return rc; + // Discover more peers + rc = hsk_peer_send_getaddr(peer); + + if (rc != HSK_SUCCESS) + return rc; + + // Start syncing return hsk_peer_send_getheaders(peer, NULL); } @@ -1336,7 +1378,7 @@ hsk_peer_handle_addr(hsk_peer_t *peer, hsk_addr_msg_t *msg) { if (addr->addr.port == 0) continue; - if (!hsk_addr_has_key(&addr->addr)) + if (hsk_addr_has_key(&addr->addr)) continue; hsk_addrman_add_na(&pool->am, addr); @@ -1406,7 +1448,10 @@ hsk_peer_handle_headers(hsk_peer_t *peer, const hsk_headers_msg_t *msg) { if (rc != HSK_SUCCESS) { hsk_peer_log(peer, "failed adding block: %s\n", hsk_strerror(rc)); - return rc; + if (rc == HSK_EDUPLICATE) + return HSK_SUCCESS; + else + return rc; } peer->headers += 1; @@ -1558,7 +1603,10 @@ hsk_peer_on_read(hsk_peer_t *peer, const uint8_t *data, size_t data_len) { memcpy(peer->msg + peer->msg_pos, data, need); data += need; data_len -= need; - hsk_peer_parse(peer, peer->msg, peer->msg_len); + if (hsk_peer_parse(peer, peer->msg, peer->msg_len) != 0) { + hsk_peer_destroy(peer); + return; + } } memcpy(peer->msg + peer->msg_pos, data, data_len); @@ -1697,13 +1745,19 @@ on_connect(uv_connect_t *conn, int status) { peer->state = HSK_STATE_READING; peer->conn_time = hsk_now(); - int r = hsk_brontide_on_connect(&peer->brontide); + if (peer->brontide != NULL) { + int r = hsk_brontide_on_connect(peer->brontide); - if (r != HSK_SUCCESS) { - hsk_peer_log(peer, "brontide_on_connect failed: %s\n", hsk_strerror(r)); - hsk_peer_destroy(peer); + if (r != HSK_SUCCESS) { + hsk_peer_log(peer, "brontide_on_connect failed: %s\n", hsk_strerror(r)); + hsk_peer_destroy(peer); + return; + } return; } + + peer->state = HSK_STATE_HANDSHAKE; + hsk_peer_send_version(peer); } static void @@ -1749,24 +1803,31 @@ after_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { if (!peer) return; + if (peer->brontide != NULL) { + int r = hsk_brontide_on_read( + peer->brontide, + (uint8_t *)buf->base, + (size_t)nread + ); + if (r != HSK_SUCCESS) { + hsk_peer_log(peer, "brontide_on_read failed: %s\n", hsk_strerror(r)); + hsk_peer_destroy(peer); + return; + } + } else { + hsk_peer_on_read( + peer, + (uint8_t *)buf->base, + (size_t)nread + ); + } + if (nread < 0) { if (nread != UV_EOF) hsk_peer_log(peer, "read error: %s\n", uv_strerror(nread)); hsk_peer_destroy(peer); return; } - - int r = hsk_brontide_on_read( - &peer->brontide, - (uint8_t *)buf->base, - (size_t)nread - ); - - if (r != HSK_SUCCESS) { - hsk_peer_log(peer, "brontide_on_read failed: %s\n", hsk_strerror(r)); - hsk_peer_destroy(peer); - return; - } } static void diff --git a/src/pool.h b/src/pool.h index 7407e116..cd859e56 100644 --- a/src/pool.h +++ b/src/pool.h @@ -56,11 +56,10 @@ typedef struct hsk_peer_s { hsk_chain_t *chain; uv_loop_t *loop; uv_tcp_t socket; - hsk_brontide_t brontide; + hsk_brontide_t *brontide; uint64_t id; char host[HSK_MAX_HOST]; hsk_addr_t addr; - uint16_t port; int state; uint8_t read_buffer[HSK_BUFFER_SIZE]; int headers;