PageRenderTime 214ms CodeModel.GetById 101ms app.highlight 14ms RepoModel.GetById 96ms app.codeStats 1ms

/src/middleware/ewgi_session/ewgi_session_server.erl

http://github.com/skarab/ewgi
Erlang | 137 lines | 80 code | 30 blank | 27 comment | 1 complexity | ae313efd1c5bb1805be4d4c95577716e MD5 | raw file
  1%% @author Dave Bryson [http://weblog.miceda.org]
  2%% @author Davide Marquęs <nesrait@gmail.com>
  3%% @copyright Dave Bryson 2008-2009
  4%%
  5%% @doc Server-side session store.
  6%% Adapted from beepbeep_session_server by Dave Bryson.
  7%% All data is stored on the server.
  8%% Only a unique session id is exchanged with the client.
  9%% Inspired by the Yaws Session Server.
 10%% @end
 11%%
 12%% Licensed under the MIT license:
 13%% http://www.opensource.org/licenses/mit-license.php
 14
 15-module(ewgi_session_server).
 16-author('Dave Bryson <http://weblog.miceda.org>').
 17-author("Davide Marquęs <nesrait@gmail.com>").
 18
 19-behaviour(gen_server).
 20
 21-export([start_link/0, start_link/1, stop/1]).
 22-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
 23-export([get_session/2, save_new_session/2, save_session/3, delete_session/2]).
 24-export([purge_stale_sessions/1, purge_stale_sessions/2]).
 25
 26-include("session.hrl").
 27-include_lib("stdlib/include/ms_transform.hrl").
 28
 29%%====================================================================
 30%% API
 31%%====================================================================
 32%%--------------------------------------------------------------------
 33%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
 34%% Description: Starts and links the server
 35%%--------------------------------------------------------------------
 36start_link() ->
 37    start_link({local, ?MODULE}).
 38
 39start_link(Name) ->
 40    gen_server:start_link(Name, ?MODULE, [], []).
 41
 42stop(Server) ->
 43    gen_server:cast(Server, stop).
 44
 45get_session(Server, Sid) ->
 46    gen_server:call(Server, {get_session, Sid}).
 47
 48save_new_session(Server, Data) ->
 49    gen_server:call(Server, {save_new_session, Data}).
 50	
 51save_session(Server, Sid, Data) ->
 52    gen_server:call(Server, {save_session, Sid, Data}).
 53
 54delete_session(Server, Sid) ->
 55    gen_server:call(Server, {delete_session, Sid}).
 56
 57purge_stale_sessions(Timeout) ->
 58    purge_stale_sessions(?MODULE, Timeout).
 59
 60purge_stale_sessions(Server, Timeout) ->
 61    gen_server:call(Server, {purge_state_sessions, Timeout}).
 62
 63%%====================================================================
 64%% gen_server callbacks
 65%%====================================================================
 66init([]) ->
 67    ets:new(?MODULE, [set, named_table, {keypos, 1}]),
 68    {A1, A2, A3} = now(),
 69    random:seed(A1, A2, A3),
 70    {ok, undefined}.
 71
 72handle_call({get_session, Sid}, _From, _State) ->
 73    Data = case ets:lookup(?MODULE, Sid) of
 74	       [{_,Session}] ->
 75		   Session;
 76	       [] ->
 77		   undefined
 78	   end,
 79    {reply, Data, undefined};
 80
 81handle_call({save_new_session, Session}, _From, _State) ->
 82	NewSid = make_session_id(),	
 83    ets:insert(?MODULE, {NewSid,Session}),
 84    {reply, NewSid, undefined};
 85
 86handle_call({save_session, Sid, Session}, _From, _State) ->
 87    ets:insert(?MODULE, {Sid,Session}),
 88    {reply, ok, undefined};
 89
 90
 91handle_call({delete_session, Sid}, _From, _State) ->
 92    ets:delete(?MODULE, Sid),
 93    {reply, ok, undefined};
 94
 95handle_call({purge_state_sessions, Timeout}, _From, _State) ->
 96    MinCreationDate = ewgi_util_calendar:now_utc_ts_ms() - Timeout,
 97    Pattern =
 98	ets:fun2ms(fun({_,#session{timestamp=Timestamp}}=A) -> Timestamp =< MinCreationDate end),
 99    NumDeleted = ets:select_delete(?MODULE, Pattern),
100    {reply, {num_deleted, NumDeleted}, undefined}.
101
102handle_cast(stop, State) ->
103    {stop, normal, State};
104
105handle_cast(_Msg, State) ->
106    {noreply, State}.
107
108handle_info(_Info, State) ->
109    {noreply, State}.
110
111terminate(_Reason, _State) ->
112    ok.
113
114code_change(_OldVsn, State, _Extra) ->
115    {ok, State}.
116
117%%--------------------------------------------------------------------
118%%% Internal functions
119%%--------------------------------------------------------------------
120
121make_session_id() ->
122    Data = crypto:rand_bytes(2048),
123    Sha_list = binary_to_list(crypto:sha(Data)),
124    Id = lists:flatten(list_to_hex(Sha_list)),
125    Id.
126
127%% Convert Integer from the SHA to Hex
128list_to_hex(L)->
129	[int_to_hex(X) || X <- L].
130 
131int_to_hex(N) when N < 256 -> 
132	[hex(N div 16), hex(N rem 16)].
133 
134hex(N) when N < 10 ->
135       $0+N;
136hex(N) when N >= 10, N < 16 ->
137       $a + (N-10).