/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011-2016 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
**************************************************************************/
#include "vld.h"
#include
#include "SessionMgr.h"
#include "Server.h"
#include "stringtools.h"
#include
CSessionMgr::CSessionMgr(void)
{
sess_mutex=Server->createMutex();
sess_cond = Server->createCondition();
wait_cond=Server->createCondition();
wait_mutex=Server->createMutex();
stop_mutex=Server->createMutex();
stop_cond=Server->createCondition();
SESSIONID_LEN=30;//Server->Settings->getValue("SESSIONID_LEN",15);
SESSION_TIMEOUT_S=1800;//Server->Settings->getValue("SESSION_TIMEOUT_S",600);
for(unsigned char i=48;i<58;++i)
Pool.push_back(i);
for(unsigned char i=65;i<91;++i)
Pool.push_back(i);
for(unsigned char i=97;i<122;++i)
Pool.push_back(i);
run=false;
}
CSessionMgr::~CSessionMgr()
{
{
IScopedLock lock( sess_mutex );
Server->Log("removing sessions...");
if(!mSessions.empty() )
{
std::vector sesids;
for(std::map::iterator i=mSessions.begin();i!=mSessions.end();++i)
{
sesids.push_back(i->first);
}
lock.relock(NULL);
for(size_t i=0;iLog("done.");
}
if(run)
{
IScopedLock slock(stop_mutex);
Server->Log("waiting for sessionmgr...");
run=false;
wait_cond->notify_all();
stop_cond->wait(&slock);
Server->Log("done.");
}
Server->destroy(sess_mutex);
Server->destroy(sess_cond);
Server->destroy(wait_mutex);
Server->destroy(stop_mutex);
Server->destroy(wait_cond);
Server->destroy(stop_cond);
}
void CSessionMgr::startTimeoutSessionThread()
{
run=true;
Server->createThread(this, "session timeouts");
}
std::string CSessionMgr::GenerateSessionIDWithUser(const std::string &pUsername, const std::string &pIdentData, bool update_user)
{
std::string ret;
ret.resize(SESSIONID_LEN);
std::vector rnd_n=Server->getSecureRandomNumbers(SESSIONID_LEN);
for(int i=0;i to_remove;
for(std::map::iterator i=mSessions.begin();i!=mSessions.end();++i)
{
if( i->second->username==pUsername )
{
to_remove.push_back(i->first);
}
}
lock.relock(NULL);
for(size_t i=0;iusername=pUsername;
user->session=ret;
user->ident_data=pIdentData;
user->id=-1;
user->lastused=Server->getTimeMS();
user->waitlock = 0;
user->refcount = 0;
mSessions.insert(std::pair(ret, user) );
return ret;
}
SUser *CSessionMgr::getUser(const std::string &pSID, const std::string &pIdentData, bool update)
{
IScopedLock lock( sess_mutex );
std::map::iterator i=mSessions.find(pSID);
if( i!=mSessions.end() )
{
if( i->second->ident_data!=pIdentData )
return NULL;
SUser* user = i->second;
++user->refcount;
while (user->waitlock > 0)
{
sess_cond->wait(&lock);
}
++user->waitlock;
if( update )
user->lastused=Server->getTimeMS();
return user;
}
else
return NULL;
}
void CSessionMgr::releaseUser(SUser *user)
{
if( user!=NULL )
{
IScopedLock lock(sess_mutex);
assert(user->refcount > 0);
--user->refcount;
assert(user->waitlock > 0);
--user->waitlock;
if (user->refcount > 0)
{
sess_cond->notify_all();
}
}
}
void CSessionMgr::unlockUser(SUser * user)
{
if (user != NULL)
{
IScopedLock lock(sess_mutex);
assert(user->waitlock > 0);
--user->waitlock;
if (user->refcount > 1)
{
sess_cond->notify_all();
}
}
}
void CSessionMgr::lockUser(SUser *user)
{
if( user!=NULL )
{
IScopedLock lock(sess_mutex);
while (user->waitlock > 0)
{
sess_cond->wait(&lock);
}
++user->waitlock;
}
}
bool CSessionMgr::RemoveSession(const std::string &pSID)
{
IScopedLock lock( sess_mutex );
std::map::iterator i=mSessions.find(pSID);
if( i!=mSessions.end() )
{
SUser* user=i->second;
if (user->refcount>0)
{
return false;
}
assert(user->waitlock == 0);
mSessions.erase(i);
lock.relock(NULL);
for(std::map::iterator iter=user->mCustom.begin();
iter!=user->mCustom.end();++iter)
{
iter->second->Remove();
}
delete user;
return true;
}
else
return false;
}
unsigned int CSessionMgr::TimeoutSessions(void)
{
if(Server!=NULL)
Server->Log("Looking for old Sessions... "+convert(mSessions.size())+" sessions", LL_INFO);
unsigned int ret=0;
IScopedLock lock( sess_mutex );
int64 ttime=Server->getTimeMS();
std::vector to_timeout;
for(std::map::iterator i=mSessions.begin();i!=mSessions.end();++i)
{
int64 diff=ttime-i->second->lastused;
if( diff > (unsigned int)(SESSION_TIMEOUT_S)*1000 )
{
Server->Log("Session timeout: Session "+i->first, LL_INFO);
to_timeout.push_back(i->first);
}
else
{
ret=static_cast((std::max)(diff, static_cast(ret)));
}
}
lock.relock(NULL);
for(size_t i=0;iwait(&lock, wtime);
}
}
IScopedLock slock(stop_mutex);
stop_cond->notify_one();
}