-
Notifications
You must be signed in to change notification settings - Fork 17
/
sessionstore.go
111 lines (89 loc) · 2.24 KB
/
sessionstore.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main
// Management of long polling sessions
import (
"container/list"
"net/http"
"sync"
"time"
"github.com/gorilla/websocket"
"github.com/daodst/chat/server/store/types"
)
type sessionStoreElement struct {
key string
val *Session
}
type SessionStore struct {
rw sync.RWMutex
sessions map[string]*list.Element
lru *list.List
lifeTime time.Duration
}
func (ss *SessionStore) Create(conn interface{}, appid uint32) *Session {
var s Session
switch conn.(type) {
case *websocket.Conn:
s.proto = WEBSOCK
s.ws, _ = conn.(*websocket.Conn)
case http.ResponseWriter:
s.proto = LPOLL
s.wrt, _ = conn.(http.ResponseWriter)
default:
s.proto = NONE
}
if s.proto != NONE {
s.subs = make(map[string]*Subscription)
s.send = make(chan []byte, 64) // buffered
s.stop = make(chan bool)
s.detach = make(chan string, 64) // buffered
}
s.appid = appid
s.lastTouched = time.Now()
s.sid = getRandomString()
s.uid = types.ZeroUid
if s.proto != WEBSOCK {
// Websocket connections are not managed by SessionStore
ss.rw.Lock()
elem := ss.lru.PushFront(&sessionStoreElement{s.sid, &s})
ss.sessions[s.sid] = elem
// Remove expired sessions
expire := s.lastTouched.Add(-ss.lifeTime)
for elem = ss.lru.Back(); elem != nil; elem = ss.lru.Back() {
if elem.Value.(*sessionStoreElement).val.lastTouched.Before(expire) {
ss.lru.Remove(elem)
delete(ss.sessions, elem.Value.(*sessionStoreElement).key)
} else {
break // don't need to traverse further
}
}
ss.rw.Unlock()
}
return &s
}
func (ss *SessionStore) Get(sid string) *Session {
ss.rw.Lock()
defer ss.rw.Unlock()
if elem := ss.sessions[sid]; elem != nil {
ss.lru.MoveToFront(elem)
elem.Value.(*sessionStoreElement).val.lastTouched = time.Now()
return elem.Value.(*sessionStoreElement).val
}
return nil
}
func (ss *SessionStore) Delete(sid string) *Session {
ss.rw.Lock()
defer ss.rw.Unlock()
if elem := ss.sessions[sid]; elem != nil {
ss.lru.Remove(elem)
delete(ss.sessions, sid)
return elem.Value.(*sessionStoreElement).val
}
return nil
}
func NewSessionStore(lifetime time.Duration) *SessionStore {
store := &SessionStore{
sessions: make(map[string]*list.Element),
lru: list.New(),
lifeTime: lifetime,
}
return store
}