rewritten: sessions management

(Session, SessionContainer, SessionManager)
           now a Session object don't copy all fields in its copy constructor (only id)
           the rest fields are set after the object is inserted in SessionContainer
added:     after successfully login a session id is changed
added:     plugin.Call() methods with a first argument a pointer to a Session object



git-svn-id: svn://ttmath.org/publicrep/winix/trunk@823 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2012-03-17 05:11:23 +00:00
parent 70421b7bd1
commit e83fd91423
25 changed files with 444 additions and 183 deletions

View File

@@ -108,18 +108,15 @@ return id;
void SessionManager::CreateSession()
{
int attempts = 100;
bool added = false;
new_session.SetTimeToNow();
new_session.Clear();
int attempts = 100;
SessionContainer::Iterator i = session_tab.End();
if( config->session_max == 0 || session_tab.Size() < config->session_max )
{
for( ; !added && attempts > 0 ; --attempts )
for( ; i == session_tab.End() && attempts > 0 ; --attempts )
{
new_session.id = CreateSessionId();
added = session_tab.PushBack(new_session);
long id = CreateSessionId();
i = session_tab.AddSession(id);
}
}
else
@@ -127,10 +124,12 @@ bool added = false;
log << log2 << "SM: sessions limit exceeded (" << config->session_max << ")" << logend;
}
if( added )
if( i != session_tab.End() )
{
session = &session_tab.Back();
session = &(*i);
session->new_session = true;
session->SetTimeToNow();
log << log2 << "SM: created a new session: " << session->id << logend;
}
else
@@ -138,8 +137,8 @@ bool added = false;
// there is a problem with generating a new session id
// we do not set a session cookie
session = &temporary_session;
session->Clear(false);
session->SetTimeToNow();
session->Clear(); // !! uwaga ten Clear wyczysci plugins data
session->new_session = false; // temporary session was initialized at the beginning
log << log1 << "SM: cannot create a session id (temporary used: with id 0)" << logend;
}
@@ -226,8 +225,7 @@ void SessionManager::DeleteSessions()
{
if( i->puser && !i->remember_me )
{
cur->session = &(*i); // for correctly setting a session data in plugins
plugin.Call(WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin.Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
last_container->UserLogout(i->puser->id, i->id);
}
}
@@ -237,6 +235,41 @@ void SessionManager::DeleteSessions()
/*
don't change a session's id when a user is logged
the session id is in last_container and the user would not be
correctly removed from the container
*/
bool SessionManager::ChangeSessionId(long old_id)
{
int attempts = 100;
bool changed = false;
long new_id;
SessionContainer::Iterator i = session_tab.FindById(old_id);
if( i != session_tab.End() )
{
for( ; !changed && attempts > 0 ; --attempts )
{
new_id = CreateSessionId();
changed = session_tab.ChangeSessionId(i, new_id);
}
if( changed )
plugin.Call(&(*i), WINIX_SESSION_CHANGED_ID, old_id, new_id);
else
log << log1 << "SM: I cannot create a new session id (still uses old one)" << logend;
}
else
{
log << log2 << "SM: there is no a session with id: " << old_id << logend;
}
return changed;
}
void SessionManager::InitTmpSession()
{
Session * old_session = cur->session;
@@ -256,7 +289,7 @@ void SessionManager::UninitTmpSession()
log << log4 << "SM: uninitializing temporary session" << logend;
cur->session = &temporary_session;
cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_SESSION_REMOVE);
cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_PLUGIN_SESSION_DATA_REMOVE);
cur->session->plugin_data.Resize(0);
cur->session = old_session;
@@ -278,11 +311,15 @@ SessionContainer::Iterator i;
for(i=session_tab.Begin() ; i != session_tab.End() ; ++i)
{
i->plugin_data.Resize(plugin.Size());
cur->session = &(*i);
plugin.Call(WINIX_SESSION_CREATED);
plugin.Call(&(*i), WINIX_SESSION_CREATED);
if( cur->session->puser )
plugin.Call(WINIX_USER_LOGGED);
/*
!! IMPROVE ME
we do not add it to the last_container (we don't have IP address stored yet)
*/
if( i->puser )
plugin.Call(&(*i), WINIX_USER_LOGGED);
}
cur->session = &temporary_session;
@@ -347,14 +384,12 @@ size_t SessionManager::MarkAllSessionsToRemove(long user_id)
{
size_t how_many = 0;
SessionContainer::Iterator i;
Session * old_session = cur->session;
for(i=session_tab.Begin() ; i!=session_tab.End() ; ++i)
{
if( i->puser && i->puser->id == user_id )
{
cur->session = &(*i); // for correctly setting a session data in plugins
plugin.Call(WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin.Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
last_container->UserLogout(i->puser->id, i->id);
i->remove_me = true;
i->puser = 0;
@@ -362,8 +397,6 @@ size_t SessionManager::MarkAllSessionsToRemove(long user_id)
}
}
cur->session = old_session;
return how_many;
}
@@ -374,18 +407,20 @@ return how_many;
*
*
* sessions gc (second thread)
*
* sessions are only removed here
* SessionContainer::IndexId can be removed from the other thread
* (when ChangeSessionId() method is called)
*
*/
void SessionManager::Work()
{
bool exit = false;
SessionContainer::IndexId::iterator i;
SessionContainer::Iterator i;
deleted = 0;
Lock();
i = session_tab.IdBegin();
i = session_tab.Begin();
Unlock();
while( !exit )
@@ -401,11 +436,11 @@ SessionContainer::IndexId::iterator i;
// it's called from the other thread (with Lock and Unlock)
void SessionManager::CheckSession(SessionContainer::IndexId::iterator & i)
void SessionManager::CheckSession(SessionContainer::Iterator & i)
{
const int deleted_max_at_once = 10;
if( i == session_tab.IdEnd() )
if( i == session_tab.End() )
{
if( deleted > 0 )
{
@@ -413,14 +448,16 @@ const int deleted_max_at_once = 10;
log << logsave;
}
i = session_tab.IdBegin();
i = session_tab.Begin();
WaitForSignalSleep(10);
}
else
{
if( i->second->remove_me || IsSessionOutdated(*i->second) )
if( i->remove_me || IsSessionOutdated(*i) )
{
DeleteSession(i++);
Session * ses = &(*i);
++i;
DeleteSession(ses);
++deleted;
}
else
@@ -444,9 +481,13 @@ bool SessionManager::IsSessionOutdated(const Session & s) const
bool outdated;
if( s.remember_me )
{
outdated = s.last_time < std::time(0) - config->session_remember_max_idle;
}
else
{
outdated = s.last_time < std::time(0) - config->session_max_idle;
}
return outdated;
}
@@ -454,14 +495,16 @@ return outdated;
// it's called from the other thread (with Lock and Unlock)
void SessionManager::DeleteSession(SessionContainer::IdIterator i)
void SessionManager::DeleteSession(Session * del_session)
{
Session * del_session = &(*i->second);
if( del_session->puser )
{
plugin.Call(del_session, WINIX_PREPARE_USER_TO_LOGOUT, del_session->puser);
last_container->UserLogout(del_session->puser->id, del_session->id);
del_session->puser = 0;
}
session_tab.EraseById(i);
session_tab.EraseById(del_session->id);
}