github.com/annchain/OG@v0.0.9/scripts/boostrap_server/run.py (about) 1 import os 2 import threading 3 import time 4 5 from http.server import BaseHTTPRequestHandler, HTTPServer 6 import json 7 import cgi 8 from urllib.parse import parse_qs 9 10 ttl = 60 * 2 11 PARTNERS = 2 12 13 # req: 14 # {"networkid": 1, "publickey":"0x01000000000", "partners": 4, "onode": "onode://d2469187c351fad31b84f4afb2939cb19c03b7c9359f07447aea3a85664cd33d39afc0c531ad4a8e9ff5ed76b58216e19b0ba208b45d5017ca40c9bd351d29ee@47.100.222.11:8001"} 15 16 # resp: 17 # {"status":"wait/ok/error", 18 # "bootstrap_node": true, 19 # "bootstrap_nodes": "onode://d2469187c351fad31b84f4afb2939cb19c03b7c9359f07447aea3a85664cd33d39afc0c531ad4a8e9ff5ed76b58216e19b0ba208b45d5017ca40c9bd351d29ee@47.100.222.11:8001", 20 # "genesis_pk": "genesis_pk"} 21 networks = {} 22 23 24 def handle(req, sourceip, requirePartners): 25 network_id = req['networkid'] 26 publickey = req['publickey'] 27 # partners = req['partners'] 28 onode: str = req['onode'] 29 # modify onode's ip to source ip 30 origin_host = onode[onode.index("@") + 1:onode.index(":", 10)] 31 if origin_host == '127.0.0.1': 32 onode = onode[0: onode.index("@") + 1] + sourceip + onode[onode.index(":", 10):] 33 print('replaced %s to %s' % (origin_host, sourceip)) 34 req['onode'] = onode 35 36 if network_id not in networks: 37 networks[network_id] = { 38 'time': time.time(), 39 'require': requirePartners, 40 'peers': {} 41 } 42 else: 43 if networks[network_id]['require'] != requirePartners: 44 msg = {'status': 'error', 45 'message': 'someone else specified required partners as %d, earlier than your %d' % ( 46 networks[network_id]['require'], requirePartners)} 47 print(msg) 48 return msg 49 50 d = networks[network_id] 51 52 if publickey not in d['peers']: 53 req['id'] = len(d['peers']) 54 d['peers'][publickey] = req 55 56 if len(d['peers']) != d['require']: 57 msg = {'status': 'wait', 58 'message': '%d of %d is registered... waiting for more' % (len(d['peers']), d['require'])} 59 print(msg) 60 return msg 61 items = d['peers'].values() 62 msg = {'status': 'ok', 63 'bootstrap_node': d['peers'][publickey]['id'] == 0, 64 'bootstrap_nodes': ';'.join([x['onode'] for x in items]), 65 'genesis_pk': ';'.join([x['publickey'] for x in items]), 66 'partners': len(d['peers']) 67 } 68 print(msg) 69 return msg 70 71 72 class Server(BaseHTTPRequestHandler): 73 def __init__(self, *args, directory=None, **kwargs): 74 self.lock = threading.Lock() 75 t = threading.Thread(target=self.wipe) 76 t.daemon = True 77 t.start() 78 79 if directory is None: 80 directory = os.getcwd() 81 self.directory = directory 82 super().__init__(*args, **kwargs) 83 84 def _set_headers(self, length): 85 self.send_response(200) 86 self.send_header('Content-type', 'application/json') 87 self.send_header('Content-Length', length) 88 self.end_headers() 89 90 def do_HEAD(self): 91 self._set_headers(0) 92 93 # GET sends back a Hello world message 94 def do_GET(self): 95 j = bytes(json.dumps(networks, indent=4), 'utf-8') 96 self._set_headers(len(j)) 97 self.wfile.write(j) 98 99 # POST echoes the message adding a JSON field 100 def do_POST(self): 101 ctype, pdict = cgi.parse_header(self.headers.get('content-type')) 102 103 # refuse to receive non-json content 104 if ctype != 'application/json': 105 self.send_response(400) 106 self.end_headers() 107 return 108 109 # read the message and convert it into a python dictionary 110 length = int(self.headers.get('content-length')) 111 message = json.loads(self.rfile.read(length)) 112 required = int(self.path[1:]) 113 114 self.lock.acquire() 115 try: 116 resp = handle(message, self.client_address[0], required) 117 finally: 118 self.lock.release() 119 120 # send the message back 121 j = bytes(json.dumps(resp), 'utf-8') 122 self._set_headers(len(j)) 123 self.wfile.write(j) 124 125 def wipe(self): 126 while True: 127 self.lock.acquire() 128 try: 129 to_remove = [] 130 for k, v in networks.items(): 131 if time.time() - v['time'] > ttl: 132 # remove it 133 to_remove.append(k) 134 135 for k in to_remove: 136 print('Removing network id', k) 137 del networks[k] 138 finally: 139 self.lock.release() 140 time.sleep(3) 141 142 143 def run(server_class=HTTPServer, handler_class=Server, port=8008): 144 server_address = ('0.0.0.0', port) 145 httpd = server_class(server_address, handler_class) 146 147 print('Starting httpd on port %d...' % port) 148 httpd.serve_forever() 149 150 151 if __name__ == "__main__": 152 from sys import argv 153 154 if len(argv) == 2: 155 run(port=int(argv[1])) 156 else: 157 run()