From f5846bfa27e5e23a348576667c616c2811331fba Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 18 Oct 2010 14:54:27 +0200 Subject: [PATCH] webconference: roomDelete and time for roomCreate added config items (webconference.conf): private_rooms support_rooms_timeout implements bugs #0000048 and #0000049 --- apps/webconference/RoomInfo.cpp | 14 ++ apps/webconference/RoomInfo.h | 8 + apps/webconference/WebConference.cpp | 192 ++++++++++++++++++--- apps/webconference/WebConference.h | 43 ++++- apps/webconference/WebConferenceDialog.cpp | 47 +++-- apps/webconference/WebConferenceDialog.h | 3 +- apps/webconference/etc/webconference.conf | 18 ++ apps/webconference/wav/wrong_pin_bye.wav | Bin 0 -> 34590 bytes 8 files changed, 281 insertions(+), 44 deletions(-) create mode 100644 apps/webconference/wav/wrong_pin_bye.wav diff --git a/apps/webconference/RoomInfo.cpp b/apps/webconference/RoomInfo.cpp index af55b058..dc08d492 100644 --- a/apps/webconference/RoomInfo.cpp +++ b/apps/webconference/RoomInfo.cpp @@ -80,6 +80,16 @@ AmArg ConferenceRoom::asArgArray() { return res; } +vector ConferenceRoom::participantLtags() { + cleanExpired(); + vector res; + for (list::iterator it=participants.begin(); + it != participants.end(); it++) { + res.push_back(it->localtag); + } + return res; +} + void ConferenceRoom::newParticipant(const string& localtag, const string& number) { gettimeofday(&last_access_time, NULL); @@ -149,3 +159,7 @@ bool ConferenceRoom::expired(const struct timeval& now) { return (diff.tv_sec > 0) && (unsigned int)diff.tv_sec > (unsigned int)WebConferenceFactory::RoomExpiredDelay; } + +bool ConferenceRoom::hard_expired(const struct timeval& now) { + return expiry_time && (now.tv_sec > expiry_time); +} diff --git a/apps/webconference/RoomInfo.h b/apps/webconference/RoomInfo.h index 9cdd3f6b..4e3b33d4 100644 --- a/apps/webconference/RoomInfo.h +++ b/apps/webconference/RoomInfo.h @@ -8,6 +8,9 @@ using std::string; #include using std::list; +#include +using std::vector; + #include @@ -54,6 +57,7 @@ struct ConferenceRoom { string adminpin; struct timeval last_access_time; + time_t expiry_time; list participants; @@ -64,6 +68,8 @@ struct ConferenceRoom { AmArg asArgArray(); + vector participantLtags(); + void newParticipant(const string& localtag, const string& number); bool updateStatus(const string& part_tag, @@ -76,6 +82,8 @@ struct ConferenceRoom { bool expired(const struct timeval& now); bool expired(); + + bool hard_expired(const struct timeval& now); }; diff --git a/apps/webconference/WebConference.cpp b/apps/webconference/WebConference.cpp index 3ca78b68..eb3db51c 100644 --- a/apps/webconference/WebConference.cpp +++ b/apps/webconference/WebConference.cpp @@ -70,6 +70,8 @@ int WebConferenceFactory::RoomExpiredDelay; int WebConferenceFactory::RoomSweepInterval; bool WebConferenceFactory::ignore_pin = false; +bool WebConferenceFactory::PrivateRoomsMode = false; + int WebConferenceFactory::onLoad() { return getInstance()->load(); @@ -95,6 +97,7 @@ int WebConferenceFactory::load() AM_PROMPT_ADD(DROP_SOUND, WEBCONF_ANNOUNCE_PATH "beep.wav"); AM_PROMPT_ADD(ENTER_PIN, WEBCONF_ANNOUNCE_PATH "enter_pin.wav"); AM_PROMPT_ADD(WRONG_PIN, WEBCONF_ANNOUNCE_PATH "wrong_pin.wav"); + AM_PROMPT_ADD(WRONG_PIN_BYE, WEBCONF_ANNOUNCE_PATH "wrong_pin_bye.wav"); AM_PROMPT_ADD(ENTERING_CONFERENCE, WEBCONF_ANNOUNCE_PATH "entering_conference.wav"); AM_PROMPT_END(prompts, cfg, APP_NAME); @@ -207,6 +210,16 @@ int WebConferenceFactory::load() } } + + if (cfg.getParameter("private_rooms") == "yes") + PrivateRoomsMode = true; + DBG("Private rooms mode %sabled.\n", PrivateRoomsMode ? "en":"dis"); + + if (cfg.getParameter("support_rooms_timeout") == "yes") { + cleaner = new WebConferenceCleaner(this); + cleaner->start(); + } + if(cfg.hasParameter("enable_session_timer") && (cfg.getParameter("enable_session_timer") == string("yes")) ){ DBG("enabling session timers\n"); @@ -219,12 +232,27 @@ int WebConferenceFactory::load() return 0; } -void WebConferenceFactory::newParticipant(const string& conf_id, +bool WebConferenceFactory::isValidConference(const string& conf_id) { + if (!PrivateRoomsMode) + return true; + rooms_mut.lock(); + bool res = rooms.find(conf_id) != rooms.end(); + rooms_mut.unlock(); + return res; +} + +bool WebConferenceFactory::newParticipant(const string& conf_id, const string& localtag, const string& number) { rooms_mut.lock(); + if (PrivateRoomsMode && rooms.find(conf_id) == rooms.end()) { + rooms_mut.unlock(); + return false; + } + rooms[conf_id].newParticipant(localtag, number); rooms_mut.unlock(); + return true; } void WebConferenceFactory::updateStatus(const string& conf_id, @@ -232,7 +260,9 @@ void WebConferenceFactory::updateStatus(const string& conf_id, ConferenceRoomParticipant::ParticipantStatus status, const string& reason) { rooms_mut.lock(); - rooms[conf_id].updateStatus(localtag, status, reason); + if (!PrivateRoomsMode || rooms.find(conf_id) != rooms.end()) { + rooms[conf_id].updateStatus(localtag, status, reason); + } rooms_mut.unlock(); } @@ -247,16 +277,21 @@ string WebConferenceFactory::getAdminpin(const string& room) { } ConferenceRoom* WebConferenceFactory::getRoom(const string& room, - const string& adminpin) { + const string& adminpin, + bool ignore_adminpin = false) { ConferenceRoom* res = NULL; map::iterator it = rooms.find(room); if (it == rooms.end()) { + if (PrivateRoomsMode) + return NULL; + // (re)open room rooms[room] = ConferenceRoom(); rooms[room].adminpin = adminpin; res = &rooms[room]; } else { if ((!ignore_pin) && + (!ignore_adminpin) && (!it->second.adminpin.empty()) && (it->second.adminpin != adminpin)) { // wrong pin @@ -372,7 +407,7 @@ void WebConferenceFactory::invoke(const string& method, { - if(method == "roomCreate"){ + if (method == "roomCreate"){ args.assertArrayFmt("s"); roomCreate(args, ret); ret.push(getServerInfoString().c_str()); @@ -380,6 +415,10 @@ void WebConferenceFactory::invoke(const string& method, args.assertArrayFmt("ss"); roomInfo(args, ret); ret.push(getServerInfoString().c_str()); + } else if(method == "roomDelete"){ + args.assertArrayFmt("ss"); + roomDelete(args, ret); + ret.push(getServerInfoString().c_str()); } else if(method == "dialout"){ args.assertArrayFmt("sssssss"); dialout(args, ret); @@ -434,6 +473,7 @@ void WebConferenceFactory::invoke(const string& method, ret.push(getServerInfoString().c_str()); } else if(method == "_list"){ ret.push("roomCreate"); + ret.push("roomDelete"); ret.push("roomInfo"); ret.push("dialout"); ret.push("mute"); @@ -492,6 +532,13 @@ void WebConferenceFactory::sweepRooms() { void WebConferenceFactory::roomCreate(const AmArg& args, AmArg& ret) { string room = args.get(0).asCStr(); + time_t expiry_time = 0; + if (args.size() > 1 && (args.get(1).asInt() > 0)) { + struct timeval now; + gettimeofday(&now, NULL); + expiry_time = now.tv_sec + args.get(1).asInt(); + } + rooms_mut.lock(); // sweep rooms (if necessary) @@ -501,6 +548,7 @@ void WebConferenceFactory::roomCreate(const AmArg& args, AmArg& ret) { if (it == rooms.end()) { rooms[room] = ConferenceRoom(); rooms[room].adminpin = getRandomPin(); + rooms[room].expiry_time = expiry_time; ret.push(0); ret.push("OK"); ret.push(rooms[room].adminpin.c_str()); @@ -523,21 +571,76 @@ void WebConferenceFactory::roomInfo(const AmArg& args, AmArg& ret) { string room = args.get(0).asCStr(); string adminpin = args.get(1).asCStr(); - rooms_mut.lock(); - ConferenceRoom* r = getRoom(room, adminpin); - if (NULL == r) { + rooms_mut.lock(); + ConferenceRoom* r = getRoom(room, adminpin); + if (NULL == r) { ret.push(1); - ret.push("wrong adminpin"); + ret.push("wrong adminpin or inexisting room"); // for consistency, add an empty array AmArg a; a.assertArray(0); ret.push(a); - } else { - ret.push(0); - ret.push("OK"); - ret.push(r->asArgArray()); - } - rooms_mut.unlock(); + } else { + ret.push(0); + ret.push("OK"); + ret.push(r->asArgArray()); + } + rooms_mut.unlock(); +} + +void WebConferenceFactory::roomDelete(const string& room, const string& adminpin, + AmArg& ret, bool ignore_adminpin = false) { + rooms_mut.lock(); + + map::iterator it = rooms.find(room); + if (it == rooms.end()) { + rooms_mut.unlock(); + ret.push(2); + ret.push("room does not exist\n"); + return; + } + + rooms_mut.unlock(); + + postAllConfEvent(room, adminpin, ret, + WebConferenceEvent::Kick, ignore_adminpin); + + if (ret.get(0).asInt()==0) { + DBG("erasing room '%s'\n", room.c_str()); + rooms_mut.lock(); + rooms.erase(room); + rooms_mut.unlock(); + } +} + +void WebConferenceFactory::roomDelete(const AmArg& args, AmArg& ret) { + rooms_mut.lock(); + string room = args.get(0).asCStr(); + string adminpin = args.get(1).asCStr(); + + roomDelete(room, adminpin, ret); +} + +void WebConferenceFactory::closeExpiredRooms() { + struct timeval now; + gettimeofday(&now, NULL); + + vector expired_rooms; + + rooms_mut.lock(); + for (map::iterator it = + rooms.begin(); it !=rooms.end(); it++) { + if (it->second.hard_expired(now)) + expired_rooms.push_back(it->first); + } + rooms_mut.unlock(); + + for (vector::iterator it= + expired_rooms.begin(); it != expired_rooms.end(); it++) { + DBG("deleting expired room '%s'\n", it->c_str()); + AmArg ret; + roomDelete(*it, "", ret, true); + } } void WebConferenceFactory::dialout(const AmArg& args, AmArg& ret) { @@ -587,11 +690,12 @@ void WebConferenceFactory::dialout(const AmArg& args, AmArg& ret) { // sweep rooms (if necessary) sweepRooms(); - ConferenceRoom* r = getRoom(room, adminpin); + bool is_valid_room = getRoom(room, adminpin) != NULL; rooms_mut.unlock(); - if (NULL == r) { + + if (!is_valid_room) { ret.push(1); - ret.push("wrong adminpin"); + ret.push("wrong adminpin or inexisting room"); ret.push(""); return; } @@ -624,6 +728,29 @@ void WebConferenceFactory::dialout(const AmArg& args, AmArg& ret) { } } +void WebConferenceFactory::postAllConfEvent(const string& room, const string& adminpin, + AmArg& ret, int id, bool ignore_adminpin = false) { + vector ltags; + rooms_mut.lock(); { + ConferenceRoom* r = getRoom(room, adminpin, ignore_adminpin); + if (NULL == r) { + rooms_mut.unlock(); + return; + } + + ltags = r->participantLtags(); + } rooms_mut.unlock(); + + for (vector::iterator it = + ltags.begin(); it != ltags.end(); it++) { + AmSessionContainer::instance()->postEvent(*it, + new WebConferenceEvent(id)); + } + + ret.push(0); + ret.push("OK"); +} + void WebConferenceFactory::postConfEvent(const AmArg& args, AmArg& ret, int id, int mute) { string room = args.get(0).asCStr(); @@ -635,16 +762,15 @@ void WebConferenceFactory::postConfEvent(const AmArg& args, AmArg& ret, rooms_mut.lock(); ConferenceRoom* r = getRoom(room, adminpin); if (NULL == r) { - ret.push(1); - ret.push("wrong adminpin"); - rooms_mut.unlock(); - return; + ret.push(1); + ret.push("wrong adminpin or inexisting room"); + rooms_mut.unlock(); + return; } bool p_exists = r->hasParticipant(call_tag); if (p_exists && (mute >= 0)) r->setMuted(call_tag, mute); - - rooms_mut.unlock(); + rooms_mut.unlock(); if (p_exists) { AmSessionContainer::instance()->postEvent(call_tag, @@ -681,7 +807,7 @@ void WebConferenceFactory::getRoomPassword(const AmArg& args, AmArg& ret) { if ((!MasterPassword.length()) || pwd != MasterPassword) { ret.push(403); - ret.push("Wrong Master Password.\n"); + ret.push("Wrong Master Password."); return; } int res_code = 404; @@ -707,7 +833,7 @@ void WebConferenceFactory::changeRoomAdminpin(const AmArg& args, AmArg& ret) { ConferenceRoom* r = getRoom(room, adminpin); if (NULL == r) { ret.push(1); - ret.push("wrong adminpin"); + ret.push("wrong adminpin or inexisting room"); } else { r->adminpin = new_adminpin; ret.push(0); @@ -724,13 +850,14 @@ void WebConferenceFactory::listRooms(const AmArg& args, AmArg& ret) { pwd != MasterPassword) { ret.push(407); AmArg res; - res.push("Wrong Master Password.\n"); + res.push("Wrong Master Password."); ret.push(res); return; } AmArg room_list; - + room_list.assertArray(); + rooms_mut.lock(); for (map::iterator it = rooms.begin(); it != rooms.end(); it++) { @@ -822,3 +949,14 @@ void WebConferenceFactory::callStats(bool success, unsigned int connect_t) { } } +void WebConferenceCleaner::on_stop() { + is_stopped.set(true); +} + +void WebConferenceCleaner::run(){ + sleep(1); + while (!is_stopped.get()) { + factory->closeExpiredRooms(); + sleep(1); + } +} diff --git a/apps/webconference/WebConference.h b/apps/webconference/WebConference.h index c4903767..2d251931 100644 --- a/apps/webconference/WebConference.h +++ b/apps/webconference/WebConference.h @@ -54,6 +54,7 @@ class ConferenceStatusContainer; #define DROP_SOUND "drop_sound" #define ENTER_PIN "enter_pin" #define WRONG_PIN "wrong_pin" +#define WRONG_PIN_BYE "wrong_pin_bye" // default path for files #define WEBCONF_ANNOUNCE_PATH "/usr/local/lib/sems/audio/webconference/" @@ -68,6 +69,8 @@ public: }; }; +class WebConferenceCleaner; + class WebConferenceFactory : public AmSessionFactory, public AmDynInvokeFactory, @@ -82,6 +85,8 @@ class WebConferenceFactory AmSessionEventHandlerFactory* session_timer_f; + WebConferenceCleaner* cleaner; + // for DI static WebConferenceFactory* _instance; bool configured; @@ -91,9 +96,13 @@ class WebConferenceFactory string getRandomPin(); /** @return NULL if adminpin wrong */ ConferenceRoom* getRoom(const string& room, - const string& adminpin); + const string& adminpin, + bool ignore_adminpin); void postConfEvent(const AmArg& args, AmArg& ret, int id, int mute); + /** broadcast conf event to all */ + void postAllConfEvent(const string& room, const string& adminpin, + AmArg& ret, int id, bool ignore_adminpin); regex_t direct_room_re; bool use_direct_room; @@ -126,13 +135,16 @@ public: static bool ignore_pin; + static bool PrivateRoomsMode; + WebConferenceFactory(const string& _app_name); AmSession* onInvite(const AmSipRequest&); AmSession* onInvite(const AmSipRequest& req, AmArg& session_params); int onLoad(); - void newParticipant(const string& conf_id, + bool isValidConference(const string& conf_id); + bool newParticipant(const string& conf_id, const string& localtag, const string& number); void updateStatus(const string& conf_id, @@ -142,33 +154,58 @@ public: void callStats(bool success, unsigned int connect_t); + void closeExpiredRooms(); + // DI API WebConferenceFactory* getInstance(){ return _instance; } void invoke(const string& method, const AmArg& args, AmArg& ret); + void roomDelete(const string& room, const string& adminpin, + AmArg& ret, bool ignore_adminpin); + // DI functions void roomCreate(const AmArg& args, AmArg& ret); void roomInfo(const AmArg& args, AmArg& ret); + void roomDelete(const AmArg& args, AmArg& ret); + void changeRoomAdminpin(const AmArg& args, AmArg& ret); + void dialout(const AmArg& args, AmArg& ret); void kickout(const AmArg& args, AmArg& ret); void mute(const AmArg& args, AmArg& ret); void unmute(const AmArg& args, AmArg& ret); - void changeRoomAdminpin(const AmArg& args, AmArg& ret); + void serverInfo(const AmArg& args, AmArg& ret); + void vqRoomFeedback(const AmArg& args, AmArg& ret); void vqCallFeedback(const AmArg& args, AmArg& ret); void vqConferenceFeedback(const AmArg& args, AmArg& ret); void resetFeedback(const AmArg& args, AmArg& ret); void flushFeedback(const AmArg& args, AmArg& ret); + void getRoomPassword(const AmArg& args, AmArg& ret); void listRooms(const AmArg& args, AmArg& ret); }; +class WebConferenceCleaner + : public AmThread +{ + WebConferenceFactory* factory; + AmCondition is_stopped; + +public: + WebConferenceCleaner(WebConferenceFactory* factory) + : factory(factory), is_stopped(false) { } + + void run(); + void on_stop(); +}; + #endif // Local Variables: // mode:C++ // End: + diff --git a/apps/webconference/WebConferenceDialog.cpp b/apps/webconference/WebConferenceDialog.cpp index 3961b750..9431d890 100644 --- a/apps/webconference/WebConferenceDialog.cpp +++ b/apps/webconference/WebConferenceDialog.cpp @@ -114,16 +114,23 @@ void WebConferenceDialog::onSessionStart(const AmSipRequest& req) { // direct room access? if (conf_id.empty()) { - state = EnteringPin; + state = EnteringPin; prompts.addToPlaylist(ENTER_PIN, (long)this, play_list); // set the playlist as input and output setInOut(&play_list,&play_list); } else { - DBG("########## direct connect conference #########\n"); - factory->newParticipant(conf_id, - getLocalTag(), - dlg.remote_party); - factory->updateStatus(conf_id, + DBG("########## direct connect conference #########\n"); + if (!factory->newParticipant(conf_id, + getLocalTag(), + dlg.remote_party)) { + DBG("inexisting conference room\n"); + state = PlayErrorFinish; + setInOut(&play_list,&play_list); + prompts.addToPlaylist(WRONG_PIN_BYE, (long)this, play_list); + return; + } + + factory->updateStatus(conf_id, getLocalTag(), ConferenceRoomParticipant::Connected, "direct access: entered"); @@ -266,21 +273,36 @@ void WebConferenceDialog::process(AmEvent* ev) if (EnteringConference == state) { state = InConference; DBG("########## connectConference after pin entry #########\n"); + + if (!factory->newParticipant(pin_str, + getLocalTag(), + dlg.remote_party)) { + DBG("inexisting conference room\n"); + state = PlayErrorFinish; + setInOut(&play_list,&play_list); + prompts.addToPlaylist(WRONG_PIN_BYE, (long)this, play_list); + return; + } + connectConference(pin_str); - factory->newParticipant(pin_str, - getLocalTag(), - dlg.remote_party); factory->updateStatus(pin_str, getLocalTag(), ConferenceRoomParticipant::Connected, "entered"); - } + } } // audio events AmAudioEvent* audio_ev = dynamic_cast(ev); if (audio_ev && audio_ev->event_id == AmAudioEvent::noAudio) { DBG("########## noAudio event #########\n"); + if (PlayErrorFinish == state) { + DBG("Finished playing bye message, ending call.\n"); + dlg.bye(); + setStopped(); + return; + } + return; } @@ -312,10 +334,9 @@ void WebConferenceDialog::onDtmf(int event, int duration) play_list.close(false); } else if (event==10 || event==11) { // pound and star key - // if required add checking of pin here... - if (!pin_str.length()) { - + if (!pin_str.length() || !factory->isValidConference(pin_str)) { prompts.addToPlaylist(WRONG_PIN, (long)this, play_list, true); + pin_str.clear(); } else { state = EnteringConference; setInOut(NULL, NULL); diff --git a/apps/webconference/WebConferenceDialog.h b/apps/webconference/WebConferenceDialog.h index 8e2fb0a9..23cb4796 100644 --- a/apps/webconference/WebConferenceDialog.h +++ b/apps/webconference/WebConferenceDialog.h @@ -48,7 +48,8 @@ public: EnteringConference, InConference, InConferenceRinging, - InConferenceEarly + InConferenceEarly, + PlayErrorFinish }; private: diff --git a/apps/webconference/etc/webconference.conf b/apps/webconference/etc/webconference.conf index c81f33d3..5b53d1f7 100644 --- a/apps/webconference/etc/webconference.conf +++ b/apps/webconference/etc/webconference.conf @@ -5,6 +5,7 @@ join_sound=/usr/local/lib/sems/audio/webconference/beep.wav drop_sound=/usr/local/lib/sems/audio/webconference/beep.wav enter_pin=/usr/local/lib/sems/audio/webconference/pin_prompt.wav wrong_pin=/usr/local/lib/sems/audio/webconference/wrong_pin.wav +wrong_pin_bye=/usr/local/lib/sems/audio/webconference/wrong_pin_bye.wav entering_conference=/usr/local/lib/sems/audio/webconference/entering_conference.wav # @@ -65,6 +66,23 @@ stats_dir=/var/log/sems-webconference/ # #webconference_urlbase=https://webconference.iptel.org/openRoom.py?action=openRoom +# private_rooms = [yes |no] +# +# In private rooms mode, participants can join rooms only if they have been +# opened before. +# +# Default: no +# +# private_rooms=yes + +# support_rooms_timeout = [yes |no] +# +# Support timeout for rooms? If rooms are timed out, they will be closed and +# all participants disconnected. +# +# Default: no +# +# support_rooms_timeout=yes # # participants_expire = [yes | no] diff --git a/apps/webconference/wav/wrong_pin_bye.wav b/apps/webconference/wav/wrong_pin_bye.wav new file mode 100644 index 0000000000000000000000000000000000000000..52c8321bd0e4102890b21c8a56ae8ebdf1b6c9e0 GIT binary patch literal 34590 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 E0eF|4CIA2c literal 0 HcmV?d00001