(module problem04 () (import scheme) (import (chicken base)) (import (chicken format)) (import (chicken port)) (import (chicken process signal)) (import (chicken string)) (import (chicken time)) (import (srfi 18)) (import (srfi 69)) (import socket) (define stderr (current-error-port)) (set-buffering-mode! stderr #:line) (define str string-append) (define (elog fmt #!rest args) (apply fprintf stderr (str "[~s] " fmt) (current-process-milliseconds) args)) (define host "0.0.0.0") (define port 10000) (define max-packet-size 1000) (socket-receive-timeout #f) (define listener (socket af/inet sock/dgram)) (socket-bind listener (inet-address host port)) (define kvstore (make-hash-table)) (define (parse-request data) (let ((i (substring-index "=" data))) (if i (let ((key (substring data 0 i)) (value (substring data (add1 i)))) (cons key value)) data))) (define (handle-client saddr data) (elog "Received data (~s): ~s\n" saddr data) (let ((parsed (parse-request data))) (if (string? parsed) (let* ((key parsed) (value (if (equal? key "version") "UDP 1.0" (hash-table-ref/default kvstore key "")))) (elog "GET ~s -> ~s (~s)\n" key value (socket-send-to listener (format "~a=~a" key value) saddr))) (let ((key (car parsed)) (value (cdr parsed))) (elog "SET ~s <- ~s\n" key value) (when (not (equal? key "version")) (hash-table-set! kvstore key value)))))) (let loop () (receive (data saddr) (socket-receive-from listener max-packet-size) (thread-start! (make-thread (lambda () (handle-client saddr data)))) (loop))) (set-signal-handler! signal/int (lambda (_) (socket-close listener) (exit 0))) )