<commit_before>var crypto = require('crypto');
var e3x = require('e3x');
var hashname = require('hashname');
var base32 = hashname.base32;
var lob = require('lob-enc');
var stringify = require('json-stable-stringify');

var Pipe = exports.Pipe = require('./pipe').Pipe;

// activity/debugging logging utilities
var log = {
  error:function(){console.error.apply(console,arguments);},
  warn:function(){console.warn.apply(console,arguments);},
  debug:function(){},
  info:function(){console.log.apply(console,arguments);}
}
// override/set any logging level
exports.log = function(args)
{
  if(typeof args == 'object') Object.keys(args).forEach(function(type){
    log[type] = args[type];
  });
  return log;
}

// keep track of all default extensions
exports.extensions = [];
exports.add = function(ext)
{
  log.debug('adding extension',ext&&ext.name);
  if(!ext || typeof ext.name != 'string') return false;
  exports.extensions[ext.name] = ext;
  return true;
}

// add the default extensions
exports.add(require('../ext/peer'));
exports.add(require('../ext/path'));
exports.add(require('../ext/stream'));

// generate new local id
exports.generate = function(cb)
{
  log.debug('generating secrets');
  e3x.generate(function(err,pairs){
    if(err)
    {
      log.debug('e3x gen failed',err);
      return cb(err);
    }
    var id = {keys:{},secrets:{}};
    Object.keys(pairs).forEach(function(csid){
      id.keys[csid] = base32.encode(pairs[csid].key);
      id.secrets[csid] = base32.encode(pairs[csid].secret);
    });
    id.hashname = hashname.fromKeys(id.keys);
    log.info('generated new id',id.hashname);
    cb(undefined,id);
  });
}

exports.mesh = function(args, cbMesh)
{
  if(typeof cbMesh != 'function') cbMesh = function(err, mesh){ if(err) log.error(err); return mesh; }; // stub for sync usage
  if(typeof args != 'object' || typeof args.id != 'object') return cbMesh('invalid args, requires id');
  var hn = hashname.fromKeys(args.id.keys);
  if(!hn) return cbMesh('invalid keys');

  // convert all id keys/secrets to pairs for e3x
  var opts = {pairs:{}};
  Object.keys(args.id.keys).forEach(function(csid){
    var pair = opts.pairs[csid] = {};
    // flexible buffer or base32 input
    pair.key = Buffer.isBuffer(args.id.keys[csid]) ? args.id.keys[csid] : base32.decode(args.id.keys[csid]);
    pair.secret = Buffer.isBuffer(args.id.secrets[csid]) ? args.id.secrets[csid] : base32.decode(args.id.secrets[csid]);
  });
  opts.debug = log.debug;
  var self = e3x.self(opts);
  if(!self) return cbMesh(e3x.err);
  log.debug('created new mesh',hn);
  
  // bundle stuff inside for extensions to use
  var mesh = {self:self, lib:exports, log:log};

  // keep args handy but dereference id/secret
  mesh.args = args;
  mesh.keys = args.id.keys;
  delete args.id;
  mesh.hashname = hn;
  
  // a json representation of the current mesh
  mesh.json_store = {};
  
  // internal util to manage .json_store
  mesh.jsonize = function(hn, args)
  {
    // add/get json store
    var json = mesh.json_store[hn];
    if(!json) json = mesh.json_store[hn] = {hashname:hn,paths:[],keys:{}};

    if(args.keys) json.keys = args.keys;

    // only know a single csid/key
    if(args.csid && args.key)
    {
      json.keys[args.csid] = args.key;
    }
    
    // make sure no buffers
    Object.keys(json.keys).forEach(function(csid){
      if(Buffer.isBuffer(json.keys[csid])) json.keys[csid] = base32.encode(json.keys[csid]);
    });
    
    return json;
  }
  
  // load our own json id
  mesh.jsonize(mesh.hashname, {keys:mesh.keys});<commit_msg>all public network addresses of a mesh are shared and settable<commit_after>var crypto = require('crypto');
var e3x = require('e3x');
var hashname = require('hashname');
var base32 = hashname.base32;
var lob = require('lob-enc');
var stringify = require('json-stable-stringify');

var Pipe = exports.Pipe = require('./pipe').Pipe;

// activity/debugging logging utilities
var log = {
  error:function(){console.error.apply(console,arguments);},
  warn:function(){console.warn.apply(console,arguments);},
  debug:function(){},
  info:function(){console.log.apply(console,arguments);}
}
// override/set any logging level
exports.log = function(args)
{
  if(typeof args == 'object') Object.keys(args).forEach(function(type){
    log[type] = args[type];
  });
  return log;
}

// keep track of all default extensions
exports.extensions = [];
exports.add = function(ext)
{
  log.debug('adding extension',ext&&ext.name);
  if(!ext || typeof ext.name != 'string') return false;
  exports.extensions[ext.name] = ext;
  return true;
}

// add the default extensions
exports.add(require('../ext/peer'));
exports.add(require('../ext/path'));
exports.add(require('../ext/stream'));

// generate new local id
exports.generate = function(cb)
{
  log.debug('generating secrets');
  e3x.generate(function(err,pairs){
    if(err)
    {
      log.debug('e3x gen failed',err);
      return cb(err);
    }
    var id = {keys:{},secrets:{}};
    Object.keys(pairs).forEach(function(csid){
      id.keys[csid] = base32.encode(pairs[csid].key);
      id.secrets[csid] = base32.encode(pairs[csid].secret);
    });
    id.hashname = hashname.fromKeys(id.keys);
    log.info('generated new id',id.hashname);
    cb(undefined,id);
  });
}

exports.mesh = function(args, cbMesh)
{
  if(typeof cbMesh != 'function') cbMesh = function(err, mesh){ if(err) log.error(err); return mesh; }; // stub for sync usage
  if(typeof args != 'object' || typeof args.id != 'object') return cbMesh('invalid args, requires id');
  var hn = hashname.fromKeys(args.id.keys);
  if(!hn) return cbMesh('invalid keys');

  // convert all id keys/secrets to pairs for e3x
  var opts = {pairs:{}};
  Object.keys(args.id.keys).forEach(function(csid){
    var pair = opts.pairs[csid] = {};
    // flexible buffer or base32 input
    pair.key = Buffer.isBuffer(args.id.keys[csid]) ? args.id.keys[csid] : base32.decode(args.id.keys[csid]);
    pair.secret = Buffer.isBuffer(args.id.secrets[csid]) ? args.id.secrets[csid] : base32.decode(args.id.secrets[csid]);
  });
  opts.debug = log.debug;
  var self = e3x.self(opts);
  if(!self) return cbMesh(e3x.err);
  log.debug('created new mesh',hn);
  
  // bundle stuff inside for extensions to use
  var mesh = {self:self, lib:exports, log:log};

  // keep args handy but dereference id/secret
  mesh.args = args;
  mesh.keys = args.id.keys;
  delete args.id;
  mesh.hashname = hn;
  
  // track any current public addresses per-mesh
  mesh.public = {};
  if(args.ipv4) mesh.public.ipv4 = args.ipv4;
  if(args.ipv6) mesh.public.ipv6 = args.ipv6;
  
  // a json representation of the current mesh
  mesh.json_store = {};
  
  // internal util to manage .json_store
  mesh.jsonize = function(hn, args)
  {
    // add/get json store
    var json = mesh.json_store[hn];
    if(!json) json = mesh.json_store[hn] = {hashname:hn,paths:[],keys:{}};

    if(args.keys) json.keys = args.keys;

    // only know a single csid/key
    if(args.csid && args.key)
    {
      json.keys[args.csid] = args.key;
    }
    
    // make sure no buffers
    Object.keys(json.keys).forEach(function(csid){
      if(Buffer.isBuffer(json.keys[csid])) json.keys[csid] = base32.encode(json.keys[csid]);
    });
    
    return json;
  }
  
  // load our own json id
  mesh.jsonize(mesh.hashname, {keys:mesh.keys});
{'fraction_non_alphanumeric': 0.17109385642283068, 'fraction_numerical': 0.007083503609862416, 'mean_word_length': 3.664548919949174, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1715722', 'n_tokens_mistral': 2562, 'n_tokens_neox': 2529, 'n_words': 536}