PageRenderTime 155ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/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
Possible License(s): MPL-2.0-no-copyleft-exception
  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. -module(ewgi_session_server).
  15. -author('Dave Bryson <http://weblog.miceda.org>').
  16. -author("Davide Marquęs <nesrait@gmail.com>").
  17. -behaviour(gen_server).
  18. -export([start_link/0, start_link/1, stop/1]).
  19. -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
  20. -export([get_session/2, save_new_session/2, save_session/3, delete_session/2]).
  21. -export([purge_stale_sessions/1, purge_stale_sessions/2]).
  22. -include("session.hrl").
  23. -include_lib("stdlib/include/ms_transform.hrl").
  24. %%====================================================================
  25. %% API
  26. %%====================================================================
  27. %%--------------------------------------------------------------------
  28. %% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
  29. %% Description: Starts and links the server
  30. %%--------------------------------------------------------------------
  31. start_link() ->
  32. start_link({local, ?MODULE}).
  33. start_link(Name) ->
  34. gen_server:start_link(Name, ?MODULE, [], []).
  35. stop(Server) ->
  36. gen_server:cast(Server, stop).
  37. get_session(Server, Sid) ->
  38. gen_server:call(Server, {get_session, Sid}).
  39. save_new_session(Server, Data) ->
  40. gen_server:call(Server, {save_new_session, Data}).
  41. save_session(Server, Sid, Data) ->
  42. gen_server:call(Server, {save_session, Sid, Data}).
  43. delete_session(Server, Sid) ->
  44. gen_server:call(Server, {delete_session, Sid}).
  45. purge_stale_sessions(Timeout) ->
  46. purge_stale_sessions(?MODULE, Timeout).
  47. purge_stale_sessions(Server, Timeout) ->
  48. gen_server:call(Server, {purge_state_sessions, Timeout}).
  49. %%====================================================================
  50. %% gen_server callbacks
  51. %%====================================================================
  52. init([]) ->
  53. ets:new(?MODULE, [set, named_table, {keypos, 1}]),
  54. {A1, A2, A3} = now(),
  55. random:seed(A1, A2, A3),
  56. {ok, undefined}.
  57. handle_call({get_session, Sid}, _From, _State) ->
  58. Data = case ets:lookup(?MODULE, Sid) of
  59. [{_,Session}] ->
  60. Session;
  61. [] ->
  62. undefined
  63. end,
  64. {reply, Data, undefined};
  65. handle_call({save_new_session, Session}, _From, _State) ->
  66. NewSid = make_session_id(),
  67. ets:insert(?MODULE, {NewSid,Session}),
  68. {reply, NewSid, undefined};
  69. handle_call({save_session, Sid, Session}, _From, _State) ->
  70. ets:insert(?MODULE, {Sid,Session}),
  71. {reply, ok, undefined};
  72. handle_call({delete_session, Sid}, _From, _State) ->
  73. ets:delete(?MODULE, Sid),
  74. {reply, ok, undefined};
  75. handle_call({purge_state_sessions, Timeout}, _From, _State) ->
  76. MinCreationDate = ewgi_util_calendar:now_utc_ts_ms() - Timeout,
  77. Pattern =
  78. ets:fun2ms(fun({_,#session{timestamp=Timestamp}}=A) -> Timestamp =< MinCreationDate end),
  79. NumDeleted = ets:select_delete(?MODULE, Pattern),
  80. {reply, {num_deleted, NumDeleted}, undefined}.
  81. handle_cast(stop, State) ->
  82. {stop, normal, State};
  83. handle_cast(_Msg, State) ->
  84. {noreply, State}.
  85. handle_info(_Info, State) ->
  86. {noreply, State}.
  87. terminate(_Reason, _State) ->
  88. ok.
  89. code_change(_OldVsn, State, _Extra) ->
  90. {ok, State}.
  91. %%--------------------------------------------------------------------
  92. %%% Internal functions
  93. %%--------------------------------------------------------------------
  94. make_session_id() ->
  95. Data = crypto:rand_bytes(2048),
  96. Sha_list = binary_to_list(crypto:sha(Data)),
  97. Id = lists:flatten(list_to_hex(Sha_list)),
  98. Id.
  99. %% Convert Integer from the SHA to Hex
  100. list_to_hex(L)->
  101. [int_to_hex(X) || X <- L].
  102. int_to_hex(N) when N < 256 ->
  103. [hex(N div 16), hex(N rem 16)].
  104. hex(N) when N < 10 ->
  105. $0+N;
  106. hex(N) when N >= 10, N < 16 ->
  107. $a + (N-10).