This commit is contained in:
jmjatlanta 2016-12-21 06:40:31 -05:00
commit f8cdaf0a97
8 changed files with 198 additions and 53 deletions

View file

@ -1,14 +1,19 @@
#ifndef IPNS_NAMESYS_PB_H
#define IPNS_NAMESYS_PB_H
#include <stdint.h>
typedef int IpnsEntry_ValidityType;
typedef int32_t IpnsEntry_ValidityType;
struct ipns_entry {
// TODO
struct routingResolver *cache;
struct stime *eol;
char *value;
char *signature;
int32_t *validityType;
char *validity;
uint64_t *sequence;
uint64_t *ttl;
struct routingResolver *cache; // cache and eol should be the last items.
struct timespec *eol;
};
struct namesys_pb {
// TODO
struct ipns_entry *IpnsEntry;
@ -23,8 +28,9 @@
};
int IpnsEntry_ValidityType_value (char *s);
struct ipns_entry* ipfs_namesys_pb_new_ipns_entry ();
char* ipfs_namesys_pb_get_validity (struct ipns_entry*);
char* ipfs_ipns_entry_data_for_sig(struct ipns_entry*);
char* ipns_entry_data_for_sig(struct ipns_entry*);
char* ipfs_ipns_entry_get_signature(struct ipns_entry*);
int ipfs_namesys_pb_get_value (char**, struct ipns_entry*);
IpnsEntry_ValidityType ipfs_namesys_pb_get_validity_type (struct ipns_entry*);

View file

@ -0,0 +1,9 @@
#ifndef IPFS_PUBLISHER_H
#define IPFS_PUBLISHER_H
char* ipns_entry_data_for_sig (struct ipns_entry *entry);
int ipns_selector_func (int *idx, struct ipns_entry ***recs, char *k, char **vals);
int ipns_select_record (int *idx, struct ipns_entry **recs, char **vals);
// ipns_validate_ipns_record implements ValidatorFunc and verifies that the
// given 'val' is an IpnsEntry and that that entry is valid.
int ipns_validate_ipns_record (char *k, char *val);
#endif // IPFS_PUBLISHER_H

View file

@ -10,7 +10,7 @@
struct cacheEntry {
char *key;
char *value;
struct stime eol;
struct timespec eol;
};
struct routingResolver {
@ -29,7 +29,8 @@
// ipfs_namesys_routing_resolve_once implements resolver. Uses the IPFS
// routing system to resolve SFS-like names.
int ipfs_namesys_routing_resolve_once (char **path, char *name, int depth, char *prefix, struct namesys_pb *pb);
int ipfs_namesys_routing_check_EOL (struct stime *st, struct namesys_pb *pb);
int ipfs_namesys_routing_check_EOL (struct timespec *ts, struct namesys_pb *pb);
int ipfs_namesys_routing_get_value (char*, char*);
int ipfs_namesys_routing_getpublic_key (char*, struct MultiHash*);
#endif // IPNS_NAMESYS_ROUTING_H

View file

@ -1,12 +1,15 @@
#ifndef IPFS_TIME_H
#define IPFS_TIME_H
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif // __USE_XOPEN
struct stime {
time_t t;
struct timespec ts;
};
#ifndef __USE_ISOC11
#define __USE_ISOC11
#endif // __USE_ISOC11
int get_gmttime(struct stime *st);
int ipfs_util_time_parse_RFC3339 (struct stime *st, char *s);
char *ipfs_util_time_format_RFC3339 (struct stime *st);
#include <time.h>
int ipfs_util_time_parse_RFC3339 (struct timespec *ts, char *s);
char *ipfs_util_time_format_RFC3339 (struct timespec *ts);
#endif // IPFS_TIME_H

View file

@ -1,4 +1,5 @@
#include <string.h>
#include "ipfs/namesys/routing.h"
#include "ipfs/namesys/pb.h"
int IpnsEntry_ValidityType_value (char *s)
@ -17,3 +18,24 @@ int IpnsEntry_ValidityType_value (char *s)
return -1; // not found.
}
struct ipns_entry* ipfs_namesys_pb_new_ipns_entry ()
{
return calloc(1, sizeof (struct ipns_entry));
}
void ipfs_namesys_ipnsentry_reset (struct ipns_entry *m)
{
if (m) {
// ipns_entry is an struct of pointers,
// so we can access as an array of pointers.
char **a = (char **)m;
int i, l = (sizeof (struct ipns_entry) / sizeof (void*)) - 2; // avoid last 2 pointers, cache and eol.
for (i = 0 ; i < l ; i++) {
if (a[i]) {
free (a[i]); // free allocated pointers,
a[i] = NULL; // and mark as free.
}
}
}
}

125
namesys/publisher.c Normal file
View file

@ -0,0 +1,125 @@
#include <stdlib.h>
#include <string.h>
#include "ipfs/errs.h"
#include "ipfs/util/time.h"
#include "ipfs/namesys/pb.h"
#include "ipfs/namesys/publisher.h"
char* ipns_entry_data_for_sig (struct ipns_entry *entry)
{
char *ret;
if (!entry || !entry->value || !entry->validity) {
return NULL;
}
ret = calloc (1, strlen(entry->value) + strlen (entry->validity) + sizeof(IpnsEntry_ValidityType) + 1);
if (ret) {
strcpy(ret, entry->value);
strcat(ret, entry->validity);
if (entry->validityType) {
memcpy(ret+strlen(entry->value)+strlen(entry->validity), entry->validityType, sizeof(IpnsEntry_ValidityType));
} else {
memcpy(ret+strlen(entry->value)+strlen(entry->validity), &IpnsEntry_EOL, sizeof(IpnsEntry_ValidityType));
}
}
return ret;
}
int ipns_selector_func (int *idx, struct ipns_entry ***recs, char *k, char **vals)
{
int err, i, c;
if (!idx || !recs || !k || !vals) {
return ErrInvalidParam;
}
for (c = 0 ; vals[c] ; c++); // count array
*recs = calloc(c+1, sizeof (void*)); // allocate return array.
if (!*recs) {
return ErrAllocFailed;
}
for (i = 0 ; i < c ; i++) {
*recs[i] = calloc(1, sizeof (struct ipns_entry)); // alloc every record
if (!*recs[i]) {
return ErrAllocFailed;
}
//err = proto.Unmarshal(vals[i], *recs[i]); // and decode.
if (err) {
ipfs_namesys_ipnsentry_reset (*recs[i]); // make sure record is empty.
}
}
return ipns_select_record(idx, *recs, vals);
}
int ipns_select_record (int *idx, struct ipns_entry **recs, char **vals)
{
int err, i, best_i = -1, best_seq = 0;
struct timespec rt, bestt;
if (!idx || !recs || !vals) {
return ErrInvalidParam;
}
for (i = 0 ; recs[i] ; i++) {
if (!(recs[i]->sequence) || *(recs[i]->sequence) < best_seq) {
continue;
}
if (best_i == -1 || *(recs[i]->sequence) > best_seq) {
best_seq = *(recs[i]->sequence);
best_i = i;
} else if (*(recs[i]->sequence) == best_seq) {
err = ipfs_util_time_parse_RFC3339 (&rt, ipfs_namesys_pb_get_validity (recs[i]));
if (err) {
continue;
}
err = ipfs_util_time_parse_RFC3339 (&bestt, ipfs_namesys_pb_get_validity (recs[best_i]));
if (err) {
continue;
}
if (rt.tv_sec > bestt.tv_sec || (rt.tv_sec == bestt.tv_sec && rt.tv_nsec > bestt.tv_nsec)) {
best_i = i;
} else if (rt.tv_sec == bestt.tv_sec && rt.tv_nsec == bestt.tv_nsec) {
if (memcmp(vals[i], vals[best_i], strlen(vals[best_i])) > 0) { // FIXME: strlen?
best_i = i;
}
}
}
}
if (best_i == -1) {
return ErrNoRecord;
}
*idx = best_i;
return 0;
}
// ipns_validate_ipns_record implements ValidatorFunc and verifies that the
// given 'val' is an IpnsEntry and that that entry is valid.
int ipns_validate_ipns_record (char *k, char *val)
{
int err;
struct ipns_entry *entry = ipfs_namesys_pb_new_ipns_entry();
struct timespec ts, now;
if (!entry) {
return ErrAllocFailed;
}
//err = proto.Unmarshal(val, entry);
if (err) {
return err;
}
if (ipfs_namesys_pb_get_validity_type (entry) == IpnsEntry_EOL) {
err = ipfs_util_time_parse_RFC3339 (&ts, ipfs_namesys_pb_get_validity (entry));
if (err) {
//log.Debug("failed parsing time for ipns record EOL")
return err;
}
timespec_get (&now, TIME_UTC);
if (now.tv_nsec > ts.tv_nsec || (now.tv_nsec == ts.tv_nsec && now.tv_nsec > ts.tv_nsec)) {
return ErrExpiredRecord;
}
} else {
return ErrUnrecognizedValidity;
}
}

View file

@ -13,15 +13,15 @@ char* ipfs_routing_cache_get (char *key, struct ipns_entry *ientry)
{
int i;
struct routingResolver *cache;
struct stime now;
struct timespec now;
if (key && ientry) {
cache = ientry->cache;
if (cache) {
get_gmttime (&now);
timespec_get (&now);
for (i = 0 ; i < cache->next ; i++) {
if (((now.t < cache->data[i]->eol.t ||
(now.t == cache->data[i]->eol.t && now.ts.tv_nsec < cache->data[i]->eol.ts.tv_nsec))) &&
if (((now.tv_sec < cache->data[i]->eol.tv_sec ||
(now.tv_sec == cache->data[i]->eol.tv_sec && now.tv_nsec < cache->data[i]->eol.tv_nsec))) &&
strcmp(cache->data[i]->key, key) == 0) {
return cache->data[i]->value;
}
@ -43,8 +43,8 @@ void ipfs_routing_cache_set (char *key, char *value, struct ipns_entry *ientry)
if (n) {
n->key = key;
n->value = value;
get_gmttime (&n->eol); // now
n->eol.t += DefaultResolverCacheTTL; // sum TTL seconds to time seconds.
timespec_get (&n->eol); // now
n->eol.tv_sec += DefaultResolverCacheTTL; // sum TTL seconds to time seconds.
cache->data[cache->next++] = n;
}
}
@ -152,7 +152,7 @@ int ipfs_namesys_routing_resolve_once (char **path, char *name, int depth, char
}
// check sig with pk
err = libp2p_crypto_verify (ipfs_ipns_entry_data_for_sig(pb->IpnsEntry), ipfs_ipns_entry_get_signature(pb->IpnsEntry), &ok);
err = libp2p_crypto_verify (ipns_entry_data_for_sig(pb->IpnsEntry), pb->IpnsEntry->signature, &ok);
if (err || !ok) {
char buf[500];
snprintf(buf, sizeof(buf), Err[ErrInvalidSignatureFmt], pubkey);
@ -198,12 +198,12 @@ int ipfs_namesys_routing_resolve_once (char **path, char *name, int depth, char
return 0;
}
int ipfs_namesys_routing_check_EOL (struct stime *st, struct namesys_pb *pb)
int ipfs_namesys_routing_check_EOL (struct timespec *ts, struct namesys_pb *pb)
{
int err;
if (ipfs_namesys_pb_get_validity_type (pb->IpnsEntry) == IpnsEntry_EOL) {
err = ipfs_util_time_parse_RFC3339 (st, ipfs_namesys_pb_get_validity (pb->IpnsEntry));
if (*(pb->IpnsEntry->validityType) == IpnsEntry_EOL) {
err = ipfs_util_time_parse_RFC3339 (ts, pb->IpnsEntry->validity);
if (!err) {
return 1;
}

View file

@ -1,47 +1,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef __USE_XOPEN
#define __USE_XOPEN
#endif // __USE_XOPEN
#ifndef __USE_ISOC11
#define __USE_ISOC11
#endif // __USE_ISOC11
#include <time.h>
#include "ipfs/util/time.h"
int get_gmttime(struct stime *st) {
if (!st) {
return 1;
}
if (!timespec_get(&st->ts, TIME_UTC) ||
!time(&st->t)) {
return 2;
}
return 0;
}
int ipfs_util_time_parse_RFC3339 (struct stime *st, char *s)
int ipfs_util_time_parse_RFC3339 (struct timespec *ts, char *s)
{
char *r;
struct tm tm;
if (!st || !s || strlen(s) != 35) {
if (!ts || !s || strlen(s) != 35) {
return 1;
}
r = strptime (s, "%Y-%m-%dT%H:%M:%S", &tm);
if (!r || *r != '.') {
return 2;
}
st->t = mktime(&tm);
st->ts.tv_nsec = atoll(++r);
ts->tv_sec = mktime(&tm);
ts->tv_nsec = atoll(++r);
return 0;
}
char *ipfs_util_time_format_RFC3339 (struct stime *st)
char *ipfs_util_time_format_RFC3339 (struct timespec *ts)
{
char buf[31], *ret;
@ -50,8 +29,8 @@ char *ipfs_util_time_format_RFC3339 (struct stime *st)
return NULL;
}
if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S.%%09dZ00:00", gmtime(&st->t)) != sizeof(buf)-1 ||
snprintf(ret, 36, buf, st->ts.tv_nsec) != 35) {
if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S.%%09dZ00:00", gmtime(&(ts->tv_sec))) != sizeof(buf)-1 ||
snprintf(ret, 36, buf, ts->tv_nsec) != 35) {
free (ret);
return NULL;
}