diff --git a/apps/webconference/WebConference.cpp b/apps/webconference/WebConference.cpp index 83e5b9f1..14affe13 100644 --- a/apps/webconference/WebConference.cpp +++ b/apps/webconference/WebConference.cpp @@ -43,7 +43,9 @@ EXPORT_PLUGIN_CLASS_FACTORY(WebConferenceFactory,APP_NAME); WebConferenceFactory::WebConferenceFactory(const string& _app_name) : AmSessionFactory(_app_name), AmDynInvokeFactory(_app_name), - configured(false) + configured(false), + use_direct_room(false), + direct_room_strip(0) { if (NULL == _instance) { _instance = this; @@ -99,6 +101,29 @@ int WebConferenceFactory::onLoad() } else { DBG("Using adaptive playout buffer as playout technique.\n"); } + + string direct_room_re_str = cfg.getParameter("direct_room_re"); + if (!direct_room_re_str.length()) { + DBG("no direct room access prefixes set.\n"); + } else { + if (regcomp(&direct_room_re, direct_room_re_str.c_str(), + REG_EXTENDED|REG_NOSUB)) { + ERROR("unable to compile direct room RE '%s'.\n", + direct_room_re_str.c_str()); + return -1; + } + use_direct_room = true; + string direct_room_strip_str = cfg.getParameter("direct_room_strip"); + if (direct_room_strip_str.length() && + str2i(direct_room_strip_str, direct_room_strip)) { + ERROR("unable to decipher direct_room_strip amount '%s'\n", + direct_room_strip_str.c_str()); + return -1; + } + DBG("Webconference will strip %d leading characters from " + "direct room access usernames\n", + direct_room_strip); + } return 0; } @@ -106,9 +131,6 @@ int WebConferenceFactory::onLoad() void WebConferenceFactory::newParticipant(const string& conf_id, const string& localtag, const string& number) { - DBG("newparticipant ------------------- %s %s %s\n", conf_id.c_str(), - localtag.c_str(), - number.c_str()); rooms_mut.lock(); rooms[conf_id].newParticipant(localtag, number); rooms_mut.unlock(); @@ -150,16 +172,23 @@ ConferenceRoom* WebConferenceFactory::getRoom(const string& room, // incoming calls AmSession* WebConferenceFactory::onInvite(const AmSipRequest& req) { - DBG("ONINVITE ----------------- INCOMING ---------------------\n"); + if (use_direct_room) { + if (!regexec(&direct_room_re, req.user.c_str(), 0,0,0)) { + string room = req.user; + if (room.length() > direct_room_strip) + room = room.substr(direct_room_strip); + DBG("direct room access match. connecting to room '%s'\n", + room.c_str()); + return new WebConferenceDialog(prompts, getInstance(), room); + } + } return new WebConferenceDialog(prompts, getInstance(), NULL); } -// outgoing calls - req is INVITE +// outgoing calls AmSession* WebConferenceFactory::onInvite(const AmSipRequest& req, AmArg& session_params) { - DBG("ONINVITE ----------------- OUTGOING ---------------------\n"); - UACAuthCred* cred = NULL; if (session_params.getType() == AmArg::AObject) { ArgObject* cred_obj = session_params.asObject(); @@ -253,55 +282,6 @@ void WebConferenceFactory::roomInfo(const AmArgArray& args, AmArgArray& ret) { ret.push(res); } rooms_mut.unlock(); - -// if (checkAdminpin(room, adminpin)) { -// ret.push(0); -// ret.push("OK"); -// AmArg r; -// r.setBorrowedPointer(it->second.asArgArray()); -// ret.push(r); -// } else { -// ret.push(1); -// ret.push("wrong adminpin"); -// // for consistency, add an empty array -// AmArgArray* a = new AmArgArray(); -// AmArg r; -// r.setBorrowedPointer(a); -// ret.push(r); -// } - -// rooms_mut.lock(); -// map::iterator it = rooms.find(room); -// if (it == rooms.end()) { -// // (re)open room -// rooms[room] = ConferenceRoom(); -// rooms[room].adminpin = adminpin; -// ret.push(0); -// ret.push("OK"); -// // add empty paricipants list -// AmArgArray* a = new AmArgArray(); -// AmArg r; -// r.setBorrowedPointer(a); -// ret.push(r); -// } else { -// if (!it->second.adminpin.empty() && -// (it->second.adminpin != adminpin)) { -// ret.push(1); -// ret.push("wrong adminpin"); -// } else { -// // update adminpin if room was created by dialin -// if (it->second.adminpin.empty()) -// it->second.adminpin = adminpin; -// // return room info -// ret.push(0); -// ret.push("OK"); -// AmArg r; -// r.setBorrowedPointer(it->second.asArgArray()); -// ret.push(r); -// } -// } - -// rooms_mut.unlock(); } void WebConferenceFactory::dialout(const AmArgArray& args, AmArgArray& ret) { @@ -415,6 +395,19 @@ WebConferenceDialog::WebConferenceDialog(AmPromptCollection& prompts, rtp_str.setPlayoutType(WebConferenceFactory::m_PlayoutType); } +WebConferenceDialog::WebConferenceDialog(AmPromptCollection& prompts, + WebConferenceFactory* my_f, + const string& room) + : play_list(this), separator(this, 0), prompts(prompts), state(None), + factory(my_f) +{ + conf_id = room; + DBG("set conf_id to %s\n", conf_id.c_str()); + is_dialout = false; + // set configured playout type + rtp_str.setPlayoutType(WebConferenceFactory::m_PlayoutType); +} + WebConferenceDialog::~WebConferenceDialog() { prompts.cleanup((long)this); @@ -454,25 +447,36 @@ void WebConferenceDialog::connectConference(const string& room) { } void WebConferenceDialog::onSessionStart(const AmSipRequest& req) { - state = EnteringPin; - - prompts.addToPlaylist(ENTER_PIN, (long)this, play_list); - - // set the playlist as input and output - setInOut(&play_list,&play_list); + // direct room access? + if (conf_id.empty()) { + 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, + getLocalTag(), + ConferenceRoomParticipant::Connected, + "direct access: entered"); + state = InConference; + connectConference(conf_id); + } } void WebConferenceDialog::onSessionStart(const AmSipReply& rep) { + DBG("########## dialout: connect conference #########\n"); state = InConference; connectConference(dlg.user); } void WebConferenceDialog::onSipReply(const AmSipReply& reply) { - DBG("SIP REPLY ----------------------\n"); AmSession::onSipReply(reply); if (is_dialout) { - DBG("is_dialout"); // map AmSipDialog state to WebConferenceState ConferenceRoomParticipant::ParticipantStatus rep_st = ConferenceRoomParticipant::Connecting; switch (dlg.getStatus()) { @@ -544,7 +548,7 @@ void WebConferenceDialog::process(AmEvent* ev) // don't care for the id here if (EnteringConference == state) { state = InConference; - DBG("connectConference. **********************\n"); + DBG("########## connectConference after pin entry #########\n"); connectConference(pin_str); factory->newParticipant(pin_str, getLocalTag(), @@ -552,14 +556,14 @@ void WebConferenceDialog::process(AmEvent* ev) factory->updateStatus(pin_str, getLocalTag(), ConferenceRoomParticipant::Connected, - "200 OK"); + "entered"); } } // audio events AmAudioEvent* audio_ev = dynamic_cast(ev); if (audio_ev && audio_ev->event_id == AmAudioEvent::noAudio) { - DBG("received noAudio event. **********************\n"); + DBG("########## noAudio event #########\n"); return; } @@ -568,6 +572,7 @@ void WebConferenceDialog::process(AmEvent* ev) if (InConference == state) { switch(webconf_ev->event_id) { case WebConferenceEvent::Kick: { + DBG("########## WebConferenceEvent::Kick #########\n"); dlg.bye(); disconnectConference(); factory->updateStatus(conf_id, @@ -575,8 +580,14 @@ void WebConferenceDialog::process(AmEvent* ev) ConferenceRoomParticipant::Disconnecting, "disconnect"); } break; - case WebConferenceEvent::Mute: { setInOut(NULL, &play_list); } break; - case WebConferenceEvent::Unmute:{ setInOut(&play_list, &play_list); } break; + case WebConferenceEvent::Mute: { + DBG("########## WebConferenceEvent::Mute #########\n"); + setInOut(NULL, &play_list); + } break; + case WebConferenceEvent::Unmute:{ + DBG("########## WebConferenceEvent::Unmute #########\n"); + setInOut(&play_list, &play_list); + } break; default: { WARN("ignoring unknown webconference event %d\n", webconf_ev->event_id); } break; } } diff --git a/apps/webconference/WebConference.h b/apps/webconference/WebConference.h index 9e623718..26a90494 100644 --- a/apps/webconference/WebConference.h +++ b/apps/webconference/WebConference.h @@ -42,6 +42,9 @@ using std::map; using std::string; +#include +#include + class ConferenceStatus; class ConferenceStatusContainer; @@ -86,6 +89,11 @@ class WebConferenceFactory const string& adminpin); void postConfEvent(const AmArgArray& args, AmArgArray& ret, int id, int mute); + + regex_t direct_room_re; + bool use_direct_room; + unsigned int direct_room_strip; + public: static string DigitsDir; static PlayoutType m_PlayoutType; @@ -156,6 +164,9 @@ public: WebConferenceDialog(AmPromptCollection& prompts, WebConferenceFactory* my_f, UACAuthCred* cred); + WebConferenceDialog(AmPromptCollection& prompts, + WebConferenceFactory* my_f, + const string& room); ~WebConferenceDialog(); void process(AmEvent* ev); diff --git a/apps/webconference/etc/webconference.conf b/apps/webconference/etc/webconference.conf index 95e3ede3..30136fc7 100644 --- a/apps/webconference/etc/webconference.conf +++ b/apps/webconference/etc/webconference.conf @@ -9,4 +9,17 @@ entering_conference=/usr/local/lib/sems/audio/webconference/entering_conference. # digits to play the room number # must contain the files 0.wav, 1.wav, ..., 9.wav -digits_dir=/usr/local/lib/sems/audio/webconference/ \ No newline at end of file +digits_dir=/usr/local/lib/sems/audio/webconference/ + +# +# direct_room_re specifies a regexp which, if matched on +# the user of an incoming call, connects the caller directly to +# the conference room, without asking for the PIN. +# +direct_room_re=00077* +# +# direct_room_strip specifies the number of digits to strip +# from the user part of the request uri to get the conference +# room number on direct room dial in. +# e.g. direct_room_strip=5, called 00077123 => room 123 +direct_room_strip=5