This is the first checked-in completely working version. It contains
nearly all concepts and simple implementations thereof needed to get a simple HTTP/0.9 "compliant" server working (there are some hacks needed that we don't yet provide, since the correct things will be added shortly, like complete HTTP/1.1 request parsing. The hacks needed are provided as part of the basic HTTP/0.9 server demo in src/test/basic-demo.cl). Further work is needed to clean up some things, Entity and Resource handling needs to be implemented right and less "naive" (the current implementations are just simple place-holders to get things up and running). Connections need to have knowledge of client identity (passed from the driver, this is implementation-specific stuff). Logging needs to be implemented (probably as server mixins). Condition handling needs to generate better responses for HTTP/0.9, and the division between condition handling and normal handling needs to be documented/rethought. Content generation is totally missing currently and needs to be implemented. If this is all in place, an HTTP/1.0 conforming server should be possible, and after porting the drivers to ACL and LW, we can make a first release.
This commit is contained in:
65
src/drivers/simple-cmu.cl
Normal file
65
src/drivers/simple-cmu.cl
Normal file
@ -0,0 +1,65 @@
|
||||
;;;; CLASH --- The Common Lisp Adaptable Simple HTTP server
|
||||
;;;; This is copyrighted software. See documentation for terms.
|
||||
;;;;
|
||||
;;;; simple-cmu.cl --- Simple HTTP-Server driver for CMU CL
|
||||
;;;;
|
||||
;;;; Checkout Tag: $Name$
|
||||
;;;; $Id$
|
||||
|
||||
(in-package :CLASH)
|
||||
|
||||
;;;; %File Description:
|
||||
;;;;
|
||||
;;;;
|
||||
;;;;
|
||||
|
||||
(defun ip-address-string (address)
|
||||
(format nil "~D.~D.~D.~D"
|
||||
(ldb (byte 8 24) address)
|
||||
(ldb (byte 8 16) address)
|
||||
(ldb (byte 8 8) address)
|
||||
(ldb (byte 8 0) address)))
|
||||
|
||||
(defun http-listener (port server)
|
||||
(let ((fd (ext:create-inet-listener port)))
|
||||
(unless fd (error "Cannot bind port ~D." port))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setf (process-name *current-process*)
|
||||
(format nil
|
||||
"HTTP connection listener on port ~D with server ~A"
|
||||
port server))
|
||||
(format t "~&;;; Started lisp connection listener on ~
|
||||
port ~d for server ~A~%" port server)
|
||||
(loop
|
||||
;; Wait for new connection
|
||||
(process-wait-until-fd-usable fd :input)
|
||||
#+CLASH-DEBUG
|
||||
(format t "~&;;; At ~D Got Connection...~%"
|
||||
(get-internal-real-time))
|
||||
(multiple-value-bind (new-fd remote-host)
|
||||
(ext:accept-tcp-connection fd)
|
||||
#+CLASH-DEBUG
|
||||
(format t "~&;;; At ~D Have Connection...~%"
|
||||
(get-internal-real-time))
|
||||
(let* ((host-entry (ext:lookup-host-entry remote-host))
|
||||
(stream (sys:make-fd-stream new-fd :input t :output t))
|
||||
(connection (make-instance 'simple-connection
|
||||
:stream stream)))
|
||||
#+CLASH-DEBUG
|
||||
(format t "~&;;; At ~D Established Connection...~%"
|
||||
(get-internal-real-time))
|
||||
(make-process
|
||||
#'(lambda ()
|
||||
(serve-connection server connection))
|
||||
:name (format nil "HTTP connection from ~A"
|
||||
(if host-entry
|
||||
(ext:host-entry-name host-entry)
|
||||
(ip-address-string remote-host))))))))
|
||||
(when fd (unix:unix-close fd)))))
|
||||
|
||||
(defun start-http-listener (port server)
|
||||
(make-process #'(lambda () (http-listener port server))))
|
||||
|
||||
(defun initialize-clash (&optional (idle-process mp::*initial-process*))
|
||||
(setf mp::*idle-process* idle-process))
|
||||
Reference in New Issue
Block a user