Update domain name to kpe.io
[wol.git] / sessions.lisp
index 227483bab3dabc19313794702c6a80d9db9bb87c..6c63e0433bd82499164e6655b6dac95db9d4736c 100644 (file)
 ;;;; Programmer:    Kevin M. Rosenberg
 ;;;; Date Started:  July 2003
 ;;;;
-;;;; $Id: sessions.lisp,v 1.1 2003/07/16 16:02:21 kevin Exp $
+;;;; $Id$
 ;;;;
 ;;;; This file and Wol are Copyright (c) 2003 by Kevin M. Rosenberg
 ;;;; *************************************************************************
 
 (in-package #:wol)
 
-(defun start-reaper ()
-  (process-run-function "wol-reaper"
-    (lambda () (reap-sessions) (kmrcl::process-sleep *reap-interval*))))
 
-(defun reap-sessions ()
-  (cmsg-c :debug "Reaping"))
+(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 make-new-session-id ()
-  (random-string :length 24 :set :lower-alphanumeric))
+(defun is-session-enabled (ent)
+  (not (null (sessions (session-master (entity-project ent))))))
 
-(defun ensure-websession (key req ent method)
-  "Find or make websession for key"
-  (let ((sessions (sessions (session-master (entity-project ent)))))
-    ;; if sessions doesn't exist, then project is not session enabled
-    (when session
-      (cond 
-       ((null key)
-       (make-websession req ent method))
-       (t
-       (maphash
-        (lambda (k v)
-          (declare (ignore k))
-          (when (equal key (websession-key v))
-            (setf (websession-lastref v) (get-universal-time))
-            (return-from ensure-websession v)))
-        sessions)
-       (make-websession req ent method))))))
-
-  
-(defun make-websession (req ent method)
-  (let* ((key (random-string :length 24 :set :lower-alphanumeric))
-        (sess (make-instance 'websession
-                :key key
-                :lastref (get-universal-time)
-                :method method))
-        (hash (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)
-  (awhen (and (request-plist req)
-             (getf (request-plist req) :session-id))
-        (setf (websession-from-req req) 
-          (ensure-websession it req ent :uri))))
+
+(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))))