r5473: *** 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.4 2003/08/08 23:40:13 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 #||
19 (awhen (and session-id (find-websession session-id ent))
20        (setf (websession-from-req req) it)
21        (setf (websession-method it) :url))
22 ||#
23
24 (defun find-websession (key ent)
25   (let ((sessions (sessions (session-master (entity-project ent)))))
26     (maphash
27      (lambda (k v)
28        (declare (ignore k))
29        (when (equal key (websession-key v))
30          (setf (websession-lastref v) (get-universal-time))
31          (return-from find-websession v)))
32      sessions)
33     nil))
34
35 (defun is-session-enabled (ent)
36   (not (null (sessions (session-master (entity-project ent))))))
37
38   
39 (defun make-websession (req ent)
40   (let* ((key (random-string :length +length-session-id+
41                              :set :lower-alphanumeric))
42          (sess (make-instance 'websession
43                  :key key
44                  :lastref (get-universal-time)
45                  :lifetime (lifetime (session-master (entity-project ent)))
46                  :method :try-cookie))
47          (hash (sessions (session-master (entity-project ent)))))
48     (when hash
49       (setf (gethash key hash) sess)
50       (setf (websession-from-req req) sess)
51       sess)))
52
53
54 (defun compute-session (req ent)
55   (when (is-session-enabled ent)
56     (let ((key (cookie-session-key ent (request-cookies req)))
57           (has-cookie-key nil)
58           (has-url-key nil))
59       (if key
60           (setq has-cookie-key t)
61         (when (setq key (url-session-key (request-raw-uri req)))
62           (setq has-url-key t)))
63       (let* ((found-session (when key (find-websession key ent)))
64              (session (aif found-session it (make-websession req ent)))) 
65         (setf (websession-from-req req) session)
66         (when found-session
67           (if has-cookie-key
68               (setf (websession-method session) :cookies)
69             (when has-url-key
70               (setf (websession-method session) :url))))
71         session))))
72   
73
74 ;;; Reap expired sessions
75
76
77 (defun start-reaper ()
78   (process-run-function "wol-reaper"
79     (lambda () (reap-sessions) (kmrcl::process-sleep *reap-interval*))))
80
81 (defun reap-sessions ()
82   (cmsg-c :debug "Reaping")
83   (dolist (expired (find-expired-sessions))
84     (flush-expired expired)))
85
86 (defun find-expired-sessions ()
87   (loop for s in (all-sessions)
88         when (is-session-expired (car s))
89         collect s))
90
91 (defun all-sessions (&aux s)
92   (maphash
93    (lambda (name proj)
94      (declare (ignore name))
95      (let* ((sm (session-master proj))
96             (sessions (when sm (sessions sm))))
97        (when sessions
98          (maphash
99           (lambda (k v)
100             (declare (ignore k))
101            (push (cons v proj) s))
102           sessions))))
103    *active-projects*)
104   s)
105
106 (defmethod flush-expired (s)
107   (let ((sessions (sessions (session-master (cdr s)))))
108     (remhash (car s) sessions)
109     (add-log-entry (cdr s) "flush expired session: key=~A" 
110                    (websession-key (car s)))))
111
112 (defun is-session-expired (ws)
113   (> (get-universal-time)  (+ (websession-lastref ws)
114                               (websession-lifetime ws))))
115
116 (defun is-raw-session-id (str)
117   (and (stringp str)
118        (> (length str) 2)
119        (char= #\~ (schar str 0) (schar str (1- (length str))))))
120
121 (defun raw-session-id->session-id (str)
122   (subseq str 1 (1- (length str))))