summaryrefslogtreecommitdiff
path: root/helld.py
diff options
context:
space:
mode:
authordzwdz2024-02-22 22:22:54 +0100
committerdzwdz2024-02-22 22:22:54 +0100
commit7a767e3c540b2fdaf227002b5010c3106b5b97f5 (patch)
treed1ec0931e9c04c6d33f2fd0a16d09427e48ba40e /helld.py
parentc88059af91bb201b5d27e3cbf3166d8840c3f376 (diff)
limit redirects, filesize
Diffstat (limited to 'helld.py')
-rw-r--r--helld.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/helld.py b/helld.py
new file mode 100644
index 0000000..68d24ac
--- /dev/null
+++ b/helld.py
@@ -0,0 +1,93 @@
+# Hellish Gemini daemon, in both behaviour and code quality.
+#
+# openssl req -newkey rsa:4096 -nodes -keyout key.pem -nodes -x509 -out cert.pem
+# python3 helld.py cert.pem key.pem
+
+import socket
+import threading
+import socketserver
+import ssl
+import sys
+import time
+import random
+from urllib.parse import urlparse
+
+handlers = []
+
+def register(addr):
+ def dec(fn):
+ handlers.append((addr, fn))
+ return dec
+
+@register('/normal')
+def normal(s, _):
+ s.sendall(b'20 text/gemini\r\n# hello\nnothing strange going on here\n')
+
+@register('/noclose')
+def noclose(s, rh):
+ s.sendall(b'20 text/gemini\r\nquick before the connection is killed i need to tell you tha')
+ close(rh.request)
+
+@register('/sleep1')
+def sleep1(s, rh):
+ s.sendall(b'20 text/gemini\r\nabout to take a nap')
+ time.sleep(120)
+
+@register('/sleep2')
+def sleep(s, rh):
+ time.sleep(120)
+ s.sendall(b'20 text/gemini\r\ntook a nap')
+
+@register('/128mb')
+def lotsofdata(s, rh):
+ s.sendall(b'20 text/gemini\r\n')
+ for n in range(128):
+ s.sendall(b'lol ' * (1024 * 1024 // 4))
+
+@register('/4mb')
+def sensibleamountofdata(s, rh):
+ buffer = b'20 text/gemini\r\n' + b'lol ' * (1024 * 1024)
+ buffer = buffer[:4*1024*1024]
+ s.sendall(buffer)
+
+@register('/over4mb')
+def nonsensibleamountofdata(s, rh):
+ buffer = b'20 text/gemini\r\n' + b'lol ' * (1024 * 1024)
+ buffer = buffer[:4*1024*1024+1]
+ s.sendall(buffer)
+
+@register('/loop')
+def loop(s, rh):
+ s.sendall(f'30 /loop/{random.randint(0, 2**32)}\r\n'.encode('utf-8'))
+
+@register('/index')
+def index(s, rh):
+ s.sendall(b'20 text/gemini\r\n')
+ for addr, _ in handlers:
+ s.sendall(f'=> {addr}\n'.encode('utf-8'))
+
+@register('')
+def toindex(s, rh):
+ s.sendall(b'30 /index\r\n')
+
+class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
+ def handle(self):
+ s = context.wrap_socket(self.request, server_side=True)
+ req = s.read().decode('utf-8').rstrip('\r\n')
+ print(req)
+ req = urlparse(req)
+ for addr, fn in handlers:
+ if req.path.startswith(addr):
+ fn(s, self)
+ break
+
+class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
+ pass
+
+if __name__ == "__main__":
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
+ context.load_cert_chain(sys.argv[1], sys.argv[2])
+
+ ThreadedTCPServer.allow_reuse_address = True
+ server = ThreadedTCPServer(('0.0.0.0', 1965), ThreadedTCPRequestHandler)
+ server.serve_forever()