You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
2.7 KiB
C

#include "peer.h"
#include "json/json.h"
#include "json/layout.h"
#include "ffdb/trie.h"
#include "ffdb/fs_list.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#define PEERS_BY_DOMAIN "data/peers/by_domain"
#define OBJ_TYPE struct peer
static struct json_object_field peer_layout[] = {
JSON_FIELD_STRING( domain, true ),
JSON_FIELD_STRING( tor_hidden_service, false ),
JSON_FIELD_DATETIME( last_successful_delivery, false ),
JSON_FIELD_DATETIME( last_failed_delivery, false ),
JSON_FIELD_DATETIME( last_hidden_service_delivery, false ),
JSON_FIELD_DATETIME( last_tor_delivery, false ),
JSON_FIELD_BOOL( admin_disable_outbox, false ),
JSON_FIELD_BOOL( admin_disable_tor, false ),
JSON_FIELD_END,
};
#undef OBJ_TYPE
void peer_model_init()
{
mkdir( "data", 0755 );
mkdir( "data/peers", 0755 );
}
struct peer* peer_new()
{
struct peer* p;
p = malloc(sizeof(*p));
memset(p,0,sizeof(*p));
return p;
}
struct peer* peer_from_id( int id )
{
if( id == 0 ) { return NULL; }
struct peer* p = peer_new();
char filename[512];
snprintf( filename,sizeof(filename), "data/peers/%d.json", id );
if( !json_read_object_layout_from_file( filename, peer_layout, p ) ) {
peer_free(p);
return NULL;
}
p->id = id;
return p;
}
struct peer* peer_from_domain( const char* domain )
{
struct peer* res = NULL;
for( const char* p = domain; *p; ++p ) {
if( !isprint(*p) ) {
return NULL;
}
}
char* id_str = ffdb_trie_get( PEERS_BY_DOMAIN, domain );
if( !id_str ) { return NULL; }
int id = 0;
if( sscanf( id_str, "%d", &id ) ) {
res = peer_from_id(id);
}
free(id_str);
// Make sure the index is still valid
if( 0 == strcmp(res->domain,domain) ) {
return res;
}
if( 0 == strcmp(res->tor_hidden_service,domain) ) {
return res;
}
// Nope. Index entry is invalid, clear
ffdb_trie_set( PEERS_BY_DOMAIN, domain, NULL );
peer_free(res);
return NULL;
}
void peer_save( struct peer* p )
{
char filename[512];
if( !p->id ) {
p->id = fs_list_inc( "data/peers/HEAD" );
}
snprintf( filename,sizeof(filename), "data/peers/%d.json", p->id );
json_write_object_layout_to_file( filename, "\t", peer_layout, p );
char id_str[32];
snprintf( id_str,sizeof(id_str), "%d", p->id );
if( p->domain ) {
ffdb_trie_set( PEERS_BY_DOMAIN, p->domain, id_str );
}
if( p->tor_hidden_service ) {
ffdb_trie_set( PEERS_BY_DOMAIN, p->tor_hidden_service, id_str );
}
}
struct peer* peer_create_from_domain( const char* domain )
{
struct peer* p = peer_from_domain(domain);
if( p ) { return p; }
p = peer_new();
p->domain = strdup(domain);
peer_save(p);
return p;
}
void peer_free( struct peer* p )
{
if( !p ) { return; }
free( p->domain );
free( p->tor_hidden_service );
free(p);
}