+
+(defun compute-session (req ent url-session-id)
+ (when (is-session-enabled ent)
+ (let* ((cookie-session-id (cookie-session-key ent (request-cookies req)))
+ (session-id (or url-session-id cookie-session-id))
+ (found-session (when session-id
+ (find-websession session-id ent)))
+ (session (aif found-session
+ it
+ (make-websession req ent))))
+ (cond
+ (cookie-session-id
+ (setf (websession-method session) :cookies))
+ (url-session-id
+ (setf (websession-method session) :url)))
+ (setf (websession-from-req req) session))))
+
+
+;;; Reap expired sessions
+
+
+(defun start-reaper ()
+ (process-run-function "wol-reaper"
+ (lambda () (reap-sessions) (kmrcl::process-sleep *reap-interval*))))
+
+(defun reap-sessions ()
+ (cmsg-c :debug "Reaping")
+ (dolist (expired (find-expired-sessions))
+ (flush-expired expired)))
+
+(defun find-expired-sessions ()
+ (loop for s in (all-sessions)
+ when (is-session-expired (car s))
+ collect s))
+
+(defun all-sessions (&aux s)
+ (maphash
+ (lambda (name proj)
+ (declare (ignore name))
+ (let* ((sm (session-master proj))
+ (sessions (when sm (sessions sm))))
+ (when sessions
+ (maphash
+ (lambda (k v)
+ (declare (ignore k))
+ (push (cons v proj) s))
+ sessions))))
+ *active-projects*)
+ s)
+
+(defmethod flush-expired (s)
+ (let ((sessions (sessions (session-master (cdr s)))))
+ (remhash (car s) sessions)
+ (add-log-entry (cdr s) "flush expired session: key=~A"
+ (websession-key (car s)))))
+
+(defun is-session-expired (ws)
+ (> (get-universal-time) (+ (websession-lastref ws)
+ (websession-lifetime ws))))
+
+(defun is-raw-session-id (str)
+ (and (stringp str)
+ (> (length str) 2)
+ (char= #\~ (schar str 0) (schar str (1- (length str))))))
+
+(defun raw-session-id->session-id (str)
+ (subseq str 1 (1- (length str))))