com.paskvil.uhttp-server.lisp
lisp/uhttp/com.paskvil.uhttp-server.lisp download
;;; -*- Lisp -*- mode
(in-package #:com.paskvil.uhttp)
(defun server-start (addr port)
"Open a socket at ADDR:PORT for listening.
Provided restarts: TRY-NEXT-PORT, can be used with
the USOCKET:ADDRESS-IN-USE-ERROR condition."
(restart-case (usocket:socket-listen addr port)
(try-next-port () (server-start addr (1+ port)))))
(defun server-stop (socket)
"Close the server socket, or server socket stream."
(usocket:socket-close socket))
(defun server-wait-for-client (socket)
"Function that waits for incoming connections on SOCKET,
and returns socket stream for each client."
(usocket:socket-accept socket))
(defun server-data-ready (stream)
"Check whether there are data that can be read on STREAM."
(not (eq (listen (usocket:socket-stream stream)) nil)))
(defun server-read (stream &key (max-length 0))
"Reads at most MAX-LENGTH bytes from the input.
If MAX-LENGHT is 0, reads all data available on input."
(let ((instr (usocket:socket-stream stream)))
(with-output-to-string (str)
(do ((len 0 (1+ len))
(c (read-char-no-hang instr nil nil)
(read-char-no-hang instr nil nil)))
((or (not c)
(and (< 0 max-length) (>= len max-length))))
(princ c str)))))
(defun server-read-line (stream &optional (non-blocking nil))
"Reads a single line from a socket STREAM.
If NON-BLOCKING is nil, checks whether any data
are ready for reading; if none, returns empty string."
(let ((line ""))
(if non-blocking
(when (server-data-ready stream)
(setf line (read-line (usocket:socket-stream stream))))
(setf line (read-line (usocket:socket-stream stream))))
(string-right-trim '(#\Newline #\Return) line)))
(defun server-read-all-lines (stream &key (stop-on ""))
"Read all data that are waiting to be read from socket STREAM,
and return them as a list of strings. If one of the lines read
is :STOP-ON string, this line is dropped and reading is stopped."
(let (line)
(loop while (server-data-ready stream)
do (setf line (server-read-line stream))
while (string-not-equal line stop-on)
collecting line)))
(defun server-send (string stream)
"Write a STRING to the server's socket STREAM."
(print string (usocket:socket-stream stream))
(force-output (usocket:socket-stream stream)))