#
Gemini Capsule on Pico W
I received my Pico W long time ago but couldn't find the time to finish this.
I decided to do this in Python (using MicroPython) first, then translate to C and see how things can be improved.
It's very simple and very basic, without concurrency. Like my ESP32 setup, it uses Duck DNS. The key and the certificate are at /pyboard/{key,cert}.der and this is /pyboard/boot.py:
```
import ussl
```
import socket
```
import network
```
import _thread
```
import machine
```
import urequests
```
```
SSID = 'AAA'
```
PASSPHRASE = 'BBB'
```
DOMAINS = 'CCC'
```
TOKEN = 'DDD'
```
PORT = 1965
```
```
keyfile = open("key.der", "rb").read()
```
certfile = open("cert.der", "rb").read()
```
```
def read_request(sc):
```
buf = sc.read(len('gemini://a'))
```
while not buf.endswith(b'\r') and len(buf) < 64:
```
b = sc.read(1)
```
buf += b
```
if not buf.endswith(b'\r'):
```
raise Exception('Truncated request')
```
```
url = buf[:-1].decode('utf-8')
```
_, _, _, path = url.split("/", 3)
```
path = path.lstrip('/')
```
print(url)
```
```
if len(path) == 0 or path == '/':
```
path = 'index.gmi'
```
elif path == 'key.der' or path == 'cert.der' or path == 'main.py':
```
sc.write(f'40 Forbidden\r\n')
```
raise Exception(f"Forbidden path: {path}")
```
```
return path
```
```
def handle_request(c):
```
try:
```
sc = ussl.wrap_socket(c, server_side=True, key=keyfile, cert=certfile)
```
try:
```
path = read_request(sc)
```
```
sc.write(f'20 text/gemini\r\n')
```
```
with open(path, "rb") as f:
```
while True:
```
chunk = f.read(128)
```
if len(chunk) == 0:
```
break
```
sc.write(chunk)
```
finally:
```
sc.close()
```
finally:
```
c.close()
```
```
wlan = network.WLAN(network.STA_IF)
```
wlan.active(True)
```
wlan.connect(SSID, PASSPHRASE)
```
```
s = socket.socket()
```
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
```
s.bind(('0.0.0.0', PORT))
```
s.listen(1)
```
led = machine.Pin('LED', machine.Pin.OUT)
```
```
print(f"Local address: {wlan.ifconfig()[0]}")
```
print('Updating public address')
```
urequests.get(f"https://www.duckdns.org/update?domains={DOMAINS}&token={TOKEN}")
```
```
print('Ready')
```
while True:
```
try:
```
print('Waiting for request')
```
c, _ = s.accept()
```
except Exception as e:
```
print(e)
```
continue
```
```
try:
```
print('Handling request')
```
c.settimeout(10)
```
led.value(1)
```
try:
```
handle_request(c)
```
finally:
```
led.value(0)
```
except Exception as e:
```
print(e)
```
c.close()
It doesn't send close_notify, something I could fix in my ESP32 Gemini server written in C by forcing mbedtls_ssl_close_notify((mbedtls_ssl_context*)tls), although all other uses of mbedlts are wrapped nicely with the ESP-TLS API. I hope I can do something similar in the Pico without having to patch ussl and rebuild MicroPython.
=>Duck DNS