Savarese Software Research Corporation
session/service.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WSPR_SESSION_SERVICE_H
00023 #define __SSRC_WSPR_SESSION_SERVICE_H
00024 
00025 #include <ssrc/wispers/index/DictionaryService.h>
00026 #include <ssrc/wispers/session/protocol.h>
00027 #include <ssrc/wispers/utility/RandomId.h>
00028 
00029 __BEGIN_NS_SSRC_WSPR_SESSION
00030 
00031 using NS_SSRC_WSPR_SERVICE::timeout_ptr;
00032 using NS_SSRC_WSPR_UTILITY::RandomId;
00033 
00034 struct SessionInitializer {
00035   unsigned int expirations_per_message;
00036   // These are in seconds.  For best results, max_idle_time should be
00037   // an integer multiple of poll_interval.
00038   unsigned int poll_interval;
00039   unsigned int max_idle_time;
00040   std::string checkpoint_path;
00041 
00042   SessionInitializer() :
00043     expirations_per_message(1024), poll_interval(300), max_idle_time(1800)
00044   { }
00045 };
00046 
00050 class Session : public DictionaryService<SessionProtocol> {
00051 public:
00052   WISP_IMPORT(SessionProtocol, MessageSingleQueryResult);
00053   WISP_IMPORT(SessionProtocol, MessageInsert);
00054   WISP_IMPORT(SessionProtocol, MessageCreateSession);
00055   WISP_IMPORT(SessionProtocol, MessageGetSession);
00056   WISP_IMPORT(SessionProtocol, MessageExpireSession);
00057   WISP_IMPORT(SessionProtocol, MessageSetAttributes);
00058   WISP_IMPORT(SessionProtocol, MessageUpdateSession);
00059   WISP_IMPORT(SessionProtocol, MessageLoginSession);
00060   WISP_IMPORT(SessionProtocol, MessageLogoutSession);
00061 
00062   WISP_IMPORT(SessionProtocol, CallExpireSession);
00063 
00064 private:
00065   struct TouchSession {
00066     idle_count_type idle_count;
00067 
00068     TouchSession(const idle_count_type idle_count) : idle_count(idle_count) { }
00069 
00070     void operator()(SessionData & session) {
00071       session.idle_count = idle_count;
00072     }
00073   };
00074 
00075   friend class NS_SSRC_WISP_SERVICE::ServiceProtocolProcessor<packing_traits>;
00076   typedef DictionaryService<SessionProtocol> super;
00077 
00078 
00079   const RandomId<std::int32_t> _random_id;
00080   const unsigned int _expirations_per_message;
00081   const sec_type _poll_interval;
00082   const sec_type _max_idle_time;
00083   idle_count_type _low_count;
00084   TouchSession _touch_session;
00085   timeout_ptr _poll_timeout;
00086   const std::string _checkpoint_path;
00087 
00088   void load_checkpoint(const std::string & filename)
00089     SSRC_DECL_THROW(std::runtime_error, boost::archive::archive_exception);
00090 
00091   void touch_session(const session_map::iterator & it) {
00092     if(it->idle_count != _touch_session.idle_count) {
00093       get_index<BySID>().modify(it, _touch_session);
00094     }
00095   }
00096 
00097   virtual void process_request(const MessageInsert & msg, const MessageInfo &);
00098 
00099   void process_request(const MessageCreateSession & msg,
00100                        const MessageInfo & msginfo);
00101 
00102   void process_request(const MessageGetSession & msg,
00103                        const MessageInfo & msginfo);
00104 
00105   void process_request(MessageSetAttributes & msg, const MessageInfo &);
00106 
00107   void update_session(const SessionData & update);
00108 
00109   void process_request(const MessageUpdateSession & msg, const MessageInfo &) {
00110     update_session(msg.session);
00111   }
00112 
00113   void process_request(const MessageLoginSession & msg, const MessageInfo &) {
00114     update_session(msg.session);
00115   }
00116 
00117   void process_request(const MessageLogoutSession & msg, const MessageInfo &);
00118 
00122   void check_for_expirations() {
00123     // We don't worry about wraparound effects because the process will never
00124     // run long enough for wraparound even at a poll interval of one second.
00125     // Still, it's easy enough to handle if we have to.
00126     expire_sessions(_low_count);
00127     ++_low_count;
00128     ++_touch_session.idle_count;
00129   }
00130 
00131   virtual void transition(State state);
00132 
00133 public:
00134 
00135   Session(super::caller_type & caller, const SessionInitializer & initializer)
00136     SSRC_DECL_THROW(std::runtime_error, boost::archive::archive_exception);
00137 
00138   virtual ~Session() { }
00139 
00140   string create_sid();
00141 
00142   string create_xsrf_token() {
00143     return _random_id(SessionIdNumChars);
00144   }
00145 
00149   std::pair<session_map::iterator, bool> create_session() {
00150     return
00151       insert<BySID>(SessionData(create_sid(), create_xsrf_token(),
00152                                 _touch_session.idle_count));
00153   }
00154 
00155   void expire_sessions(const idle_count_type low_count);
00156 
00157 };
00158 
00159 __END_NS_SSRC_WSPR_SESSION
00160 
00161 #endif

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.