// --------------------------------------------------------------------------- // - Session.cpp - // - afnix:nwg module - http session class implementation - // --------------------------------------------------------------------------- // - This program is free software; you can redistribute it and/or modify - // - it provided that this copyright notice is kept intact. - // - - // - This program is distributed in the hope that it will be useful, but - // - without any warranty; without even the implied warranty of - // - merchantability or fitness for a particular purpose. In no event shall - // - the copyright holder be liable for any direct, indirect, incidental or - // - special damages arising in any way out of the use of this software. - // --------------------------------------------------------------------------- // - copyright (c) 1999-2007 amaury darsch - // --------------------------------------------------------------------------- #include "Sha1.hpp" #include "Time.hpp" #include "Nwgsid.hxx" #include "Vector.hpp" #include "System.hpp" #include "Session.hpp" #include "Integer.hpp" #include "Boolean.hpp" #include "QuarkZone.hpp" #include "Exception.hpp" namespace afnix { // ------------------------------------------------------------------------- // - private section - // ------------------------------------------------------------------------- // this procedure returns a new session for deserialization static Serial* mksob (void) { return new Session; } // register this session serial id static const t_byte SERIAL_ID = Serial::setsid (SERIAL_SESS_ID, mksob); // this procedure compute the session id with the help of an hasher object // the SHA-1 hasher object is used by operating on the session name static String get_session_id (const String& name) { // create the SHA-1 object Sha1 hasher; // get the result return hasher.compute (name); } // serialize an integer to an output stream static inline void wrs_integer (const t_long value, Output& os) { Integer iobj (value); iobj.wrstream (os); } // deserialize an integer static inline t_long rds_integer (Input& is) { Integer iobj; iobj.rdstream (is); return iobj.tointeger (); } // ------------------------------------------------------------------------- // - class section - // ------------------------------------------------------------------------- // create an empty session Session::Session (void) { d_path = System::tempnam (); d_expt = 0; } // create a session by name Session::Session (const String& name) { d_name = name; d_user = name; d_id = get_session_id (d_name); d_path = System::tempnam (); d_expt = 0; } // create a session by name and user Session::Session (const String& name, const String& user) { d_name = name; d_user = user; d_id = get_session_id (d_name); d_path = System::tempnam (); d_expt = 0; } // create a session by name, user and path Session::Session (const String& name, const String& user, const String& path) { d_name = name; d_user = user; d_id = get_session_id (d_name); d_path = path; d_expt = 0; } // return the class name String Session::repr (void) const { return "Session"; } // return the session serial code t_byte Session::serialid (void) const { return SERIAL_SESS_ID; } // serialize this session void Session::wrstream (Output& os) const { rdlock (); try { d_name.wrstream (os); d_user.wrstream (os); d_id.wrstream (os); wrs_integer (d_expt, os); unlock (); } catch (...) { unlock (); throw; } } // deserialize this session void Session::rdstream (Input& is) { wrlock (); d_name.rdstream (is); d_user.rdstream (is); d_id.rdstream (is); d_expt = rds_integer (is); unlock (); } // get the session name String Session::getname (void) const { rdlock (); String result = d_name; unlock (); return result; } // get the session id String Session::getid (void) const { rdlock (); String result = d_id; unlock (); return result; } // set the session user void Session::setuser (const String& user) { wrlock (); d_user = user; unlock (); } // get the session user String Session::getuser (void) const { rdlock (); String result = d_user; unlock (); return result; } // set the session path void Session::setpath (const String& path) { wrlock (); d_path = path; unlock (); } // get the session path String Session::getpath (void) const { rdlock (); String result = d_path; unlock (); return result; } // return true if the session has expired bool Session::isexpt (void) const { rdlock (); try { // get the current time t_long ctim = Time::gettclk (); // check for expiration bool result = d_expt == 0 ? false : (d_expt <= ctim); unlock (); return result; } catch (...) { unlock (); throw; } } // set the session expiration time void Session::setexpt (const t_long time) { wrlock (); d_expt = time; unlock (); } // get the session expiration time t_long Session::getexpt (void) const { rdlock (); t_long result = d_expt; unlock (); return result; } // set the session maximum age void Session::setmage (const t_long mage) { wrlock (); try { d_expt = Time::gettclk () + mage; unlock (); } catch (...) { unlock (); throw; } } // get the session valid remaining time t_long Session::getvldt (void) const { rdlock (); try { // get the current time t_long ctim = Time::gettclk (); // compute remaining time t_long vldt = (d_expt == 0) ? 0 : d_expt - ctim; if (vldt < 0) vldt = 0; // unlock and return unlock (); return vldt; } catch (...) { unlock (); throw; } } // ------------------------------------------------------------------------- // - object section - // ------------------------------------------------------------------------- // the quark zone static const long QUARK_ZONE_LENGTH = 11; static QuarkZone zone (QUARK_ZONE_LENGTH); // the object supported quarks static const long QUARK_GETID = zone.intern ("get-id"); static const long QUARK_EXPTP = zone.intern ("expire-p"); static const long QUARK_GETNAME = zone.intern ("get-name"); static const long QUARK_GETUSER = zone.intern ("get-user"); static const long QUARK_SETUSER = zone.intern ("set-user"); static const long QUARK_GETPATH = zone.intern ("get-path"); static const long QUARK_SETPATH = zone.intern ("set-path"); static const long QUARK_SETMAGE = zone.intern ("set-max-age"); static const long QUARK_GETVLDT = zone.intern ("get-valid-time"); static const long QUARK_SETEXPT = zone.intern ("set-expire-time"); static const long QUARK_GETEXPT = zone.intern ("get-expire-time"); // create a new object in a generic way Object* Session::mknew (Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); // check for 1 argument if (argc == 1) { String name = argv->getstring (0); return new Session (name); } // check for 2 arguments if (argc == 2) { String name = argv->getstring (0); String user = argv->getstring (1); return new Session (name, user); } // check for 3 arguments if (argc == 3) { String name = argv->getstring (0); String user = argv->getstring (1); String path = argv->getstring (2); return new Session (name, user, path); } // invalid arguments throw Exception ("argument-error", "invalid arguments with session"); } // return true if the given quark is defined bool Session::isquark (const long quark, const bool hflg) const { rdlock (); if (zone.exists (quark) == true) { unlock (); return true; } bool result = hflg ? Object::isquark (quark, hflg) : false; unlock (); return result; } // apply this object with a set of arguments and a quark Object* Session::apply (Runnable* robj, Nameset* nset, const long quark, Vector* argv) { // get the number of arguments long argc = (argv == nilp) ? 0 : argv->length (); // dispatch 0 argument if (argc == 0) { if (quark == QUARK_GETID) return new String (getid ()); if (quark == QUARK_EXPTP) return new Boolean (isexpt ()); if (quark == QUARK_GETNAME) return new String (getname ()); if (quark == QUARK_GETUSER) return new String (getuser ()); if (quark == QUARK_GETPATH) return new String (getpath ()); if (quark == QUARK_GETEXPT) return new Integer (getexpt ()); if (quark == QUARK_GETVLDT) return new Integer (getvldt ()); } // dispatch 1 argument if (argc == 1) { if (quark == QUARK_SETUSER) { String user = argv->getstring (0); setuser (user); return nilp; } if (quark == QUARK_SETPATH) { String path = argv->getstring (0); setpath (path); return nilp; } if (quark == QUARK_SETEXPT) { t_long expt = argv->getint (0); setexpt (expt); return nilp; } if (quark == QUARK_SETMAGE) { t_long mage = argv->getint (0); setmage (mage); return nilp; } } // call the object method return Object::apply (robj, nset, quark, argv); } }