2016-11-23 20:19:16 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include "ipfs/cid/cid.h"
|
|
|
|
#include "ipfs/path/path.h"
|
2016-11-24 22:49:26 +00:00
|
|
|
#define NAMESYS_C
|
2016-11-23 20:19:16 +00:00
|
|
|
#include "ipfs/namesys/namesys.h"
|
|
|
|
|
|
|
|
/* mpns (a multi-protocol NameSystem) implements generic IPFS naming.
|
|
|
|
*
|
|
|
|
* Uses several Resolvers:
|
|
|
|
* (a) IPFS routing naming: SFS-like PKI names.
|
|
|
|
* (b) dns domains: resolves using links in DNS TXT records
|
|
|
|
* (c) proquints: interprets string as the raw byte data.
|
|
|
|
*
|
|
|
|
* It can only publish to: (a) IPFS routing naming.
|
|
|
|
*/
|
|
|
|
|
|
|
|
mpns **ns;
|
|
|
|
// NewNameSystem will construct the IPFS naming system based on Routing
|
|
|
|
/*
|
|
|
|
func NewNameSystem(r routing.ValueStore, ds ds.Datastore, cachesize int) NameSystem {
|
|
|
|
return &mpns{
|
|
|
|
resolvers: map[string]resolver{
|
|
|
|
"dns": newDNSResolver(),
|
|
|
|
"proquint": new(ProquintResolver),
|
|
|
|
"dht": NewRoutingResolver(r, cachesize),
|
|
|
|
},
|
|
|
|
publishers: map[string]Publisher{
|
|
|
|
"/ipns/": NewRoutingPublisher(r, ds),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
const DefaultResolverCacheTTL = time.Minute;
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
// ipfs_namesys_resolve implements Resolver.
|
|
|
|
int ipfs_namesys_resolve(char **path, char *name)
|
2016-11-23 20:19:16 +00:00
|
|
|
{
|
2016-12-05 11:55:17 +00:00
|
|
|
return ipfs_namesys_resolve_n(path, name, DefaultDepthLimit);
|
2016-11-23 20:19:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
// ipfs_namesys_resolve_n implements Resolver.
|
|
|
|
int ipfs_namesys_resolve_n(char **path, char *name, int depth)
|
2016-11-23 20:19:16 +00:00
|
|
|
{
|
|
|
|
char ipfs_prefix[] = "/ipfs/";
|
2016-11-24 10:52:15 +00:00
|
|
|
char p[500];
|
|
|
|
char *ps[] = {"/ipns/", NULL};
|
|
|
|
int err;
|
|
|
|
resolver r;
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
r.resolveOnce = ipfs_namesys_resolve_once;
|
2016-11-23 20:19:16 +00:00
|
|
|
|
|
|
|
if (memcmp(name, ipfs_prefix, strlen(ipfs_prefix)) == 0) {
|
2016-12-05 11:55:17 +00:00
|
|
|
ipfs_path_parse(p, name);
|
2016-11-24 10:52:15 +00:00
|
|
|
*path = malloc(strlen(p) + 1);
|
|
|
|
if (*p) {
|
|
|
|
strcpy(*path, p);
|
|
|
|
} else {
|
|
|
|
err = ErrAllocFailed;
|
|
|
|
}
|
|
|
|
return err;
|
2016-11-23 20:19:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*name == '/') {
|
|
|
|
int err;
|
|
|
|
char *str = malloc(sizeof(ipfs_prefix) + strlen(name));
|
|
|
|
if (!str) {
|
|
|
|
return ErrAllocFailed;
|
|
|
|
}
|
|
|
|
strcpy(str, ipfs_prefix);
|
2016-11-24 10:52:15 +00:00
|
|
|
strcat(str, name+1); // ignore inital / from name, because ipfs_prefix already has it.
|
2016-12-05 11:55:17 +00:00
|
|
|
err = ipfs_path_parse(p, str); // save return value.
|
2016-11-24 10:52:15 +00:00
|
|
|
free (str); // so we can free allocated memory before return.
|
|
|
|
*path = malloc(strlen(p) + 1);
|
|
|
|
if (*p) {
|
|
|
|
strcpy(*path, p);
|
|
|
|
} else {
|
|
|
|
err = ErrAllocFailed;
|
|
|
|
}
|
2016-11-23 20:19:16 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
return ipfs_namesys_resolve(&r, path, name, depth, ps);
|
2016-11-23 20:19:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
// ipfs_namesys_resolve_once implements resolver.
|
|
|
|
int ipfs_namesys_resolve_once (char **path, char *name)
|
2016-11-23 20:19:16 +00:00
|
|
|
{
|
|
|
|
char ipns_prefix[] = "/ipns/";
|
|
|
|
char *ptr = NULL;
|
|
|
|
char **segs;
|
|
|
|
int i, err = 0;
|
|
|
|
|
|
|
|
if (!name) { // NULL pointer.
|
|
|
|
return ErrNULLPointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp (name, ipns_prefix, strlen(ipns_prefix)) == 0) { // prefix missing.
|
|
|
|
ptr = malloc(strlen(name) + sizeof(ipns_prefix));
|
|
|
|
if (!ptr) { // allocation fail.
|
|
|
|
return ErrAllocFailed;
|
|
|
|
}
|
|
|
|
strcpy(ptr, ipns_prefix);
|
|
|
|
strcat(ptr, name);
|
2016-12-05 11:55:17 +00:00
|
|
|
segs = ipfs_path_split_segments(ptr);
|
2016-11-23 20:19:16 +00:00
|
|
|
free (ptr);
|
|
|
|
} else {
|
2016-12-05 11:55:17 +00:00
|
|
|
segs = ipfs_path_split_segments(name);
|
2016-11-23 20:19:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
if (!segs || ipfs_path_segments_length(segs) < 2) {
|
2016-11-23 20:19:16 +00:00
|
|
|
//log.Warningf("Invalid name syntax for %s", name);
|
|
|
|
return ErrResolveFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0 ; ns[i] ; i++) {
|
|
|
|
char *p;
|
|
|
|
//log.Debugf("Attempting to resolve %s with %s", segments[1], ns[i]->resolver->protocol);
|
|
|
|
err = ns[i]->resolver->func(&p, segs[1]);
|
|
|
|
if (!err) {
|
2016-12-05 11:55:17 +00:00
|
|
|
if (ipfs_path_segments_length(segs) > 2) {
|
|
|
|
*path = ipfs_path_from_segments(p, segs+2);
|
2016-11-23 20:19:16 +00:00
|
|
|
} else {
|
|
|
|
*path = p;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//log.Warningf("No resolver found for %s", name);
|
|
|
|
return ErrResolveFailed;
|
|
|
|
}
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
// ipfs_namesys_publish implements Publisher
|
|
|
|
int ipfs_namesys_publish (char *proto, ciPrivKey name, char *value)
|
2016-11-23 20:19:16 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0 ; ns[i] ; i++) {
|
|
|
|
if (strcmp(ns[i]->Publisher->protocol, proto)==0) {
|
|
|
|
return ns[i]->Publisher->func(name, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ErrPublishFailed;
|
|
|
|
}
|
|
|
|
|
2016-12-05 11:55:17 +00:00
|
|
|
int ipfs_namesys_publish_with_eol (char *proto, ciPrivKey name, char *value, time_t eol)
|
2016-11-23 20:19:16 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0 ; ns[i] ; i++) {
|
|
|
|
if (strcmp(ns[i]->Publisher->protocol, proto)==0) {
|
|
|
|
return ns[i]->Publisher->func_eol(name, value, eol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ErrPublishFailed;
|
|
|
|
}
|