summaryrefslogtreecommitdiff
path: root/generate_tox_bootstrap.py
blob: cb8c804cd6f7d4795bac5f1a712e30ede607fccf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/python
# pip install jinja2 requests

import datetime
import jinja2
import json
import requests
import socket

json_url = 'https://nodes.tox.chat/json'

tox_bootstrap_template = """
/*
 * Generated with generate_tox_bootstrap.py by GDR!
 * from {{ json_url }} on {{ now }}
 */
struct bootstrap_node {
    char *address;
    uint16_t port;
    uint8_t key[32];
} bootstrap_nodes[] = {
{% for node in nodes %}
    {
        "{{ node.ipv4 }}",
        {{ node.port }},
        {
            {{ node.public_key|toxtoc }}
        }
    },
{% endfor %}
    {
        "176.31.28.63",
        465,
        {
            0x0B, 0x6C, 0x7A, 0x93, 0xA6, 0xD8, 0xC0, 0xEB, 0x44, 0x96, 0x5C, 0x4A, 0x85, 0xCB, 0x88, 0xBA, 
            0x75, 0x71, 0x17, 0x0F, 0xE2, 0xDB, 0x3D, 0xEA, 0x10, 0x71, 0x3E, 0x48, 0x55, 0x9A, 0x55, 0x4D
        }
    },
};
"""

def toxtoc(value):
    """
    A Jinja2 filter to turn a ToxID into two lines of C bytes
    """
    def get_16_bytes(value):
        """
        Generate 1 line of C code - 16 bytes
        @param value a hex string of length 32 (32 hex chars)
        """
        if len(value) <> 32:
            raise ValueError('%r is not a 32-char string')

        rv = ""

        for i in range(16):
            rv += "0x%s" % value[2*i : 2*i+2]
            if i < 15:
                rv += ", "

        return rv

    rv = get_16_bytes(value[:32]) + \
         ",\n" + (12*' ') + \
         get_16_bytes(value[32:])

    return rv

class Loader(jinja2.BaseLoader):
    def get_source(self, environment, template):
        return tox_bootstrap_template, 'tox_bootstrap_template', True

if __name__ == "__main__":
    r = requests.get(json_url)
    data = r.json()
    if 'nodes' not in data:
        raise ValueError('nodes element not in JSON')

    nodes = []
    for elem in data['nodes']:
        node = {}
        if 'ipv4' not in elem or 'port' not in elem or 'public_key' not in elem:
            print "SKIPPING", elem
            continue
        
        if len(elem['public_key']) <> 64:
            print "Bad public key %s, skipping!" % elem['public_key']
            continue

        node['port'] = int(elem['port'])
        node['public_key'] = elem['public_key']

        try:
            socket.inet_aton(elem['ipv4'])
            node['ipv4'] = elem['ipv4']
        except socket.error:
            # IPv4 is not numeric, let's try resolving
            try:
                print "RESOLVING", elem['ipv4']
                node['ipv4'] = socket.gethostbyname(elem['ipv4'])
            except socket.error:
                print "Could not resolve ipv4: %s, skipping!" % elem['ipv4']
                continue

        nodes.append(node)

    env = jinja2.Environment(loader=Loader())
    env.filters['toxtoc'] = toxtoc
    template = env.get_template('tox_bootstrap_template')
    tox_bootstrap_h = template.render(nodes=nodes, now=datetime.datetime.now(), json_url=json_url)
    open('tox_bootstrap.h', 'w').write(tox_bootstrap_h)