diff --git a/include/libp2p/peer/peer.h b/include/libp2p/peer/peer.h index 2871e42..418f7fb 100644 --- a/include/libp2p/peer/peer.h +++ b/include/libp2p/peer/peer.h @@ -94,7 +94,7 @@ int libp2p_peer_matches_id(struct Libp2pPeer* in, const unsigned char* peer_id, * @param in the peer object * @returns the peer id as a null terminated string */ -char* libp2p_peer_id_to_string(struct Libp2pPeer* in); +char* libp2p_peer_id_to_string(const struct Libp2pPeer* in); /*** * Determine if we are currently connected to this peer diff --git a/peer/peer.c b/peer/peer.c index 1536f67..b7bc4a8 100644 --- a/peer/peer.c +++ b/peer/peer.c @@ -167,14 +167,18 @@ struct Libp2pPeer* libp2p_peer_copy(const struct Libp2pPeer* in) { struct Libp2pLinkedList* current_out = NULL; while (current_in != NULL) { struct MultiAddress* addr = (struct MultiAddress*)current_in->item; - struct Libp2pLinkedList* copy_item = libp2p_utils_linked_list_new(); - copy_item->item = multiaddress_copy(addr); - if (out->addr_head == NULL) { - out->addr_head = copy_item; + if (addr == NULL) { + libp2p_logger_error("peer", "Attempted to copy MultiAddress, but current item is NULL.\n"); } else { - current_out->next = copy_item; + struct Libp2pLinkedList* copy_item = libp2p_utils_linked_list_new(); + copy_item->item = multiaddress_copy(addr); + if (out->addr_head == NULL) { + out->addr_head = copy_item; + } else { + current_out->next = copy_item; + } + current_out = copy_item; } - current_out = copy_item; current_in = current_in->next; } out->sessionContext = in->sessionContext; @@ -202,7 +206,7 @@ static char string_retval[100]; * @param in the peer object * @returns the peer id as a null terminated string */ -char* libp2p_peer_id_to_string(struct Libp2pPeer* in) { +char* libp2p_peer_id_to_string(const struct Libp2pPeer* in) { memcpy(string_retval, in->id, in->id_size); string_retval[in->id_size] = 0; return string_retval; @@ -232,7 +236,11 @@ size_t libp2p_peer_protobuf_encode_size(struct Libp2pPeer* in) { while (current != NULL) { // find the length of the MultiAddress converted into bytes struct MultiAddress* data = (struct MultiAddress*)current->item; - sz += 11 + data->bsize; + if (data == NULL) { + libp2p_logger_error("peer", "encode_size: Attempted to get MultiAddress, but item was NULL.\n"); + } else { + sz += 11 + data->bsize; + } current = current->next; } } @@ -253,10 +261,14 @@ int libp2p_peer_protobuf_encode(struct Libp2pPeer* in, unsigned char* buffer, si struct Libp2pLinkedList* current = in->addr_head; while (current != NULL) { struct MultiAddress* data = (struct MultiAddress*)current->item; - retVal = protobuf_encode_length_delimited(2, WIRETYPE_LENGTH_DELIMITED, (char*)data->bytes, data->bsize, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); - if (retVal == 0) - return 0; - *bytes_written += bytes_used; + if (data == NULL) { + libp2p_logger_error("peer", "encode: Attempted to get multiaddress, but item was NULL.\n"); + } else { + retVal = protobuf_encode_length_delimited(2, WIRETYPE_LENGTH_DELIMITED, (char*)data->bytes, data->bsize, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); + if (retVal == 0) + return 0; + *bytes_written += bytes_used; + } current = current->next; } // field 3 (varint) diff --git a/peer/peerstore.c b/peer/peerstore.c index adfe692..a7085e8 100644 --- a/peer/peerstore.c +++ b/peer/peerstore.c @@ -109,6 +109,40 @@ int libp2p_peerstore_add_peer_entry(struct Peerstore* peerstore, struct PeerEntr return 1; } +int libp2p_peerstore_update_addresses(struct Libp2pPeer* existing, const struct Libp2pPeer* incoming) { + struct Libp2pLinkedList* incoming_list_pos = incoming->addr_head; + while (incoming_list_pos != NULL) { + if (incoming_list_pos->item == NULL) { + libp2p_logger_error("peerstore", "update_addresses: incoming address list has null item.\n"); + } else { + struct MultiAddress* incoming_ma = (struct MultiAddress*) incoming_list_pos->item; + // see if we have this multiaddress already + struct Libp2pLinkedList* existing_list_pos = existing->addr_head; + while (existing_list_pos != NULL) { + if (multiaddress_compare(incoming_ma, (struct MultiAddress*)existing_list_pos->item) == 0) { + // we found a match + break; + } + existing_list_pos = existing_list_pos->next; + } + if (existing_list_pos == NULL) { + // we didnt find a match. Add this multiaddress to the top of the existing peer's list + struct MultiAddress* ma_copy = multiaddress_copy(incoming_ma); + if (ma_copy == NULL) { + libp2p_logger_error("peerstore", "Attempted copy of multiaddress, but was null."); + } else { + struct Libp2pLinkedList* new_ma = libp2p_utils_linked_list_new(); + new_ma->item = multiaddress_copy(incoming_list_pos->item); + new_ma->next = existing->addr_head; + existing->addr_head = new_ma; + } + } + } + incoming_list_pos = incoming_list_pos->next; + } + return 1; +} + /*** * Add a peer to the peerstore * @param peerstore the peerstore to add the entry to @@ -123,15 +157,19 @@ int libp2p_peerstore_add_peer(struct Peerstore* peerstore, const struct Libp2pPe ma_string = ((struct MultiAddress*)peer->addr_head->item)->string; } // first check to see if it exists. If it does, return TRUE - if (libp2p_peerstore_get_peer_entry(peerstore, (unsigned char*)peer->id, peer->id_size) != NULL) { - libp2p_logger_debug("peerstore", "Attempted to add %s to peerstore, but already there.\n", ma_string); + struct PeerEntry* peer_entry = libp2p_peerstore_get_peer_entry(peerstore, (unsigned char*)peer->id, peer->id_size); + if (peer_entry != NULL) { + libp2p_logger_debug("peerstore", "Attempted to add %s to peerstore, but already there. Checking if we need to update addresses.\n", ma_string); + libp2p_peerstore_update_addresses(peer_entry->peer, peer); return 1; } if (peer->id_size > 0) { - if (peer->addr_head != NULL) { + if (peer->addr_head != NULL && peer->addr_head->item != NULL) { char* address = ((struct MultiAddress*)peer->addr_head->item)->string; - libp2p_logger_debug("peerstore", "Adding peer %s with address %s to peer store\n", peer->id, address); + libp2p_logger_debug("peerstore", "Adding peer %s with address %s to peer store\n", libp2p_peer_id_to_string(peer), address); + } else { + libp2p_logger_debug("peerstore", "Adding peer %s with no addresses to peer store.\n", libp2p_peer_id_to_string(peer)); } struct PeerEntry* peer_entry = libp2p_peer_entry_new(); if (peer_entry == NULL) { diff --git a/routing/dht_protocol.c b/routing/dht_protocol.c index f53d6d8..c512af2 100644 --- a/routing/dht_protocol.c +++ b/routing/dht_protocol.c @@ -157,15 +157,16 @@ int libp2p_routing_dht_handle_get_providers(struct SessionContext* session, stru message->provider_peer_head->item = libp2p_peer_copy(libp2p_peerstore_get_local_peer(peerstore)); } else if (libp2p_providerstore_get(providerstore, (unsigned char*)message->key, message->key_size, &peer_id, &peer_id_size)) { // Can I provide it because someone announced it earlier? - libp2p_logger_debug("dht_protocol", "I can provide a provider for this key.\n"); // we have a peer id, convert it to a peer object struct Libp2pPeer* peer = libp2p_peerstore_get_peer(peerstore, peer_id, peer_id_size); if (peer != NULL) { + libp2p_logger_debug("dht_protocol", "I can provide a provider for this key, because %s says he has it.\n", libp2p_peer_id_to_string(peer)); // add it to the message if (message->provider_peer_head == NULL) { message->provider_peer_head = libp2p_utils_linked_list_new(); message->provider_peer_head->item = libp2p_peer_copy(peer); } else { + struct Libp2pLinkedList* current = message->provider_peer_head; // find the last one in the list while (current->next != NULL) { @@ -196,7 +197,7 @@ int libp2p_routing_dht_handle_get_providers(struct SessionContext* session, stru } */ if (message->provider_peer_head != NULL) { - libp2p_logger_debug("dht_protocol", "GetProviders: We have a peer. Sending it back\n"); + libp2p_logger_debug("dht_protocol", "GetProviders: We have a peer. Sending it back."); // protobuf it and send it back if (!libp2p_routing_dht_protobuf_message(message, results, results_size)) { libp2p_logger_error("dht_protocol", "GetProviders: Error protobufing results\n"); @@ -268,6 +269,7 @@ int libp2p_routing_dht_handle_add_provider(struct SessionContext* session, struc } // add what we know to be the ip for this peer + /* char *ip; char new_string[255]; multiaddress_get_ip_address(session->default_stream->address, &ip); @@ -286,6 +288,7 @@ int libp2p_routing_dht_handle_add_provider(struct SessionContext* session, struc new_head->item = new_ma; new_head->next = peer->addr_head; peer->addr_head = new_head; + */ // now add the peer to the peerstore libp2p_logger_debug("dht_protocol", "About to add peer %s to peerstore\n", peer_ma->string); if (!libp2p_peerstore_add_peer(peerstore, peer)) diff --git a/secio/secio.c b/secio/secio.c index de658a8..7fcaf0a 100644 --- a/secio/secio.c +++ b/secio/secio.c @@ -980,6 +980,18 @@ int libp2p_secio_handshake(struct SessionContext* local_session, const struct Rs } } remote_peer->sessionContext = local_session; + // add a multiaddress to the peer (if we have what we need) + char url[100]; + sprintf(url, "/ip4/%s/tcp/%d/ipfs/%s", local_session->host, local_session->port, libp2p_peer_id_to_string(remote_peer)); + struct MultiAddress* ma = multiaddress_new_from_string(url); + if (ma == NULL) { + libp2p_logger_error("secio", "Unable to generate MultiAddress from [%s].\n", url); + } else { + libp2p_logger_debug("secio", "Adding %s to peer %s.\n", url, libp2p_peer_id_to_string(remote_peer)); + struct Libp2pLinkedList* ma_ll = libp2p_utils_linked_list_new(); + ma_ll->item = ma; + remote_peer->addr_head = ma_ll; + } } else { if (remote_peer->sessionContext != local_session) { // clean up old session context