(module problem01 () (import scheme) (import (chicken base)) (import (chicken condition)) (import (chicken format)) (import (chicken io)) (import (chicken process signal)) (import (chicken time)) (import (srfi 1)) (import (srfi 18)) (import medea) (import socket) (define stderr (current-error-port)) (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 backlog 10) (socket-receive-timeout #f) (define listener (socket af/inet sock/stream)) (set! (so-reuse-address? listener) #t) (socket-bind listener (inet-address host port)) (socket-listen listener backlog) (define (parse-request line) (and-let* ((json (read-json line)) (method (alist-ref 'method json)) (_ (equal? method "isPrime")) (number (alist-ref 'number json)) (_ (number? number))) number)) (define (mutilate n) (inexact->exact (truncate n))) (define (prime? n) (cond ((< n 2) #f) ((or (= n 2) (= n 3)) #t) ((even? n) #f) (else (let ((limit (mutilate (sqrt n)))) (let loop ((x 3)) (cond ((zero? (modulo n x)) #f) ((> x limit) #t) (else (loop (+ x 2))))))))) (define (send-json-response out alist) (let ((response (json->string alist))) (elog "Sent JSON line: ~s\n" response) (write-line response out))) (define (handle-client conn-socket) (elog "Incoming connection (~s)\n" conn-socket) (receive (in out) (socket-i/o-ports conn-socket) (let loop () (let ((line (read-line in))) (if (eof-object? line) (begin (close-input-port in) (close-output-port out)) (begin (elog "Received JSON line: ~s\n" line) (let ((arg (parse-request line))) (elog "Extracted arg ~s\n" arg) (if arg (let ((json `((method . "isPrime") (prime . ,(prime? (mutilate arg)))))) (send-json-response out json) (loop)) (let ((json '((error . "malformed")))) (send-json-response out json) (close-input-port in) (close-output-port out)))))))))) (let loop () (let ((conn-socket (socket-accept listener))) (thread-start! (make-thread (lambda () (handle-client conn-socket)))) (loop))) (set-signal-handler! signal/int (lambda (_) (socket-close listener) (exit 0))) )