From dfac67bbad8bb9c1ed7aa5919c35fcbad398bf3a Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 8 Dec 2008 16:53:35 +0000 Subject: [PATCH] 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 --- apps/webconference/RoomInfo.cpp | 51 ++++++++++++++++++--- apps/webconference/RoomInfo.h | 12 +++-- apps/webconference/WebConference.cpp | 56 ++++++++++++++++++++++- apps/webconference/WebConference.h | 8 ++++ apps/webconference/etc/webconference.conf | 41 +++++++++++++++++ 5 files changed, 156 insertions(+), 12 deletions(-) diff --git a/apps/webconference/RoomInfo.cpp b/apps/webconference/RoomInfo.cpp index 41610608..af55b058 100644 --- a/apps/webconference/RoomInfo.cpp +++ b/apps/webconference/RoomInfo.cpp @@ -1,5 +1,7 @@ #include "RoomInfo.h" +#include "WebConference.h" + #include #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::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::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::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; +} diff --git a/apps/webconference/RoomInfo.h b/apps/webconference/RoomInfo.h index 532b2bc2..9cdd3f6b 100644 --- a/apps/webconference/RoomInfo.h +++ b/apps/webconference/RoomInfo.h @@ -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 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(); }; diff --git a/apps/webconference/WebConference.cpp b/apps/webconference/WebConference.cpp index d7495e9b..d9e9a226 100644 --- a/apps/webconference/WebConference.cpp +++ b/apps/webconference/WebConference.cpp @@ -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::iterator it=rooms.begin(); + while (it != rooms.end()) { + if (it->second.expired(now)) { + map::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::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) { diff --git a/apps/webconference/WebConference.h b/apps/webconference/WebConference.h index 21136d29..b04a9147 100644 --- a/apps/webconference/WebConference.h +++ b/apps/webconference/WebConference.h @@ -80,6 +80,8 @@ class WebConferenceFactory map 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&); diff --git a/apps/webconference/etc/webconference.conf b/apps/webconference/etc/webconference.conf index fa77785e..e7d32a6b 100644 --- a/apps/webconference/etc/webconference.conf +++ b/apps/webconference/etc/webconference.conf @@ -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