build
This commit is contained in:
parent
acb2380660
commit
24a801bc0e
|
@ -39,13 +39,19 @@ openssl req -x509 \
|
||||||
Start sbcl with proper readline support: `rlwrap sbcl`
|
Start sbcl with proper readline support: `rlwrap sbcl`
|
||||||
|
|
||||||
```lisp
|
```lisp
|
||||||
|
(ql:quickload "geml")
|
||||||
(gemini.server:start-server)
|
(gemini.server:start-server)
|
||||||
; or with a custom settings file location
|
; or with a custom settings file location
|
||||||
(gemini.server:start-server "/path/to/geml.ini")
|
(gemini.server:start-server "/path/to/geml.ini")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Standalone Executable
|
### Standalone Executable
|
||||||
|
|
||||||
- [ ] save-lisp-and-die
|
To get a `geml-server` binary run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sbcl --non-interactive --load build.lisp
|
||||||
|
```
|
||||||
|
|
||||||
### Systemd
|
### Systemd
|
||||||
|
|
||||||
|
|
5
build.lisp
Normal file
5
build.lisp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
(ql:quickload :geml/bin)
|
||||||
|
|
||||||
|
(sb-ext:save-lisp-and-die "geml-server"
|
||||||
|
:toplevel 'geml.server:bin
|
||||||
|
:executable t)
|
13
geml.asd
13
geml.asd
|
@ -9,6 +9,13 @@
|
||||||
:cl+ssl
|
:cl+ssl
|
||||||
:quri
|
:quri
|
||||||
:cl-ini)
|
:cl-ini)
|
||||||
:serial t
|
:components ((:file "packages")
|
||||||
:components ((:module "src" :components
|
(:module "src"
|
||||||
((:file "server")))))
|
:serial t
|
||||||
|
:components ((:file "server")))))
|
||||||
|
|
||||||
|
(asdf:defsystem geml/bin
|
||||||
|
:depends-on (:geml
|
||||||
|
:unix-opts)
|
||||||
|
:components ((:module "src"
|
||||||
|
:components ((:file "bin")))))
|
||||||
|
|
3
packages.lisp
Normal file
3
packages.lisp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
(defpackage #:geml.server
|
||||||
|
(:use :common-lisp)
|
||||||
|
(:export :start-server :bin))
|
18
src/bin.lisp
Normal file
18
src/bin.lisp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
(in-package #:geml.server)
|
||||||
|
|
||||||
|
(unix-opts:define-opts
|
||||||
|
(:name :config
|
||||||
|
:short #\c
|
||||||
|
:long "config"
|
||||||
|
;; TODO create arg-parser that resolves stuff like --config ./gmi.ini
|
||||||
|
:arg-parser #'identity
|
||||||
|
:description "path to a geml.ini file"
|
||||||
|
:default "/etc/geml/geml.ini")
|
||||||
|
;; TODO --help
|
||||||
|
;; TODO --gen-certs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(defun bin ()
|
||||||
|
(multiple-value-bind (options free-args) (unix-opts:get-opts)
|
||||||
|
(start-server (getf options :config))))
|
|
@ -1,9 +1,13 @@
|
||||||
(defpackage #:geml.server
|
|
||||||
(:use :common-lisp))
|
|
||||||
(in-package #:geml.server)
|
(in-package #:geml.server)
|
||||||
|
|
||||||
;; TODO use path library for portability:
|
(defun write-file (filepath conn)
|
||||||
;; http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_the_filen_s_dictionary.html
|
(with-open-file (in filepath :element-type '(unsigned-byte 8))
|
||||||
|
(loop
|
||||||
|
with buffer = (make-array 1024 :element-type '(unsigned-byte 8))
|
||||||
|
for pos = (read-sequence buffer in)
|
||||||
|
until (zerop pos)
|
||||||
|
do (write-sequence buffer conn :end pos))))
|
||||||
|
|
||||||
(defun resolve-index (path)
|
(defun resolve-index (path)
|
||||||
(let ((index "index.gmi")
|
(let ((index "index.gmi")
|
||||||
(has-extension (if (< 5 (length path))
|
(has-extension (if (< 5 (length path))
|
||||||
|
@ -14,14 +18,6 @@
|
||||||
(has-backslash (concatenate 'string path index))
|
(has-backslash (concatenate 'string path index))
|
||||||
(t (concatenate 'string path "/" index)))))
|
(t (concatenate 'string path "/" index)))))
|
||||||
|
|
||||||
(defun write-file (filepath conn)
|
|
||||||
(with-open-file (in filepath :element-type '(unsigned-byte 8))
|
|
||||||
(loop
|
|
||||||
with buffer = (make-array 1024 :element-type '(unsigned-byte 8))
|
|
||||||
for pos = (read-sequence buffer in)
|
|
||||||
until (zerop pos)
|
|
||||||
do (write-sequence buffer conn :end pos))))
|
|
||||||
|
|
||||||
(defun handle-request (conn settings)
|
(defun handle-request (conn settings)
|
||||||
(let* ((uri (quri:uri (read-line conn)))
|
(let* ((uri (quri:uri (read-line conn)))
|
||||||
(domain (quri:uri-domain uri))
|
(domain (quri:uri-domain uri))
|
||||||
|
@ -30,11 +26,13 @@
|
||||||
:root
|
:root
|
||||||
:section (intern (string-upcase domain)
|
:section (intern (string-upcase domain)
|
||||||
:keyword)))
|
:keyword)))
|
||||||
|
;; TODO use path library?
|
||||||
|
;; http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_the_filen_s_dictionary.html
|
||||||
(filename (probe-file (concatenate 'string
|
(filename (probe-file (concatenate 'string
|
||||||
root
|
root
|
||||||
(resolve-index path)))))
|
(resolve-index path)))))
|
||||||
(if filename
|
(if filename
|
||||||
(progn (format t "serving ~a~%" filename)
|
(progn (format t "geml is serving gemini://~a~a (~a)~%" domain path filename)
|
||||||
(write-line "20 text/gemini" conn)
|
(write-line "20 text/gemini" conn)
|
||||||
(write-file filename conn))
|
(write-file filename conn))
|
||||||
(format conn "51 ~a does not exist for ~a~%" path domain)))
|
(format conn "51 ~a does not exist for ~a~%" path domain)))
|
||||||
|
@ -48,21 +46,24 @@
|
||||||
"0.0.0.0"))
|
"0.0.0.0"))
|
||||||
(port (or (cl-ini:ini-value settings :port)
|
(port (or (cl-ini:ini-value settings :port)
|
||||||
1965))
|
1965))
|
||||||
(server (usocket:socket-listen host port)))
|
(key (probe-file (cl-ini:ini-value settings :key)))
|
||||||
(format t "geml is live on ~a:~a with settings from ~a~%"
|
(cert (probe-file (cl-ini:ini-value settings :cert))))
|
||||||
host
|
(cond
|
||||||
port
|
((not cert) (format t "geml cannot read cert using path defined in ~a~%" settings-file))
|
||||||
settings-file)
|
((not key) (format t "geml cannot read key using path defined in ~a~%" settings-file))
|
||||||
(unwind-protect
|
(t (let ((server (usocket:socket-listen host port)))
|
||||||
(loop (let* ((socket (usocket:socket-accept server))
|
(format t "geml booted on ~a:~a (~a)~%"
|
||||||
(key (cl-ini:ini-value settings :key))
|
host
|
||||||
(cert (cl-ini:ini-value settings :cert))
|
port
|
||||||
(conn (cl+ssl:make-ssl-server-stream
|
settings-file)
|
||||||
(usocket:socket-stream socket)
|
(unwind-protect
|
||||||
:external-format '(:utf-8 :eol-style :crlf)
|
(loop (let* ((socket (usocket:socket-accept server))
|
||||||
:certificate cert
|
(conn (cl+ssl:make-ssl-server-stream
|
||||||
:key key)))
|
(usocket:socket-stream socket)
|
||||||
(unwind-protect (handle-request conn settings)
|
:external-format '(:utf-8 :eol-style :crlf)
|
||||||
(close conn))))
|
:certificate (namestring cert)
|
||||||
(format t "Closing Server~%")
|
:key (namestring key))))
|
||||||
(usocket:socket-close server))))
|
(unwind-protect (handle-request conn settings)
|
||||||
|
(close conn))))
|
||||||
|
(format t "geml is shutting down...~%")
|
||||||
|
(usocket:socket-close server)))))))
|
||||||
|
|
Loading…
Reference in a new issue