More work on ipns publisher and resolver
This commit is contained in:
parent
e094528293
commit
9425e2fee3
11 changed files with 165 additions and 56 deletions
|
@ -15,7 +15,7 @@ int ipns_validate_ipns_record (char *k, char *val);
|
||||||
* Store the hash locally, and notify the network
|
* Store the hash locally, and notify the network
|
||||||
*
|
*
|
||||||
* @param local_node the context
|
* @param local_node the context
|
||||||
* @param cid the hash
|
* @param path the "/ipfs/" or "/ipns" path
|
||||||
* @returns true(1) on success, false(0) otherwise
|
* @returns true(1) on success, false(0) otherwise
|
||||||
*/
|
*/
|
||||||
int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, struct Cid* cid);
|
int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, char* path);
|
||||||
|
|
14
include/ipfs/namesys/resolver.h
Normal file
14
include/ipfs/namesys/resolver.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ipfs/core/ipfs_node.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve an IPNS name.
|
||||||
|
* NOTE: if recursive is set to false, the result could be another ipns path
|
||||||
|
* @param local_node the context
|
||||||
|
* @param path the ipns path (i.e. "/ipns/Qm12345..")
|
||||||
|
* @param recursive true to resolve until the result is not ipns, false to simply get the next step in the path
|
||||||
|
* @param result the results (i.e. "/ipfs/QmAb12CD...")
|
||||||
|
* @returns true(1) on success, false(0) otherwise
|
||||||
|
*/
|
||||||
|
int ipfs_namesys_resolver_resolve(struct IpfsNode* local_node, const char* path, int recursive, char** results);
|
|
@ -7,7 +7,7 @@ endif
|
||||||
|
|
||||||
LFLAGS =
|
LFLAGS =
|
||||||
DEPS =
|
DEPS =
|
||||||
OBJS = base.o dns.o isdomain.o namesys.o proquint.o publisher.o pb.o name.o
|
OBJS = base.o dns.o isdomain.o namesys.o proquint.o publisher.o pb.o name.o resolver.o
|
||||||
|
|
||||||
%.o: %.c $(DEPS)
|
%.o: %.c $(DEPS)
|
||||||
$(CC) -c -o $@ $< $(CFLAGS)
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|
|
@ -174,32 +174,48 @@ int ipfs_namesys_copy_bytes(uint8_t* from, size_t from_size, uint8_t** to, size_
|
||||||
* Store the hash locally, and notify the network
|
* Store the hash locally, and notify the network
|
||||||
*
|
*
|
||||||
* @param local_node the context
|
* @param local_node the context
|
||||||
* @param cid the hash
|
* @param path the path (could be "/ipns" or "/ipfs")
|
||||||
* @returns true(1) on success, false(0) otherwise
|
* @returns true(1) on success, false(0) otherwise
|
||||||
*/
|
*/
|
||||||
int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, struct Cid* cid) {
|
int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, char* path) {
|
||||||
|
int retVal = 0;
|
||||||
|
|
||||||
// store locally
|
// store locally
|
||||||
struct DatastoreRecord* record = libp2p_datastore_record_new();
|
struct DatastoreRecord* record = libp2p_datastore_record_new();
|
||||||
if (record == NULL)
|
if (record == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// key
|
// convert this peer id into a cid
|
||||||
if (!ipfs_namesys_copy_bytes(cid->hash, cid->hash_length, &record->key, &record->key_size)) {
|
struct Cid* local_peer = NULL;
|
||||||
|
|
||||||
|
if (!ipfs_cid_decode_hash_from_base58((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, &local_peer)) {
|
||||||
libp2p_datastore_record_free(record);
|
libp2p_datastore_record_free(record);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// value
|
|
||||||
if (!ipfs_namesys_copy_bytes((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, &record->value, &record->value_size)) {
|
// key, which is the peer id
|
||||||
|
if (!ipfs_namesys_copy_bytes(local_peer->hash, local_peer->hash_length, &record->key, &record->key_size)) {
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
|
libp2p_datastore_record_free(record);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// value, which is what it should resolve to (a mutable key)
|
||||||
|
if (!ipfs_namesys_copy_bytes((uint8_t*)path, strlen(path), &record->value, &record->value_size)) {
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
libp2p_datastore_record_free(record);
|
libp2p_datastore_record_free(record);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!local_node->repo->config->datastore->datastore_put(record, local_node->repo->config->datastore)) {
|
if (!local_node->repo->config->datastore->datastore_put(record, local_node->repo->config->datastore)) {
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
libp2p_datastore_record_free(record);
|
libp2p_datastore_record_free(record);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
libp2p_datastore_record_free(record);
|
libp2p_datastore_record_free(record);
|
||||||
|
|
||||||
|
// for now, even if what is below fails because of not being connected, return TRUE
|
||||||
|
retVal = 1;
|
||||||
|
|
||||||
// propagate to network
|
// propagate to network
|
||||||
// build the KademliaMessage
|
// build the KademliaMessage
|
||||||
struct KademliaMessage* msg = libp2p_message_new();
|
struct KademliaMessage* msg = libp2p_message_new();
|
||||||
|
@ -208,31 +224,36 @@ int ipfs_namesys_publisher_publish(struct IpfsNode* local_node, struct Cid* cid)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
msg->provider_peer_head = libp2p_utils_linked_list_new();
|
msg->provider_peer_head = libp2p_utils_linked_list_new();
|
||||||
msg->provider_peer_head->item = local_node->identity->peer;
|
msg->provider_peer_head->item = libp2p_peer_copy(local_node->identity->peer);
|
||||||
// msg->Libp2pRecord
|
// msg->Libp2pRecord
|
||||||
msg->record = libp2p_record_new();
|
msg->record = libp2p_record_new();
|
||||||
if (msg->record == NULL) {
|
if (msg->record == NULL) {
|
||||||
libp2p_message_free(msg);
|
libp2p_message_free(msg);
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// KademliaMessage->Libp2pRecord->author
|
// KademliaMessage->Libp2pRecord->author
|
||||||
if (!ipfs_namesys_copy_bytes((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, (unsigned char**)&msg->record->author, &msg->record->author_size)) {
|
if (!ipfs_namesys_copy_bytes(local_peer->hash, local_peer->hash_length, (unsigned char**)&msg->record->author, &msg->record->author_size)) {
|
||||||
libp2p_message_free(msg);
|
libp2p_message_free(msg);
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// KademliaMessage->Libp2pRecord->key
|
// KademliaMessage->Libp2pRecord->key
|
||||||
if (!ipfs_namesys_copy_bytes(cid->hash, cid->hash_length, (unsigned char**)&msg->record->key, &msg->record->key_size)) {
|
if (!ipfs_namesys_copy_bytes(local_peer->hash, local_peer->hash_length, (unsigned char**)&msg->record->key, &msg->record->key_size)) {
|
||||||
libp2p_message_free(msg);
|
libp2p_message_free(msg);
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// KademliaMessage->Libp2pRecord->value
|
// KademliaMessage->Libp2pRecord->value
|
||||||
if (!ipfs_namesys_copy_bytes((unsigned char*)local_node->identity->peer->id, local_node->identity->peer->id_size, &msg->record->value, &msg->record->value_size)) {
|
if (!ipfs_namesys_copy_bytes((uint8_t*)path, strlen(path), &msg->record->value, &msg->record->value_size)) {
|
||||||
libp2p_message_free(msg);
|
libp2p_message_free(msg);
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int retVal = libp2p_routing_dht_send_message_nearest_x(&local_node->identity->private_key, local_node->peerstore, local_node->repo->config->datastore, msg, 10);
|
libp2p_routing_dht_send_message_nearest_x(&local_node->identity->private_key, local_node->peerstore, local_node->repo->config->datastore, msg, 10);
|
||||||
|
|
||||||
libp2p_message_free(msg);
|
libp2p_message_free(msg);
|
||||||
|
ipfs_cid_free(local_peer);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libp2p/utils/logger.h"
|
||||||
|
#include "ipfs/namesys/resolver.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The opposite of publisher.c
|
* The opposite of publisher.c
|
||||||
*
|
*
|
||||||
|
@ -61,7 +66,15 @@ int ipfs_namesys_resolver_resolve(struct IpfsNode* local_node, const char* path,
|
||||||
char* current_path = (char*) malloc(strlen(path) + 1);
|
char* current_path = (char*) malloc(strlen(path) + 1);
|
||||||
strcpy(current_path, path);
|
strcpy(current_path, path);
|
||||||
|
|
||||||
|
// if we go more than 10 deep, bail
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
if (counter > 10) {
|
||||||
|
libp2p_logger_error("resolver", "Resolver looped %d times. Infinite loop? Last result: %s.\n", counter, current_path);
|
||||||
|
free(current_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
// resolve the current path
|
// resolve the current path
|
||||||
if (!ipfs_namesys_resolver_resolve_once(local_node, current_path, &result)) {
|
if (!ipfs_namesys_resolver_resolve_once(local_node, current_path, &result)) {
|
||||||
libp2p_logger_error("resolver", "Resolver returned false searching for %s.\n", current_path);
|
libp2p_logger_error("resolver", "Resolver returned false searching for %s.\n", current_path);
|
||||||
|
@ -73,6 +86,7 @@ int ipfs_namesys_resolver_resolve(struct IpfsNode* local_node, const char* path,
|
||||||
current_path = (char*) malloc(strlen(result)+1);
|
current_path = (char*) malloc(strlen(result)+1);
|
||||||
strcpy(current_path, result);
|
strcpy(current_path, result);
|
||||||
free(result);
|
free(result);
|
||||||
|
counter++;
|
||||||
} while(recursive && is_ipns_string(current_path));
|
} while(recursive && is_ipns_string(current_path));
|
||||||
|
|
||||||
*results = current_path;
|
*results = current_path;
|
||||||
|
|
|
@ -253,7 +253,7 @@ int repo_fsrepo_lmdb_put(struct DatastoreRecord* datastore_record, const struct
|
||||||
if (journalstore_record->timestamp != datastore_record->timestamp) {
|
if (journalstore_record->timestamp != datastore_record->timestamp) {
|
||||||
// we need to update
|
// we need to update
|
||||||
journalstore_record->timestamp = datastore_record->timestamp;
|
journalstore_record->timestamp = datastore_record->timestamp;
|
||||||
lmdb_journalstore_cursor_put(journalstore_cursor, journalstore_record);
|
retVal = lmdb_journalstore_cursor_put(journalstore_cursor, journalstore_record);
|
||||||
lmdb_journalstore_cursor_close(journalstore_cursor, 0);
|
lmdb_journalstore_cursor_close(journalstore_cursor, 0);
|
||||||
lmdb_journal_record_free(journalstore_record);
|
lmdb_journal_record_free(journalstore_record);
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,7 +358,24 @@ int lmdb_journalstore_cursor_put(struct lmdb_trans_cursor *crsr, struct JournalR
|
||||||
libp2p_logger_error("lmdb_journalstore", "Unable to create journalstore record.\n");
|
libp2p_logger_error("lmdb_journalstore", "Unable to create journalstore record.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (mdb_cursor_put(cursor, &db_key, &db_value, 0) == 0) {
|
int retVal = mdb_cursor_put(cursor, &db_key, &db_value, 0);
|
||||||
|
if (retVal != 0) {
|
||||||
|
char* result = "";
|
||||||
|
switch (retVal) {
|
||||||
|
case(MDB_MAP_FULL):
|
||||||
|
result = "Database Full";
|
||||||
|
break;
|
||||||
|
case (MDB_TXN_FULL):
|
||||||
|
result = "Transaction has too many dirty pages";
|
||||||
|
break;
|
||||||
|
case (EACCES) :
|
||||||
|
result = "Attempt was made to write in a read only transaction";
|
||||||
|
break;
|
||||||
|
case (EINVAL) :
|
||||||
|
result = "An invalid parameter was specified";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
libp2p_logger_error("lmdb_journalstore", "Put failed with error message %d [%s].\n", retVal, result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ OBJS = testit.o test_helper.o \
|
||||||
../multibase/multibase.o \
|
../multibase/multibase.o \
|
||||||
../namesys/pb.o \
|
../namesys/pb.o \
|
||||||
../namesys/publisher.o \
|
../namesys/publisher.o \
|
||||||
|
../namesys/resolver.o \
|
||||||
../repo/init.o \
|
../repo/init.o \
|
||||||
../repo/fsrepo/*.o \
|
../repo/fsrepo/*.o \
|
||||||
../repo/config/*.o \
|
../repo/config/*.o \
|
||||||
|
|
79
test/namesys/test_namesys.h
Normal file
79
test/namesys/test_namesys.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "../test_helper.h"
|
||||||
|
#include "ipfs/cid/cid.h"
|
||||||
|
#include "ipfs/core/ipfs_node.h"
|
||||||
|
#include "ipfs/namesys/publisher.h"
|
||||||
|
#include "ipfs/namesys/resolver.h"
|
||||||
|
|
||||||
|
int test_namesys_publisher_publish() {
|
||||||
|
int retVal = 0;
|
||||||
|
struct IpfsNode* local_node = NULL;
|
||||||
|
char* hash_text = "/ipns/QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD";
|
||||||
|
char* repo_path = "/tmp/ipfs_1";
|
||||||
|
|
||||||
|
// get a local node
|
||||||
|
if (!ipfs_node_offline_new(repo_path, &local_node)) {
|
||||||
|
libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to publish
|
||||||
|
if (!ipfs_namesys_publisher_publish(local_node, hash_text)) {
|
||||||
|
libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = 1;
|
||||||
|
exit:
|
||||||
|
ipfs_node_free(NULL, local_node);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_namesys_resolver_resolve() {
|
||||||
|
int retVal = 0;
|
||||||
|
struct IpfsNode* local_node = NULL;
|
||||||
|
char* hash_text = "QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD"; // the hash of a hello, world file
|
||||||
|
char ipns_path[512] = ""; // the Peer ID of config.test1
|
||||||
|
char* repo_path = "/tmp/ipfs_1";
|
||||||
|
char* peer_id = NULL;
|
||||||
|
char* result = NULL;
|
||||||
|
|
||||||
|
drop_and_build_repository(repo_path, 4001, NULL, &peer_id);
|
||||||
|
|
||||||
|
// get a local node
|
||||||
|
if (!ipfs_node_offline_new(repo_path, &local_node)) {
|
||||||
|
libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set ipns_path
|
||||||
|
sprintf(ipns_path, "/ipfs/%s", peer_id);
|
||||||
|
|
||||||
|
// attempt to publish
|
||||||
|
if (!ipfs_namesys_publisher_publish(local_node, hash_text)) {
|
||||||
|
libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to retrieve
|
||||||
|
if (!ipfs_namesys_resolver_resolve(local_node, ipns_path, 1, &result)) {
|
||||||
|
libp2p_logger_error("test_namesys", "Could not resolve %s.\n", hash_text);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(result, hash_text) != 0) {
|
||||||
|
libp2p_logger_error("test_namesys", "Retrieve wrong result. %s should be %s.\n", result, hash_text);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
libp2p_logger_error("test_namesys", "Asked for %s and received %s. Success!\n", ipns_path, result);
|
||||||
|
|
||||||
|
retVal = 1;
|
||||||
|
exit:
|
||||||
|
ipfs_node_free(NULL, local_node);
|
||||||
|
if (result != NULL)
|
||||||
|
free(result);
|
||||||
|
return retVal;
|
||||||
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "ipfs/cid/cid.h"
|
|
||||||
#include "ipfs/core/ipfs_node.h"
|
|
||||||
#include "ipfs/namesys/publisher.h"
|
|
||||||
|
|
||||||
int test_namesys_publisher_publish() {
|
|
||||||
int retVal = 0;
|
|
||||||
struct IpfsNode* local_node = NULL;
|
|
||||||
struct Cid* cid = NULL;
|
|
||||||
char* hash_text = "QmZtAEqmnXMZkwVPKdyMGxUoo35cQMzNhmq6CN3DvgRwAD";
|
|
||||||
char* repo_path = "/tmp/ipfs_1/.ipfs";
|
|
||||||
pthread_t api_pth = 0;
|
|
||||||
|
|
||||||
// get a local node
|
|
||||||
if (!ipfs_node_offline_new(repo_path, &local_node)) {
|
|
||||||
libp2p_logger_error("test_publisher", "publish: Unable to open ipfs repository.\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get a cid
|
|
||||||
if (!ipfs_cid_decode_hash_from_base58((unsigned char*)hash_text, strlen(hash_text), &cid)) {
|
|
||||||
libp2p_logger_error("test_publisher", "publish: Unable to convert hash from base58.\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempt to publish
|
|
||||||
if (!ipfs_namesys_publisher_publish(local_node, cid)) {
|
|
||||||
libp2p_logger_error("test_publisher", "publish: Unable to publish %s.\n", hash_text);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
retVal = 1;
|
|
||||||
exit:
|
|
||||||
ipfs_node_free(&api_pth, local_node);
|
|
||||||
ipfs_cid_free(cid);
|
|
||||||
return retVal;
|
|
||||||
}
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "flatfs/test_flatfs.h"
|
#include "flatfs/test_flatfs.h"
|
||||||
#include "journal/test_journal.h"
|
#include "journal/test_journal.h"
|
||||||
#include "merkledag/test_merkledag.h"
|
#include "merkledag/test_merkledag.h"
|
||||||
#include "namesys/test_publisher.h"
|
|
||||||
#include "node/test_node.h"
|
#include "node/test_node.h"
|
||||||
#include "node/test_importer.h"
|
#include "node/test_importer.h"
|
||||||
#include "node/test_resolver.h"
|
#include "node/test_resolver.h"
|
||||||
|
@ -27,6 +26,7 @@
|
||||||
#include "storage/test_blocks.h"
|
#include "storage/test_blocks.h"
|
||||||
#include "storage/test_unixfs.h"
|
#include "storage/test_unixfs.h"
|
||||||
#include "libp2p/utils/logger.h"
|
#include "libp2p/utils/logger.h"
|
||||||
|
#include "namesys/test_namesys.h"
|
||||||
|
|
||||||
int testit(const char* name, int (*func)(void)) {
|
int testit(const char* name, int (*func)(void)) {
|
||||||
printf("TESTING %s...\n", name);
|
printf("TESTING %s...\n", name);
|
||||||
|
@ -85,6 +85,7 @@ const char* names[] = {
|
||||||
"test_merkledag_add_node",
|
"test_merkledag_add_node",
|
||||||
"test_merkledag_add_node_with_links",
|
"test_merkledag_add_node_with_links",
|
||||||
"test_namesys_publisher_publish",
|
"test_namesys_publisher_publish",
|
||||||
|
"test_namesys_resolver_resolve",
|
||||||
"test_resolver_get",
|
"test_resolver_get",
|
||||||
"test_routing_find_peer",
|
"test_routing_find_peer",
|
||||||
"test_routing_provide" /*,
|
"test_routing_provide" /*,
|
||||||
|
@ -149,6 +150,7 @@ int (*funcs[])(void) = {
|
||||||
test_merkledag_add_node,
|
test_merkledag_add_node,
|
||||||
test_merkledag_add_node_with_links,
|
test_merkledag_add_node_with_links,
|
||||||
test_namesys_publisher_publish,
|
test_namesys_publisher_publish,
|
||||||
|
test_namesys_resolver_resolve,
|
||||||
test_resolver_get,
|
test_resolver_get,
|
||||||
test_routing_find_peer,
|
test_routing_find_peer,
|
||||||
test_routing_provide /*,
|
test_routing_provide /*,
|
||||||
|
|
Loading…
Reference in a new issue