r5549: *** 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.6 2003/08/23 22:30:30 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 :try-cookie))
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          (setf (websession-method session) :url)))
62       (setf (websession-from-req req) session))))
63   
64
65 ;;; Reap expired sessions
66
67
68 (defun start-reaper ()
69   (process-run-function "wol-reaper"
70     (lambda () (reap-sessions) (kmrcl::process-sleep *reap-interval*))))
71
72 (defun reap-sessions ()
73   (cmsg-c :debug "Reaping")
74   (dolist (expired (find-expired-sessions))
75     (flush-expired expired)))
76
77 (defun find-expired-sessions ()
78   (loop for s in (all-sessions)
79         when (is-session-expired (car s))
80         collect s))
81
82 (defun all-sessions (&aux s)
83   (maphash
84    (lambda (name proj)
85      (declare (ignore name))
86      (let* ((sm (session-master proj))
87             (sessions (when sm (sessions sm))))
88        (when sessions
89          (maphash
90           (lambda (k v)
91             (declare (ignore k))
92            (push (cons v proj) s))
93           sessions))))
94    *active-projects*)
95   s)
96
97 (defmethod flush-expired (s)
98   (let ((sessions (sessions (session-master (cdr s)))))
99     (remhash (car s) sessions)
100     (add-log-entry (cdr s) "flush expired session: key=~A" 
101                    (websession-key (car s)))))
102
103 (defun is-session-expired (ws)
104   (> (get-universal-time)  (+ (websession-lastref ws)
105                               (websession-lifetime ws))))
106
107 (defun is-raw-session-id (str)
108   (and (stringp str)
109        (> (length str) 2)
110        (char= #\~ (schar str 0) (schar str (1- (length str))))))
111
112 (defun raw-session-id->session-id (str)
113   (subseq str 1 (1- (length str))))