Skip to content
This repository
Newer
Older
100644 350 lines (289 sloc) 11.246 kb
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
1 %%%----------------------------------------------------------------------
2 %%% File : yaws_session_server.erl
3 %%% Author : Claes Wikstrom <klacke@hyber.org>
4 %%% Purpose : maintain state for cookie sessions
5 %%% Created : 17 Sep 2002 by Claes Wikstrom <klacke@hyber.org>
6 %%%----------------------------------------------------------------------
7
8 -module(yaws_session_server).
9 -author('klacke@hyber.org').
10
11
12 -behaviour(gen_server).
13
14 %% External exports
9a74e5aa »
2008-05-12 Major general code cleanup, finally got rid of all the export_all sta…
15 -export([start_link/0, start/0, stop/0]).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
16
17 %% gen_server callbacks
ca1c8b1b » karlsson
2010-07-01 Fixed a number of compiler warnings and html validation errors
18 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
6e96a140 »
2011-03-03 indendation cleanup
19 code_change/3]).
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
20
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
21 -include("../include/yaws_api.hrl").
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
22 -include("../include/yaws.hrl").
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
23
5f13a9c1 »
2009-02-17 Two patches by Joseph Wayen Norton, one dbg-bug and one providing bet…
24 -export([new_session/1,new_session/2,new_session/3,new_session/4,
9a74e5aa »
2008-05-12 Major general code cleanup, finally got rid of all the export_all sta…
25 cookieval_to_opaque/1,
26 print_sessions/0,
27 replace_session/2,
28 delete_session/1]).
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
29
30 %% Default ETS backend callbacks
31 -export ([init_backend/1, stop_backend/0,
32 list/0, lookup/1, insert/1, delete/1,
33 traverse/1, cleanup/0]).
34
35 %% Utility functions for callbacks
36 -export ([has_timedout/2, report_timedout_sess/1, cookie/1]).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
37
87b14560 »
2002-10-06 wrote the shopppingcart example
38 -define(TTL, (30 * 60)). % 30 minutes
39
40 -record(ysession,
0be3c7e8 »
2008-02-14 untabified all of yaws
41 {cookie, %% the cookie assigned to the session
42 to, %% greg secs untill timeout death
43 ttl, %% default time to live
44 starttime, %% When calendar:local_time() did sess start
6964fff7 »
2008-07-01 modified patch by Robert David to add a hook to yaws session server w…
45 cleanup, %% PID to notify of session end
0be3c7e8 »
2008-02-14 untabified all of yaws
46 opaque %% any data the user supplies
47 }).
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
48
49 -record(state,
50 {backend %% storage engine module
51 }).
87b14560 »
2002-10-06 wrote the shopppingcart example
52
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
53
54 %%%----------------------------------------------------------------------
55 %%% API
56 %%%----------------------------------------------------------------------
57 start_link() ->
d2d461c2 » Torbjorn Tornkvist
2011-03-04 Figuring out proper yaws_session_server backend.
58 Backend = get_yaws_session_server_backend(),
455578a2 » vinoski
2011-04-19 major trailing whitespace cleanup
59 gen_server:start_link({local, yaws_session_server},
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
60 yaws_session_server, Backend, []).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
61 start() ->
d2d461c2 » Torbjorn Tornkvist
2011-03-04 Figuring out proper yaws_session_server backend.
62 Backend = get_yaws_session_server_backend(),
455578a2 » vinoski
2011-04-19 major trailing whitespace cleanup
63 gen_server:start({local, yaws_session_server},
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
64 yaws_session_server, Backend, []).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
65 stop() ->
aa815f2d »
2008-05-17 added a set of infinity to several gen_server:calls
66 gen_server:call(?MODULE, stop, infinity).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
67
68
d2d461c2 » Torbjorn Tornkvist
2011-03-04 Figuring out proper yaws_session_server backend.
69 %% We are bending over here in our pursuit of finding a
70 %% proper ysession_server backend.
71 get_yaws_session_server_backend() ->
72 #gconf{ysession_mod = DefaultBackend} = #gconf{},
73 case yaws_server:getconf() of
74 {ok, #gconf{ysession_mod = Backend}, _} -> Backend;
75 _ ->
76 case application:get_env(yaws, embedded) of
f43aa7df »
2011-03-06 correction
77 {ok, true} ->
d2d461c2 » Torbjorn Tornkvist
2011-03-04 Figuring out proper yaws_session_server backend.
78 case application:get_env(yaws, embedded_conf) of
525846e2 »
2011-03-05 Some dialyzer fixes - no real bugs, just enhancements, removed the de…
79 {ok, L} when is_list(L) ->
d2d461c2 » Torbjorn Tornkvist
2011-03-04 Figuring out proper yaws_session_server backend.
80 case lists:keysearch(gc, 1, L) of
81 {value, {_, #gconf{ysession_mod = Backend}}} ->
82 Backend;
83 _ ->
84 DefaultBackend
85 end;
86 _ ->
87 DefaultBackend
88 end;
89 _ ->
90 DefaultBackend
91 end
92 end.
93
94
87b14560 »
2002-10-06 wrote the shopppingcart example
95 %% will return a new cookie as a string
96 new_session(Opaque) ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
97 Call = {new_session, Opaque, ?TTL, undefined, undefined},
98 gen_server:call(?MODULE, Call, infinity).
13b21a99 »
2004-05-28 yaws_session_server ttl patch from Rob.Schmersel
99
100 new_session(Opaque, TTL) ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
101 Call = {new_session, Opaque, TTL, undefined, undefined},
102 gen_server:call(?MODULE, Call, infinity).
6964fff7 »
2008-07-01 modified patch by Robert David to add a hook to yaws session server w…
103
104 new_session(Opaque, TTL, Cleanup) ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
105 Call = {new_session, Opaque, TTL, Cleanup, undefined},
106 gen_server:call(?MODULE, Call, infinity).
87b14560 »
2002-10-06 wrote the shopppingcart example
107
5f13a9c1 »
2009-02-17 Two patches by Joseph Wayen Norton, one dbg-bug and one providing bet…
108 new_session(Opaque, TTL, Cleanup, Cookie) ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
109 Call = {new_session, Opaque, TTL, Cleanup, Cookie},
110 gen_server:call(?MODULE, Call, infinity).
6e96a140 »
2011-03-03 indendation cleanup
111
5f13a9c1 »
2009-02-17 Two patches by Joseph Wayen Norton, one dbg-bug and one providing bet…
112 cookieval_to_opaque(Cookie) ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
113 gen_server:call(?MODULE, {cookieval_to_opaque, Cookie}, infinity).
87b14560 »
2002-10-06 wrote the shopppingcart example
114
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
115 print_sessions() ->
f73d23dc »
2011-02-23 Fixed dialyzer bugs found by Tuncer, Issue #54
116 gen_server:cast(?MODULE, print_sessions).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
117
87b14560 »
2002-10-06 wrote the shopppingcart example
118 replace_session(Cookie, NewOpaque) ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
119 gen_server:call(?MODULE, {replace_session, Cookie, NewOpaque}, infinity).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
120
87b14560 »
2002-10-06 wrote the shopppingcart example
121 delete_session(CookieVal) ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
122 gen_server:call(?MODULE, {delete_session, CookieVal}, infinity).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
123
124 %%%----------------------------------------------------------------------
125 %%% Callback functions from gen_server
126 %%%----------------------------------------------------------------------
127
128 %%----------------------------------------------------------------------
129 %% Func: init/1
130 %% Returns: {ok, State} |
131 %% {ok, State, Timeout} |
132 %% ignore |
133 %% {stop, Reason}
134 %%----------------------------------------------------------------------
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
135 init(Backend) ->
136 Backend:init_backend(record_info(fields, ysession)),
f4867b8a »
2008-05-08 Better timeout support in yaws-session_server
137 start_long_timer(),
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
138 {ok, #state{backend = Backend}, to()}.
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
139
140 %%----------------------------------------------------------------------
141 %% Func: handle_call/3
142 %% Returns: {reply, Reply, State} |
143 %% {reply, Reply, State, Timeout} |
144 %% {noreply, State} |
145 %% {noreply, State, Timeout} |
146 %% {stop, Reason, Reply, State} | (terminate/2 is called)
147 %% {stop, Reason, State} (terminate/2 is called)
148 %%----------------------------------------------------------------------
149
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
150 handle_call({new_session, Opaque, undefined, Cleanup, Cookie}, From, State) ->
151 handle_call({new_session, Opaque, ?TTL, Cleanup, Cookie}, From, State);
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
152
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
153 handle_call({new_session, Opaque, TTL, Cleanup, undefined}, From, State) ->
b44aba6d »
2012-06-20 Use crypto:rand_bytes() instead of the cryptogrphicalli weak random m…
154 N = crypto:rand_bytes(16),
155 Cookie = atom_to_list(node()) ++ [$-|binary_to_list(N)],
5f13a9c1 »
2009-02-17 Two patches by Joseph Wayen Norton, one dbg-bug and one providing bet…
156 handle_call({new_session, Opaque, TTL, Cleanup, Cookie}, From, State);
157
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
158 handle_call({new_session, Opaque, TTL, Cleanup, Cookie}, _From, State) ->
5f13a9c1 »
2009-02-17 Two patches by Joseph Wayen Norton, one dbg-bug and one providing bet…
159 Now = gnow(),
87b14560 »
2002-10-06 wrote the shopppingcart example
160 TS = calendar:local_time(),
5f13a9c1 »
2009-02-17 Two patches by Joseph Wayen Norton, one dbg-bug and one providing bet…
161 NS = #ysession{cookie = Cookie,
0be3c7e8 »
2008-02-14 untabified all of yaws
162 starttime = TS,
163 opaque = Opaque,
164 to = Now + TTL,
6964fff7 »
2008-07-01 modified patch by Robert David to add a hook to yaws session server w…
165 ttl = TTL,
166 cleanup = Cleanup},
455578a2 » vinoski
2011-04-19 major trailing whitespace cleanup
167 Backend = State#state.backend,
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
168 true = Backend:insert(NS),
169 {reply, Cookie, State, to()};
170
171 handle_call({cookieval_to_opaque, Cookie}, _From, State) ->
172 Backend = State#state.backend,
173 Result =
174 case Backend:lookup(Cookie) of
175 [Y] ->
176 Y2 = Y#ysession{to = gnow() + Y#ysession.ttl},
177 Backend:insert(Y2),
178 {ok, Y#ysession.opaque};
179 [] ->
180 {error, no_session}
181 end,
182 {reply, Result, State, to()};
183
184 handle_call({replace_session, Cookie, NewOpaque}, _From, State) ->
185 Backend = State#state.backend,
455578a2 » vinoski
2011-04-19 major trailing whitespace cleanup
186 Result =
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
187 case Backend:lookup(Cookie) of
188 [Y] ->
189 Y2 = Y#ysession{to = gnow() + Y#ysession.ttl,
190 opaque = NewOpaque},
191 Backend:insert(Y2);
192 [] ->
193 error
194 end,
195 {reply, Result, State, to()};
196
197 handle_call({delete_session, CookieVal}, _From, State) ->
198 Backend = State#state.backend,
199 Result =
200 case Backend:lookup(CookieVal) of
455578a2 » vinoski
2011-04-19 major trailing whitespace cleanup
201 [Y] ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
202 Backend:delete(CookieVal),
203 report_deleted_sess(Y);
204 [] ->
205 true
206 end,
207 {reply, Result, State, to()};
208
209 handle_call(stop, From, State) ->
210 gen_server:reply(From, ok),
211 {stop, normal, State}.
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
212
213 %%----------------------------------------------------------------------
214 %% Func: handle_cast/2
215 %% Returns: {noreply, State} |
216 %% {noreply, State, Timeout} |
217 %% {stop, Reason, State} (terminate/2 is called)
218 %%----------------------------------------------------------------------
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
219 handle_cast(print_session, #state{backend = Backend} = State) ->
220 Ss = Backend:list(Backend),
221 io:format("** ~p sessions active ~n~n", [length(Ss)]),
222 N = gnow(),
223 lists:foreach(fun(S) ->
224 io:format("Cookie ~p ~n", [S#ysession.cookie]),
225 io:format("Start ~p ~n", [S#ysession.starttime]),
226 io:format("TTL ~p secs~n", [S#ysession.to - N]),
227 io:format("Opaque ~p ~n~n~n", [S#ysession.opaque]),
228 ok
229 end, Ss),
230 {noreply, State, to()};
231
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
232 handle_cast(_Msg, State) ->
f4867b8a »
2008-05-08 Better timeout support in yaws-session_server
233 {noreply, State, to()}.
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
234
235 %%----------------------------------------------------------------------
236 %% Func: handle_info/2
237 %% Returns: {noreply, State} |
238 %% {noreply, State, Timeout} |
239 %% {stop, Reason, State} (terminate/2 is called)
240 %%----------------------------------------------------------------------
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
241 handle_info(timeout, #state{backend = Backend} = State) ->
242 Backend:traverse(gnow()),
243 {noreply, State, to()};
f4867b8a »
2008-05-08 Better timeout support in yaws-session_server
244
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
245 handle_info(long_timeout, #state{backend = Backend} = State) ->
246 Backend:traverse(gnow()),
f4867b8a »
2008-05-08 Better timeout support in yaws-session_server
247 start_long_timer(),
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
248 {noreply, State, to()}.
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
249
250
251 %%----------------------------------------------------------------------
252 %% Func: terminate/2
253 %% Purpose: Shutdown the server
254 %% Returns: any (ignored by gen_server)
255 %%----------------------------------------------------------------------
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
256 terminate(_Reason, #state{backend = Backend}) ->
257 Backend:stop_backend(),
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
258 ok.
259
ca1c8b1b » karlsson
2010-07-01 Fixed a number of compiler warnings and html validation errors
260 %%----------------------------------------------------------------------
261 %% Func: code_change/3
262 %% Purpose: Handle upgrade
263 %% Returns: new State data
264 %%----------------------------------------------------------------------
265 code_change(_OldVsn, Data, _Extra) ->
266 {ok, Data}.
267
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
268 %%%----------------------------------------------------------------------
269 %%% Internal functions
270 %%%----------------------------------------------------------------------
271
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
272 %% timeout once every hour even if the server handles traffic all the time.
273 start_long_timer() ->
274 erlang:send_after(long_to(), self(), long_timeout).
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
275
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
276 long_to() ->
277 60 * 60 * 1000.
278
279 %% timeout if the server is idle for more than 2 minutes.
280 to() ->
b44aba6d »
2012-06-20 Use crypto:rand_bytes() instead of the cryptogrphicalli weak random m…
281 2 * 60 * 1000.
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
282 gnow() ->
283 calendar:datetime_to_gregorian_seconds(
284 calendar:local_time()).
285
286 send_cleanup_message(Sess,Msg) ->
287 case Sess#ysession.cleanup of
288 undefined ->
289 nocleanup;
290 Pid ->
291 Pid ! Msg
292 end.
293
294 report_timedout_sess(S) ->
295 send_cleanup_message(S,{yaws_session_end,timeout,
296 S#ysession.cookie, S#ysession.opaque}).
297
298 report_deleted_sess(S) ->
299 send_cleanup_message(S,{yaws_session_end,normal,
300 S#ysession.cookie, S#ysession.opaque}).
301
302 has_timedout(Y, Time) ->
303 Y#ysession.to =< Time.
304
305 cookie(Y) ->
306 Y#ysession.cookie.
307
308 %% Backend callbacks (ETS as default)
309
310 init_backend (_) ->
311 ets:new(?MODULE, [set, named_table, public, {keypos, 2}]).
312
313 stop_backend() ->
314 ok.
315
316 lookup(Key) ->
317 ets:lookup(?MODULE, Key).
318
319 insert(Session) ->
320 ets:insert(?MODULE, Session).
321
322 list() ->
323 ets:tab2list(?MODULE).
324
325 delete(Key) ->
326 ets:delete(?MODULE, Key).
327
328 cleanup() ->
329 ets:delete_all_objects(?MODULE).
330
331 traverse(N) ->
332 traverse(N, ets:first(?MODULE)).
333
334 traverse(_N, '$end_of_table') ->
87b14560 »
2002-10-06 wrote the shopppingcart example
335 ok;
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
336 traverse(N, Key) ->
337 case lookup(Key) of
0be3c7e8 »
2008-02-14 untabified all of yaws
338 [Y] ->
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
339 case has_timedout(Y, N) of
340 false ->
341 traverse(N, ets:next(?MODULE, Key));
0be3c7e8 »
2008-02-14 untabified all of yaws
342 true ->
343 report_timedout_sess(Y),
344 Next = ets:next(?MODULE, Key),
c6f26aaa » nthauvin
2011-01-06 Pluggable ysession storage with mnesia sample in src/contrib, part 2
345 delete(Key),
455578a2 » vinoski
2011-04-19 major trailing whitespace cleanup
346 traverse(N, Next)
0be3c7e8 »
2008-02-14 untabified all of yaws
347 end;
348 [] ->
6e96a140 »
2011-03-03 indendation cleanup
349 traverse(N, ets:next(?MODULE, Key))
87b14560 »
2002-10-06 wrote the shopppingcart example
350 end.
80771c86 »
2002-09-17 cache_refresh to 0 if debug, added a cookie_session-server for persis…
351
Something went wrong with that request. Please try again.