Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 352 lines (289 sloc) 11.246 kb
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
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
9a74e5a Claes Wikstrom Major general code cleanup, finally got rid of all the export_all statem...
authored
15 -export([start_link/0, start/0, stop/0]).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
16
17 %% gen_server callbacks
ca1c8b1 Mikael Karlsson Fixed a number of compiler warnings and html validation errors
karlsson authored
18 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
6e96a14 Claes Wikstrom indendation cleanup
authored
19 code_change/3]).
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
20
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
21 -include("../include/yaws_api.hrl").
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
22 -include("../include/yaws.hrl").
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
23
5f13a9c Claes Wikstrom Two patches by Joseph Wayen Norton, one dbg-bug and one providing better...
authored
24 -export([new_session/1,new_session/2,new_session/3,new_session/4,
9a74e5a Claes Wikstrom Major general code cleanup, finally got rid of all the export_all statem...
authored
25 cookieval_to_opaque/1,
26 print_sessions/0,
27 replace_session/2,
28 delete_session/1]).
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
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]).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
37
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
38 -define(TTL, (30 * 60)). % 30 minutes
39
40 -record(ysession,
0be3c7e Claes Wikstrom untabified all of yaws
authored
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
6964fff Claes Wikstrom modified patch by Robert David to add a hook to yaws session server when...
authored
45 cleanup, %% PID to notify of session end
0be3c7e Claes Wikstrom untabified all of yaws
authored
46 opaque %% any data the user supplies
47 }).
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
48
49 -record(state,
50 {backend %% storage engine module
51 }).
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
52
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
53
54 %%%----------------------------------------------------------------------
55 %%% API
56 %%%----------------------------------------------------------------------
57 start_link() ->
d2d461c Figuring out proper yaws_session_server backend.
Torbjorn Tornkvist authored
58 Backend = get_yaws_session_server_backend(),
455578a Steve Vinoski major trailing whitespace cleanup
vinoski authored
59 gen_server:start_link({local, yaws_session_server},
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
60 yaws_session_server, Backend, []).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
61 start() ->
d2d461c Figuring out proper yaws_session_server backend.
Torbjorn Tornkvist authored
62 Backend = get_yaws_session_server_backend(),
455578a Steve Vinoski major trailing whitespace cleanup
vinoski authored
63 gen_server:start({local, yaws_session_server},
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
64 yaws_session_server, Backend, []).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
65 stop() ->
aa815f2 Claes Wikstrom added a set of infinity to several gen_server:calls
authored
66 gen_server:call(?MODULE, stop, infinity).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
67
68
d2d461c Figuring out proper yaws_session_server backend.
Torbjorn Tornkvist authored
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
f43aa7d Claes Wikstrom correction
authored
77 {ok, true} ->
d2d461c Figuring out proper yaws_session_server backend.
Torbjorn Tornkvist authored
78 case application:get_env(yaws, embedded_conf) of
525846e Claes Wikstrom Some dialyzer fixes - no real bugs, just enhancements, removed the depre...
authored
79 {ok, L} when is_list(L) ->
d2d461c Figuring out proper yaws_session_server backend.
Torbjorn Tornkvist authored
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
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
95 %% will return a new cookie as a string
96 new_session(Opaque) ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
97 Call = {new_session, Opaque, ?TTL, undefined, undefined},
98 gen_server:call(?MODULE, Call, infinity).
13b21a9 Claes Wikstrom yaws_session_server ttl patch from Rob.Schmersel
authored
99
100 new_session(Opaque, TTL) ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
101 Call = {new_session, Opaque, TTL, undefined, undefined},
102 gen_server:call(?MODULE, Call, infinity).
6964fff Claes Wikstrom modified patch by Robert David to add a hook to yaws session server when...
authored
103
104 new_session(Opaque, TTL, Cleanup) ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
105 Call = {new_session, Opaque, TTL, Cleanup, undefined},
106 gen_server:call(?MODULE, Call, infinity).
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
107
5f13a9c Claes Wikstrom Two patches by Joseph Wayen Norton, one dbg-bug and one providing better...
authored
108 new_session(Opaque, TTL, Cleanup, Cookie) ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
109 Call = {new_session, Opaque, TTL, Cleanup, Cookie},
110 gen_server:call(?MODULE, Call, infinity).
6e96a14 Claes Wikstrom indendation cleanup
authored
111
5f13a9c Claes Wikstrom Two patches by Joseph Wayen Norton, one dbg-bug and one providing better...
authored
112 cookieval_to_opaque(Cookie) ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
113 gen_server:call(?MODULE, {cookieval_to_opaque, Cookie}, infinity).
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
114
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
115 print_sessions() ->
f73d23d Claes Wikstrom Fixed dialyzer bugs found by Tuncer, Issue #54
authored
116 gen_server:cast(?MODULE, print_sessions).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
117
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
118 replace_session(Cookie, NewOpaque) ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
119 gen_server:call(?MODULE, {replace_session, Cookie, NewOpaque}, infinity).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
120
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
121 delete_session(CookieVal) ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
122 gen_server:call(?MODULE, {delete_session, CookieVal}, infinity).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
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 %%----------------------------------------------------------------------
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
135 init(Backend) ->
136 Backend:init_backend(record_info(fields, ysession)),
f4867b8 Claes Wikstrom Better timeout support in yaws-session_server
authored
137 start_long_timer(),
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
138 {ok, #state{backend = Backend}, to()}.
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
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
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
150 handle_call({new_session, Opaque, undefined, Cleanup, Cookie}, From, State) ->
151 handle_call({new_session, Opaque, ?TTL, Cleanup, Cookie}, From, State);
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
152
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
153 handle_call({new_session, Opaque, TTL, Cleanup, undefined}, From, State) ->
b44aba6 Claes Wikstrom Use crypto:rand_bytes() instead of the cryptogrphicalli weak random modu...
authored
154 N = crypto:rand_bytes(16),
155 Cookie = atom_to_list(node()) ++ [$-|binary_to_list(N)],
5f13a9c Claes Wikstrom Two patches by Joseph Wayen Norton, one dbg-bug and one providing better...
authored
156 handle_call({new_session, Opaque, TTL, Cleanup, Cookie}, From, State);
157
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
158 handle_call({new_session, Opaque, TTL, Cleanup, Cookie}, _From, State) ->
5f13a9c Claes Wikstrom Two patches by Joseph Wayen Norton, one dbg-bug and one providing better...
authored
159 Now = gnow(),
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
160 TS = calendar:local_time(),
5f13a9c Claes Wikstrom Two patches by Joseph Wayen Norton, one dbg-bug and one providing better...
authored
161 NS = #ysession{cookie = Cookie,
0be3c7e Claes Wikstrom untabified all of yaws
authored
162 starttime = TS,
163 opaque = Opaque,
164 to = Now + TTL,
6964fff Claes Wikstrom modified patch by Robert David to add a hook to yaws session server when...
authored
165 ttl = TTL,
166 cleanup = Cleanup},
455578a Steve Vinoski major trailing whitespace cleanup
vinoski authored
167 Backend = State#state.backend,
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
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,
455578a Steve Vinoski major trailing whitespace cleanup
vinoski authored
186 Result =
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
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
455578a Steve Vinoski major trailing whitespace cleanup
vinoski authored
201 [Y] ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
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}.
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
212
213 %%----------------------------------------------------------------------
214 %% Func: handle_cast/2
215 %% Returns: {noreply, State} |
216 %% {noreply, State, Timeout} |
217 %% {stop, Reason, State} (terminate/2 is called)
218 %%----------------------------------------------------------------------
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
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
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
232 handle_cast(_Msg, State) ->
f4867b8 Claes Wikstrom Better timeout support in yaws-session_server
authored
233 {noreply, State, to()}.
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
234
235 %%----------------------------------------------------------------------
236 %% Func: handle_info/2
237 %% Returns: {noreply, State} |
238 %% {noreply, State, Timeout} |
239 %% {stop, Reason, State} (terminate/2 is called)
240 %%----------------------------------------------------------------------
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
241 handle_info(timeout, #state{backend = Backend} = State) ->
242 Backend:traverse(gnow()),
243 {noreply, State, to()};
f4867b8 Claes Wikstrom Better timeout support in yaws-session_server
authored
244
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
245 handle_info(long_timeout, #state{backend = Backend} = State) ->
246 Backend:traverse(gnow()),
f4867b8 Claes Wikstrom Better timeout support in yaws-session_server
authored
247 start_long_timer(),
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
248 {noreply, State, to()}.
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
249
250
251 %%----------------------------------------------------------------------
252 %% Func: terminate/2
253 %% Purpose: Shutdown the server
254 %% Returns: any (ignored by gen_server)
255 %%----------------------------------------------------------------------
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
256 terminate(_Reason, #state{backend = Backend}) ->
257 Backend:stop_backend(),
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
258 ok.
259
ca1c8b1 Mikael Karlsson Fixed a number of compiler warnings and html validation errors
karlsson authored
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
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
268 %%%----------------------------------------------------------------------
269 %%% Internal functions
270 %%%----------------------------------------------------------------------
271
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
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).
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
275
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
276 long_to() ->
277 60 * 60 * 1000.
278
279 %% timeout if the server is idle for more than 2 minutes.
280 to() ->
b44aba6 Claes Wikstrom Use crypto:rand_bytes() instead of the cryptogrphicalli weak random modu...
authored
281 2 * 60 * 1000.
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
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') ->
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
335 ok;
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
336 traverse(N, Key) ->
337 case lookup(Key) of
0be3c7e Claes Wikstrom untabified all of yaws
authored
338 [Y] ->
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
339 case has_timedout(Y, N) of
340 false ->
341 traverse(N, ets:next(?MODULE, Key));
0be3c7e Claes Wikstrom untabified all of yaws
authored
342 true ->
343 report_timedout_sess(Y),
344 Next = ets:next(?MODULE, Key),
c6f26aa Nicolas Thauvin Pluggable ysession storage with mnesia sample in src/contrib, part 2
nthauvin authored
345 delete(Key),
455578a Steve Vinoski major trailing whitespace cleanup
vinoski authored
346 traverse(N, Next)
0be3c7e Claes Wikstrom untabified all of yaws
authored
347 end;
348 [] ->
6e96a14 Claes Wikstrom indendation cleanup
authored
349 traverse(N, ets:next(?MODULE, Key))
87b1456 Claes Wikstrom wrote the shopppingcart example
authored
350 end.
80771c8 Claes Wikstrom cache_refresh to 0 if debug, added a cookie_session-server for persistan...
authored
351
Something went wrong with that request. Please try again.