r5483: *** empty log message ***
[wol.git] / sessions.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: wol -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          sessions.lisp
6 ;;;; Purpose:       Session handler
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  July 2003
9 ;;;;
10 ;;;; $Id: sessions.lisp,v 1.5 2003/08/09 21:42:24 kevin Exp $
11 ;;;;
12 ;;;; This file and Wol are Copyright (c) 2003 by Kevin M. Rosenberg
13 ;;;; *************************************************************************
14
15 (in-package #:wol)
16
17
18 (defun find-websession (key ent)
19   (let ((sessions (sessions (session-master (entity-project ent)))))
20     (maphash
21      (lambda (k v)
22        (declare (ignore k))
23        (when (equal key (websession-key v))
24          (setf (websession-lastref v) (get-universal-time))
25          (return-from find-websession v)))
26      sessions)
27     nil))
28
29 (defun is-session-enabled (ent)
30   (not (null (sessions (session-master (entity-project ent))))))
31
32   
33 (defun make-websession (req ent)
34   (let* ((key (random-string :length +length-session-id+
35                              :set :lower-alphanumeric))
36          (sess (make-instance 'websession
37                  :key key
38                  :lastref (get-universal-time)
39                  :lifetime (lifetime (session-master (entity-project ent)))
40                  :method nil))
41          (hash (sessions (session-master (entity-project ent)))))
42     (when hash
43       (setf (gethash key hash) sess)
44       (setf (websession-from-req req) sess)
45       sess)))
46
47
48 (defun compute-session (req ent url-session-id)
49   (when (is-session-enabled ent)
50     (let* ((cookie-session-id (cookie-session-key ent (request-cookies req)))
51            (session-id (or url-session-id cookie-session-id))
52            (found-session (when session-id
53                             (find-websession session-id ent)))
54            (session (aif found-session
55                          it
56                          (make-websession req ent))))
57       (cond
58         (cookie-session-id
59          (setf (websession-method session) :cookies))
60         (url-session-id
61          (case (websession-method session)
62            (nil
63             (setf (websession-method session) :try-cookie))
64            (:try-cookie
65             (setf (websession-method session) :try-cookie-2))
66            (t
67             (setf (websession-method session) :url)))))
68       (setf (websession-from-req req) session))))
69   
70
71 ;;; Reap expired sessions
72
73
74 (defun start-reaper ()
75   (process-run-function "wol-reaper"
76     (lambda () (reap-sessions) (kmrcl::process-sleep *reap-interval*))))
77
78 (defun reap-sessions ()
79   (cmsg-c :debug "Reaping")
80   (dolist (expired (find-expired-sessions))
81     (flush-expired expired)))
82
83 (defun find-expired-sessions ()
84   (loop for s in (all-sessions)
85         when (is-session-expired (car s))
86         collect s))
87
88 (defun all-sessions (&aux s)
89   (maphash
90    (lambda (name proj)
91      (declare (ignore name))
92      (let* ((sm (session-master proj))
93             (sessions (when sm (sessions sm))))
94        (when sessions
95          (maphash
96           (lambda (k v)
97             (declare (ignore k))
98            (push (cons v proj) s))
99           sessions))))
100    *active-projects*)
101   s)
102
103 (defmethod flush-expired (s)
104   (let ((sessions (sessions (session-master (cdr s)))))
105     (remhash (car s) sessions)
106     (add-log-entry (cdr s) "flush expired session: key=~A" 
107                    (websession-key (car s)))))
108
109 (defun is-session-expired (ws)
110   (> (get-universal-time)  (+ (websession-lastref ws)
111                               (websession-lifetime ws))))
112
113 (defun is-raw-session-id (str)
114   (and (stringp str)
115        (> (length str) 2)
116        (char= #\~ (schar str 0) (schar str (1- (length str))))))
117
118 (defun raw-session-id->session-id (str)
119   (subseq str 1 (1- (length str))))