From 7ddba70adac8d3dbeaae141b4b099e6359fabf8b Mon Sep 17 00:00:00 2001 From: Jose Marcial Vieira Bisneto Date: Wed, 23 Nov 2016 17:19:16 -0300 Subject: [PATCH] Initial implementation of namesys. --- include/ipfs/namesys/namesys.h | 45 +++++++++++ namesys/base.c | 47 +++++++++++ namesys/namesys.c | 137 +++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 include/ipfs/namesys/namesys.h create mode 100644 namesys/base.c create mode 100644 namesys/namesys.c diff --git a/include/ipfs/namesys/namesys.h b/include/ipfs/namesys/namesys.h new file mode 100644 index 0000000..2ce57d1 --- /dev/null +++ b/include/ipfs/namesys/namesys.h @@ -0,0 +1,45 @@ +#ifndef NAMESYS_H + #define NAMESYS_H + + #define DefaultDepthLimit 32 + + char *ErrNamesys[] = { + NULL, + "ErrAllocFailed", + "ErrNULLPointer", + "Could not publish name." + "Could not resolve name.", + "Could not resolve name (recursion limit exceeded).", + "expired record", + "unrecognized validity type" + }; + + enum { + ErrAllocFailed = 1, + ErrNULLPointer, + ErrPublishFailed, + ErrResolveFailed, + ErrResolveRecursion, + ErrExpiredRecord, + ErrUnrecognizedValidity + } NamesysErrs; + + typedef struct s_resolvers { + char *protocol; + int (*func)(char**, char*); + } resolvers; + + //TODO ciPrivKey from c-libp2p-crypto + typedef void* ciPrivKey; + + typedef struct s_publishers { + char *protocol; + int (*func) (ciPrivKey, char*); + int (*func_eol) (ciPrivKey, char*, time_t); + } publishers; + + typedef struct s_mpns { + resolvers *resolver; + publishers *Publisher; + } mpns; +#endif //NAMESYS_H diff --git a/namesys/base.c b/namesys/base.c new file mode 100644 index 0000000..96b4064 --- /dev/null +++ b/namesys/base.c @@ -0,0 +1,47 @@ +#include +#include +#include "ipfs/cid/cid.h" +#include "ipfs/path/path.h" +#include "ipfs/namesys/namesys.h" + +typedef struct s_resolver { + // resolveOnce looks up a name once (without recursion). + int (*resolveOnce) (char **, char *); +} resolver; + +int resolve (resolver *r, char **p, char *str, int depth, char **prefixes) +{ + int err, i; + char ipfs_prefix[] = "/ipfs/"; + + for (;;) { + err = r->resolveOnce(p, str); + if (err) { + //log.Warningf("Could not resolve %s", name); + *p = NULL; + return err; + } + //log.Debugf("Resolved %s to %s", name, p.String()); + if (memcmp(p, ipfs_prefix, strlen(ipfs_prefix)) == 0) { + // we've bottomed out with an IPFS path + return 0; + } + if (depth == 1) { + return ErrResolveRecursion; + } + for (i = 0 ; prefixes[i] ; i++) { + if (memcmp(*p, prefixes[i], strlen(prefixes[i])) == 0) { + if (SegmentsLength(prefixes) == 1) { + str += strlen(prefixes[i]); + } + break; + } + } + if ( !prefixes[i] ) { + return 0; + } + if (depth > 1) { + depth--; + } + } +} diff --git a/namesys/namesys.c b/namesys/namesys.c new file mode 100644 index 0000000..d4240ab --- /dev/null +++ b/namesys/namesys.c @@ -0,0 +1,137 @@ +#include +#include +#include +#include "ipfs/cid/cid.h" +#include "ipfs/path/path.h" +#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; + +// Resolve implements Resolver. +int Resolve(char *name) +{ + return ResolveN(name, DefaultDepthLimit); +} + +// ResolveN implements Resolver. +int ResolveN(char *name, int depth) +{ + char ipfs_prefix[] = "/ipfs/"; + + if (memcmp(name, ipfs_prefix, strlen(ipfs_prefix)) == 0) { + return ParsePath(name); + } + + if (*name == '/') { + int err; + char *str = malloc(sizeof(ipfs_prefix) + strlen(name)); + if (!str) { + return ErrAllocFailed; + } + strcpy(str, ipfs_prefix); + strcat(str, name+1); // ignore inital / from name, because ipfs_prefix already has it. + err = ParsePath(str); // save return value. + free (str); // so we can free allocated memory before return. + return err; + } + + return resolve(ns, name, depth, "/ipns/"); +} + +// resolveOnce implements resolver. +int resolveOnce (char **path, char *name) +{ + 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); + segs = Segments(ptr); + free (ptr); + } else { + segs = Segments(name); + } + + if (!segs || SegmentsLength(segs) < 2) { + //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) { + if (SegmentsLength(segs) > 2) { + *path = PathFromSegments(p, segs+2); + } else { + *path = p; + } + return 0; + } + } + //log.Warningf("No resolver found for %s", name); + return ErrResolveFailed; +} + +// Publish implements Publisher +int Publish (char *proto, ciPrivKey name, char *value) +{ + 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; +} + +int PublishWithEOL (char *proto, ciPrivKey name, char *value, time_t eol) +{ + 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; +}