-
Notifications
You must be signed in to change notification settings - Fork 0
/
teleportdirectoryserver.py
144 lines (129 loc) · 5.84 KB
/
teleportdirectoryserver.py
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import http.server
from urllib.parse import parse_qs
from datetime import datetime, timedelta
from calendar import timegm
import time
import threading
#a relatively small amount at first, because theres no antispam
#then later we'll increase it a lot to reduce the frequency at
#which people need to hit the server
#once fidelity bonds get in we can perhaps use the locktimes of them
#or since the locktime will be several months, maybe x10 less
#e.g. locktime is 24 months, set expiry to be 2.4 months
TIME_TO_LIVE_DAYS = 1
ERROR_TEXT = "Something went wrong"
NETWORKS = ["main", "test", "signet"]
allowed_txt_files = ["/makers-" + n + ".txt" for n in NETWORKS]
allowed_pages = allowed_txt_files + ["/received", "/submitmaker.html"]
file_lock = threading.Lock()
class TeleportDirectoryServerHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path in allowed_pages:
response_code = 200
if self.path == "/received":
page = "<html><h1>Received your submission. Directory will update shortly.</h1>" \
+ "Expiry unix time = <b>" + str(self.expiry_unixtime) + "</b></html>"
else:
return super().do_GET()
else:
response_code = 404
page = "<html><h1>" + ERROR_TEXT + "</h1></html>"
self.send_response(response_code)
self.send_header('Content-Type', 'text/html')
self.send_header('Content-Length', len(page))
self.end_headers()
self.wfile.write(page.encode('utf-8'))
def do_POST(self):
self.expiry_unixtime = 0
if self.path != "/directoryserver" or "Content-Length" not in self.headers:
self.path = "error"
return self.do_GET()
try:
int(self.headers["Content-Length"])
except:
self.path = "error"
return self.do_GET()
if int(self.headers["Content-Length"]) > 200: #arbitrary max length
self.path = "error"
return self.do_GET()
body = self.rfile.read(int(self.headers["Content-Length"]))
post_data = parse_qs(body.decode())
#post_data = {'address': ['myhiddenservice.onion:6102'], 'net': ['test']}
address = None
net = None
try:
address = post_data["address"][0].replace(",", "")
net = post_data["net"][0]
except:
self.path = "error"
return self.do_GET()
expiry_datetime = datetime.now() + timedelta(days=TIME_TO_LIVE_DAYS)
self.expiry_unixtime = timegm(expiry_datetime.timetuple())
filename = "makers-" + net + ".txt"
with file_lock:
refreshed_entry = False
entries = []
try:
with open(filename, "r") as fd:
filedata = fd.read()
for file_entry in filedata.split("\n"):
if file_entry.find(",") == -1:
continue
file_address = file_entry.split(",")[1]
if address == file_address:
refreshed_entry = True
entries.append(str(self.expiry_unixtime) + "," + address)
print("[" + datetime.now().strftime("%Y-%m-%d %X")
+ "] maker refreshed: " + address + " expiry="
+ expiry_datetime.strftime("%Y-%m-%d %X"))
else:
entries.append(file_entry)
except FileNotFoundError:
pass
if refreshed_entry:
with open(filename, "w") as fd:
fd.write("\n".join(entries) + "\n")
else:
with open(filename, "a") as fd:
fd.write(str(self.expiry_unixtime) + "," + address + "\n")
print("[" + datetime.now().strftime("%Y-%m-%d %X")
+ "] maker added: " + address + " expiry="
+ expiry_datetime.strftime("%Y-%m-%d %X"))
self.path = "/received"
return self.do_GET()
class ExpiryThread(threading.Thread):
def run(self):
filenames = ["makers-" + net + ".txt" for net in NETWORKS]
while True:
time.sleep(60 * 30)
with file_lock:
for filename in filenames:
at_least_one_expiry = False
remaining_entries = []
try:
with open(filename, "r") as fd:
filedata = fd.read()
for file_entry in filedata.split("\n"):
if file_entry.find(",") == -1:
continue
expiry_unixtime = int(file_entry.split(",")[0])
expiry_datetime = (datetime.utcfromtimestamp(0) +
timedelta(seconds=expiry_unixtime))
if datetime.now() > expiry_datetime:
print("[" + datetime.now().strftime("%Y-%m-%d %X")
+ "] maker expired: " + str(file_entry))
at_least_one_expiry = True
else:
remaining_entries.append(file_entry)
except FileNotFoundError:
continue
if at_least_one_expiry:
with open(filename, "w") as fd:
fd.write("\n".join(remaining_entries) + "\n")
expiry_thread = ExpiryThread()
expiry_thread.daemon = True
expiry_thread.start()
hostport = ("localhost", 8080)
httpd = http.server.HTTPServer(hostport, TeleportDirectoryServerHandler)
print("serving forever on " + str(hostport))
httpd.serve_forever()