;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: wol -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sessions.lisp ;;;; Purpose: Session handler ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: July 2003 ;;;; ;;;; $Id: sessions.lisp,v 1.4 2003/08/08 23:40:13 kevin Exp $ ;;;; ;;;; This file and Wol are Copyright (c) 2003 by Kevin M. Rosenberg ;;;; ************************************************************************* (in-package #:wol) #|| (awhen (and session-id (find-websession session-id ent)) (setf (websession-from-req req) it) (setf (websession-method it) :url)) ||# (defun find-websession (key ent) (let ((sessions (sessions (session-master (entity-project ent))))) (maphash (lambda (k v) (declare (ignore k)) (when (equal key (websession-key v)) (setf (websession-lastref v) (get-universal-time)) (return-from find-websession v))) sessions) nil)) (defun is-session-enabled (ent) (not (null (sessions (session-master (entity-project ent)))))) (defun make-websession (req ent) (let* ((key (random-string :length +length-session-id+ :set :lower-alphanumeric)) (sess (make-instance 'websession :key key :lastref (get-universal-time) :lifetime (lifetime (session-master (entity-project ent))) :method :try-cookie)) (hash (sessions (session-master (entity-project ent))))) (when hash (setf (gethash key hash) sess) (setf (websession-from-req req) sess) sess))) (defun compute-session (req ent) (when (is-session-enabled ent) (let ((key (cookie-session-key ent (request-cookies req))) (has-cookie-key nil) (has-url-key nil)) (if key (setq has-cookie-key t) (when (setq key (url-session-key (request-raw-uri req))) (setq has-url-key t))) (let* ((found-session (when key (find-websession key ent))) (session (aif found-session it (make-websession req ent)))) (setf (websession-from-req req) session) (when found-session (if has-cookie-key (setf (websession-method session) :cookies) (when has-url-key (setf (websession-method session) :url)))) 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))))