time out empty webconference rooms. fixes SEMS-35

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1169 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 17 years ago
parent 61c0d81569
commit dfac67bbad

@ -1,5 +1,7 @@
#include "RoomInfo.h"
#include "WebConference.h"
#include <string.h>
#include "log.h"
@ -11,10 +13,13 @@ bool ConferenceRoomParticipant::expired(const struct timeval& now) {
if (Finished != status)
return false;
if (WebConferenceFactory::ParticipantExpiredDelay < 0)
return false;
struct timeval diff;
timersub(&now,&last_access_time,&diff);
return (diff.tv_sec > 0) &&
(unsigned int)diff.tv_sec > PARTICIPANT_EXPIRED_DELAY;
(unsigned int)diff.tv_sec > (unsigned int)WebConferenceFactory::ParticipantExpiredDelay;
}
AmArg ConferenceRoomParticipant::asArgArray() {
@ -33,26 +38,34 @@ void ConferenceRoomParticipant::setMuted(int mute) {
void ConferenceRoomParticipant::updateStatus(ConferenceRoomParticipant::ParticipantStatus
new_status,
const string& reason) {
const string& reason,
struct timeval& now) {
status = new_status;
last_reason = reason;
struct timeval now;
gettimeofday(&now, NULL);
updateAccess(now);
}
ConferenceRoom::ConferenceRoom() {
gettimeofday(&last_access_time, NULL);
}
void ConferenceRoom::cleanExpired() {
struct timeval now;
gettimeofday(&now, NULL);
gettimeofday(&now, NULL);
bool is_updated = false;
list<ConferenceRoomParticipant>::iterator it=participants.begin();
while (it != participants.end()) {
if (it->expired(now)) {
participants.erase(it);
it=participants.begin();
is_updated = true;
} else
it++;
}
if (is_updated)
memcpy(&last_access_time, &now, sizeof(struct timeval));
}
AmArg ConferenceRoom::asArgArray() {
@ -69,6 +82,8 @@ AmArg ConferenceRoom::asArgArray() {
void ConferenceRoom::newParticipant(const string& localtag,
const string& number) {
gettimeofday(&last_access_time, NULL);
participants.push_back(ConferenceRoomParticipant());
participants.back().localtag = localtag;
participants.back().number = number;
@ -87,6 +102,8 @@ bool ConferenceRoom::hasParticipant(const string& localtag) {
}
void ConferenceRoom::setMuted(const string& localtag, int mute) {
gettimeofday(&last_access_time, NULL);
for (list<ConferenceRoomParticipant>::iterator it =participants.begin();
it != participants.end();it++)
if (it->localtag == localtag) {
@ -98,11 +115,13 @@ void ConferenceRoom::setMuted(const string& localtag, int mute) {
bool ConferenceRoom::updateStatus(const string& part_tag,
ConferenceRoomParticipant::ParticipantStatus newstatus,
const string& reason) {
gettimeofday(&last_access_time, NULL);
bool res = false;
for (list<ConferenceRoomParticipant>::iterator it=participants.begin();
it != participants.end(); it++) {
if (it->localtag == part_tag) {
it->updateStatus(newstatus, reason);
it->updateStatus(newstatus, reason, last_access_time);
res = true;
break;
}
@ -112,3 +131,21 @@ bool ConferenceRoom::updateStatus(const string& part_tag,
return res;
}
bool ConferenceRoom::expired() {
struct timeval now;
gettimeofday(&now, NULL);
return expired(now);
}
bool ConferenceRoom::expired(const struct timeval& now) {
if (!participants.empty())
return false;
if (WebConferenceFactory::RoomExpiredDelay < 0)
return false;
struct timeval diff;
timersub(&now,&last_access_time,&diff);
return (diff.tv_sec > 0) &&
(unsigned int)diff.tv_sec > (unsigned int)WebConferenceFactory::RoomExpiredDelay;
}

@ -14,8 +14,6 @@ using std::list;
#include "AmArg.h"
#include "AmThread.h"
#define PARTICIPANT_EXPIRED_DELAY 10
struct ConferenceRoomParticipant {
enum ParticipantStatus {
Disconnected = 0,
@ -44,7 +42,8 @@ struct ConferenceRoomParticipant {
inline bool expired(const struct timeval& now);
inline void updateStatus(ParticipantStatus new_status,
const string& reason);
const string& reason,
struct timeval& now);
inline void setMuted(int mute);
@ -54,9 +53,11 @@ struct ConferenceRoomParticipant {
struct ConferenceRoom {
string adminpin;
struct timeval last_access_time;
list<ConferenceRoomParticipant> participants;
ConferenceRoom() { }
ConferenceRoom();
~ConferenceRoom() { }
void cleanExpired();
@ -72,6 +73,9 @@ struct ConferenceRoom {
bool hasParticipant(const string& localtag);
void setMuted(const string& localtag, int mute);
bool expired(const struct timeval& now);
bool expired();
};

@ -66,6 +66,10 @@ string WebConferenceFactory::urlbase = "";
string WebConferenceFactory::MasterPassword;
int WebConferenceFactory::ParticipantExpiredDelay;
int WebConferenceFactory::RoomExpiredDelay;
int WebConferenceFactory::RoomSweepInterval;
int WebConferenceFactory::onLoad()
{
// only execute this once
@ -158,8 +162,24 @@ int WebConferenceFactory::onLoad()
MasterPassword = cfg.getParameter("master_password");
if (!MasterPassword.empty()) {
DBG("Master password set.\n");
}
if (cfg.getParameter("participants_expire") == "no") {
ParticipantExpiredDelay = -1;
} else {
// default: 10s
ParticipantExpiredDelay = cfg.getParameterInt("participants_expire_delay", 10);
}
if (cfg.getParameter("rooms_expire") == "no") {
RoomExpiredDelay = -1;
} else {
RoomExpiredDelay = cfg.getParameterInt("rooms_expire_delay", 7200); // default: 2h
}
// default: every 10 times
RoomSweepInterval = cfg.getParameterInt("room_sweep_interval", 10);
return 0;
}
@ -208,6 +228,12 @@ ConferenceRoom* WebConferenceFactory::getRoom(const string& room,
if (it->second.adminpin.empty())
it->second.adminpin = adminpin;
res = &it->second;
if (res->expired()) {
DBG("clearing expired room '%s'\n", room.c_str());
rooms.erase(it);
res = NULL;
}
}
}
@ -368,10 +394,34 @@ string WebConferenceFactory::getRandomPin() {
return res;
}
// possibly clear expired rooms. OJO: lock rooms_mut !
void WebConferenceFactory::sweepRooms() {
if ((RoomSweepInterval>0) && (!((++room_sweep_cnt)%RoomSweepInterval))) {
struct timeval now;
gettimeofday(&now, NULL);
map<string, ConferenceRoom>::iterator it=rooms.begin();
while (it != rooms.end()) {
if (it->second.expired(now)) {
map<string, ConferenceRoom>::iterator d_it = it;
it++;
DBG("clearing expired room '%s'\n", d_it->first.c_str());
rooms.erase(d_it);
} else {
it++;
}
}
}
}
void WebConferenceFactory::roomCreate(const AmArg& args, AmArg& ret) {
assertArgCStr(args.get(0));
string room = args.get(0).asCStr();
rooms_mut.lock();
// sweep rooms (if necessary)
sweepRooms();
map<string, ConferenceRoom>::iterator it = rooms.find(room);
if (it == rooms.end()) {
rooms[room] = ConferenceRoom();
@ -451,6 +501,10 @@ void WebConferenceFactory::dialout(const AmArg& args, AmArg& ret) {
// check adminpin
rooms_mut.lock();
// sweep rooms (if necessary)
sweepRooms();
ConferenceRoom* r = getRoom(room, adminpin);
rooms_mut.unlock();
if (NULL == r) {

@ -80,6 +80,8 @@ class WebConferenceFactory
map<string, ConferenceRoom> rooms;
AmMutex rooms_mut;
int room_sweep_cnt;
// for DI
static WebConferenceFactory* _instance;
bool configured;
@ -105,11 +107,17 @@ class WebConferenceFactory
// for access of dialog to its url
string getAdminpin(const string& room);
void sweepRooms();
public:
static string DigitsDir;
static PlayoutType m_PlayoutType;
static string urlbase;
static string MasterPassword;
static int ParticipantExpiredDelay;
static int RoomExpiredDelay;
static int RoomSweepInterval;
WebConferenceFactory(const string& _app_name);
AmSession* onInvite(const AmSipRequest&);

@ -56,3 +56,44 @@ stats_dir=/var/log/sems-webconference/
#
#webconference_urlbase=https://webconference.iptel.org/openRoom.py?action=openRoom
#
# participants_expire = [yes | no]
#
# if set to no, participants do not expire from conference rooms
#
# default:
# participants_expire=yes
# delay after which a participant whose call has ended is removed from the
# conference room view. Only active if participants_expire=yes
#
# default:
# participants_expire_delay = 10
#
#
# rooms_expire = [yes | no]
#
# if set to no, empty rooms do not expire
#
# default:
# rooms_expire=yes
# delay after which an empty room vanishes, in seconds.
# Only active if rooms_expire=yes
#
# default:
# rooms_expire_delay=7200
#
# Only active if rooms_expire=yes
#
# default:
# rooms_expire_delay=7200
#
# look for expired conference rooms every n times, createRoom
# or dialout is called
#
# room_sweep_interval=10

Loading…
Cancel
Save