In [9]:
from pylab import *
from numpy import *
from scipy import *
import netdb, os, operator, traceback
import GeoIP
from GeoIP import GEOIP_CHARSET_UTF8 as STANDARD
import logging

class Analyze:

    _log = logging.getLogger('Stats')
    
    def __init__(self, directory, geoip_file):
        self.netdb_dir = directory
        self.geo = GeoIP.open(geoip_file, STANDARD)
    
    def analyze(self, hook):
        
        def _hook_func(e):
            try:
                hook(e,self.geo)
            except:
                traceback.print_exc()
        
        self.info('start analysis')
        netdb.inspect(netdb_dir = self.netdb_dir, hook = _hook_func)
        self.info('ended analysis')
    
    def info(self, msg):
        self._log.info(msg)
        
class GEO:
    
    def __init__(self):
        self.countries = dict()
        self.codes = dict()

    def _get_addr(self, entry):
        if 'addrs' in entry:
            for e in entry['addrs']:
                if 'options' in e:
                    o = e['options']
                    if 'host' in o:
                        return o['host']
        
    def _get_ccode(self, entry, geo):
        addr = self._get_addr(entry)
        if addr:
            rec = geo.record_by_addr(addr)
            if rec:
                return rec['country_name']
    
    def hook(self, entry, geo):
        ccode = self._get_ccode(entry, geo)
        if ccode not in self.countries:
            self.countries[ccode] = 0
        self.countries[ccode] += 1
        
        
        
class Bandwidth:
    
    caps = [
        ('O' , 256 * 1024), # 256KB/s
        ('N' , 128 * 1024), # 128KB/s
        ('M' , 64 * 1024),  # 64KB/s
        ('L' , 32 * 1024),  # 32KB/s
        ('K' , 12 * 1024),  # 16KB/s
        ]
    
    
    def __init__(self):
        self.bw = 0 # bytes per second
        self.routers = 0
        
    def _bw_for_caps(self, caps):
        for cap, amount in self.caps:
            if cap in caps:
                return amount 
        
    def hook(self, entry, geo):
        if 'options' in entry:
            caps = entry['options']['caps']
            self.bw += self._bw_for_caps(caps)
            self.routers += 1


def main(netdb_dir=None, geoip_db=None):
    logging.basicConfig(level=logging.INFO)
    
    home = os.environ['HOME']
    
    if netdb_dir is None:
        netdb_dir = os.path.join(home,'.i2p','netDb')
        
    if geoip_db is None:
        geoip_db =  os.path.join(home, 'GeoLiteCity.dat')
        
    a = Analyze(netdb_dir, geoip_db)
    bw = Bandwidth()
    geo = GEO()
    a.analyze(bw.hook)
    a.analyze(geo.hook)
    make_pie_chart(a.geo, bw.routers, geo.countries)
    #print 'Estimated min bandwidth %.4f Gbps' % ( bw.bw / 1024. / 1024. / 1024. * 8 ) 
    #print 'There are %d routers' % bw.routers
   
    
def make_pie_chart(geo, total, dictionary):
    keys, vals = ['Other'], [0]
    routers = [0]
    total = float(total)
    v = 255
    items = dictionary.items()
    items = sorted(items,key=operator.itemgetter(1))
    for k,val in items:
        if val < 50:
            vals[0] += val
            routers[0] += val
        elif k is not None:
            routers.append('%.2f %% (%d)' % ( val / total * 100, val) )
            vals.append(val)
            keys.append(k)
    val = vals[0]
    routers[0] = '%.2f %% (%d)' % ( val / total * 100, val) 
    fig = pyplot.figure()
    pylab.pie(vals, labels=routers)
    pylab.legend(keys,bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    fig.set_figheight(6)
    fig.set_figwidth(6)
    pylab.title('i2p netdb demographics')
            

    
main()



In [7]:


In [ ]: