11 (define gopher-root "./gopher-root")
12 (define gopher-index-file-name "index")
13 (define gopher-server-hostname "localhost")
14 (define gopher-server-port 70)
17 (print "Gopher server listening on port " gopher-server-port " ...")
18 (let ((listener (tcp-listen gopher-server-port)))
20 (let-values (((in-port out-port) (tcp-accept listener)))
21 (let* ((line (read-line in-port))
22 (selector (string-trim-both line)))
23 (let-values (((local-ip remote-ip) (tcp-addresses in-port)))
24 (print "Accepted connection from " remote-ip
25 " on " (seconds->string)))
26 (with-output-to-port out-port
29 (if (= (string-length selector) 0)
33 gopher-server-hostname
35 (print "... served selector '" selector "'. Closing connection."))
36 (close-input-port in-port)
37 (close-output-port out-port))
39 (tcp-close listener)))
41 ;;; Selector retrieval
43 (define (serve-selector selector gopher-root server-host server-port)
44 (let ((type (with-input-from-string (substring selector 0 1) read))
45 (path (substring selector 1)))
47 ((0) (serve-text-file path server-host server-port))
48 ((1) (serve-index-file path server-host server-port))
49 ((9 g I) (serve-binary-file path server-host server-port))
50 (else (error "Unhandled file type:" type)))))
52 (define (serve-index-file path server-host server-port)
53 (let ((file-name (make-pathname (list gopher-root path) gopher-index-file-name)))
54 (if (regular-file? file-name)
55 (with-input-from-file file-name
61 (error "Index file not found."))))
63 (define (serve-text-file path server-host server-port)
64 (let ((file-name (make-pathname gopher-root path)))
65 (if (regular-file? file-name)
66 (with-input-from-file file-name
72 (error "File not found."))))
74 (define (serve-binary-file path server-host server-port)
75 (let ((file-name (make-pathname gopher-root path)))
76 (if (regular-file? file-name)
77 (with-input-from-file file-name
79 (let loop ((b (read-byte)))
84 (loop (read-byte)))))))))
85 (print "File not found."))
89 (define entry-type car)
91 (define entry-name cadr)
93 (define (has-selector? entry) (>= (length entry) 3))
95 (define (entry-selector entry) (list-ref entry 2))
97 (define (has-host? entry) (>= (length entry) 4))
99 (define (entry-host entry) (list-ref entry 3))
101 (define (has-port? entry) (>= (length entry) 5))
103 (define (entry-port entry) (list-ref entry 4))
105 (define (render-entry entry default-selector default-host default-port selector-prefix)
106 (let ((name-string (entry-name entry)))
108 (lambda (name-string-line)
109 (print* (entry-type entry) name-string-line)
110 (print* "\t" (if (has-selector? entry)
111 (if (has-host? entry)
112 (entry-selector entry)
113 (conc (entry-type entry)
114 (make-pathname selector-prefix (entry-selector entry))))
116 (print* "\t" (if (has-host? entry)
119 (print* "\t" (if (has-port? entry)
123 (string-split name-string "\n" #t))))
125 (define (render-index index selector-prefix this-host this-port)
128 (if (eq? (entry-type entry) 'i)
129 (render-entry entry "fake.selector" "fake.host" 1 selector-prefix)
130 (render-entry entry "" this-host this-port selector-prefix)))