diff options
Diffstat (limited to 'src/mwi')
-rw-r--r-- | src/mwi/Makefile.am | 29 | ||||
-rw-r--r-- | src/mwi/mwi.cpp | 74 | ||||
-rw-r--r-- | src/mwi/mwi.h | 68 | ||||
-rw-r--r-- | src/mwi/mwi_dialog.cpp | 35 | ||||
-rw-r--r-- | src/mwi/mwi_dialog.h | 35 | ||||
-rw-r--r-- | src/mwi/mwi_subscription.cpp | 105 | ||||
-rw-r--r-- | src/mwi/mwi_subscription.h | 43 | ||||
-rw-r--r-- | src/mwi/simple_msg_sum_body.cpp | 186 | ||||
-rw-r--r-- | src/mwi/simple_msg_sum_body.h | 103 |
9 files changed, 678 insertions, 0 deletions
diff --git a/src/mwi/Makefile.am b/src/mwi/Makefile.am new file mode 100644 index 0000000..29415e6 --- /dev/null +++ b/src/mwi/Makefile.am @@ -0,0 +1,29 @@ +AM_CPPFLAGS = \ + -Wall \ + -I$(top_srcdir)/src \ + $(CCRTP_CFLAGS) \ + $(XML2_CFLAGS) + +#noinst_PROGRAMS = mwitest + +#mwitest_SOURCES = mwitest.cpp + +#mwitest_LDADD = $(top_builddir)/src/util.o\ +# $(top_builddir)/src/mwi/libmwi.a\ +# $(top_builddir)/src/sockets/libsocket.a\ +# $(top_builddir)/src/parser/libsipparser.a\ +# $(top_builddir)/src/sdp/libsdpparser.a\ +# -lresolv\ +# -lboost_regex + +noinst_LIBRARIES = libmwi.a + +libmwi_a_SOURCES =\ + mwi.cpp\ + mwi_dialog.cpp\ + mwi_subscription.cpp\ + simple_msg_sum_body.cpp\ + mwi.h\ + mwi_dialog.h\ + mwi_subscription.h\ + simple_msg_sum_body.h diff --git a/src/mwi/mwi.cpp b/src/mwi/mwi.cpp new file mode 100644 index 0000000..d889cd9 --- /dev/null +++ b/src/mwi/mwi.cpp @@ -0,0 +1,74 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mwi.h" + +t_mwi::t_mwi() : + status(MWI_UNKNOWN) +{} + +t_mwi::t_status t_mwi::get_status(void) const { + t_status result; + mtx_mwi.lock(); + result = status; + mtx_mwi.unlock(); + + return result; +} + +bool t_mwi::get_msg_waiting(void) const { + bool result; + mtx_mwi.lock(); + result = msg_waiting; + mtx_mwi.unlock(); + + return result; +} + +t_msg_summary t_mwi::get_voice_msg_summary(void) const { + t_msg_summary result; + mtx_mwi.lock(); + result = voice_msg_summary; + mtx_mwi.unlock(); + + return result; +} + +void t_mwi::set_status(t_status _status) { + mtx_mwi.lock(); + status = _status; + mtx_mwi.unlock(); +} + +void t_mwi::set_msg_waiting(bool _msg_waiting) { + mtx_mwi.lock(); + msg_waiting = _msg_waiting; + mtx_mwi.unlock(); +} + +void t_mwi::set_voice_msg_summary(const t_msg_summary &summary) { + mtx_mwi.lock(); + voice_msg_summary = summary; + mtx_mwi.unlock(); +} + +void t_mwi::clear_voice_msg_summary(void) { + mtx_mwi.lock(); + voice_msg_summary.clear(); + mtx_mwi.unlock(); +} diff --git a/src/mwi/mwi.h b/src/mwi/mwi.h new file mode 100644 index 0000000..a6bd51b --- /dev/null +++ b/src/mwi/mwi.h @@ -0,0 +1,68 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file + * Message Waiting Indication information. + */ + +#ifndef _MWI_HH +#define _MWI_HH + +#include "simple_msg_sum_body.h" +#include "threads/mutex.h" + +/** MWI information */ +class t_mwi { +public: + /** Status of MWI information */ + enum t_status { + MWI_UNKNOWN, /**< The status is unknown */ + MWI_KNOWN, /**< MWI properly received */ + MWI_FAILED /**< MWI subscription failed */ + }; + +private: + /** Mutex for exclusive access to MWI information */ + mutable t_mutex mtx_mwi; + + /** MWI status */ + t_status status; + + /** Indication if messages are waiting */ + bool msg_waiting; + + /** Summary of voice messages waiting */ + t_msg_summary voice_msg_summary; + +public: + t_mwi(); + + t_status get_status(void) const; + bool get_msg_waiting(void) const; + t_msg_summary get_voice_msg_summary(void) const; + + void set_status(t_status _status); + void set_msg_waiting(bool _msg_waiting); + void set_voice_msg_summary(const t_msg_summary &summary); + + /** Set all counters to zero */ + void clear_voice_msg_summary(void); +}; + +#endif diff --git a/src/mwi/mwi_dialog.cpp b/src/mwi/mwi_dialog.cpp new file mode 100644 index 0000000..41ca0dd --- /dev/null +++ b/src/mwi/mwi_dialog.cpp @@ -0,0 +1,35 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mwi_dialog.h" + +#include "mwi_subscription.h" +#include "phone_user.h" +#include "audits/memman.h" + +t_mwi_dialog::t_mwi_dialog(t_phone_user *_phone_user) : + t_subscription_dialog(_phone_user) +{ + subscription = new t_mwi_subscription(this, &(phone_user->mwi)); + MEMMAN_NEW(subscription); +} + +t_mwi_dialog *t_mwi_dialog::copy(void) { + // Copy is not needed. + assert(false); +} diff --git a/src/mwi/mwi_dialog.h b/src/mwi/mwi_dialog.h new file mode 100644 index 0000000..73e2d91 --- /dev/null +++ b/src/mwi/mwi_dialog.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MWI_DIALOG_H +#define _MWI_DIALOG_H + +#include "mwi.h" +#include "subscription_dialog.h" + +// Forward declaration +class t_phone_user; + +class t_mwi_dialog : public t_subscription_dialog { +public: + t_mwi_dialog(t_phone_user *_phone_user); + + virtual t_mwi_dialog *copy(void); +}; + +#endif diff --git a/src/mwi/mwi_subscription.cpp b/src/mwi/mwi_subscription.cpp new file mode 100644 index 0000000..795acd7 --- /dev/null +++ b/src/mwi/mwi_subscription.cpp @@ -0,0 +1,105 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mwi_subscription.h" + +#include <cassert> + +#include "userintf.h" +#include "audits/memman.h" +#include "parser/hdr_event.h" + +t_request *t_mwi_subscription::create_subscribe(unsigned long expires) const { + t_request *r = t_subscription::create_subscribe(expires); + SET_MWI_HDR_ACCEPT(r->hdr_accept); + + return r; +} + +t_mwi_subscription::t_mwi_subscription(t_mwi_dialog *_dialog, t_mwi *_mwi) : + t_subscription(_dialog, SR_SUBSCRIBER, SIP_EVENT_MSG_SUMMARY), + mwi(_mwi) +{} + +bool t_mwi_subscription::recv_notify(t_request *r, t_tuid tuid, t_tid tid) { + if (t_subscription::recv_notify(r, tuid, tid)) return true; + + bool unsupported_body = false; + + // NOTE: if the subscription is still pending (RFC 3265 3.2.4), then the + // information in the body has no meaning. + if (r->body && r->body->get_type() == BODY_SIMPLE_MSG_SUM && + !is_pending()) + { + t_simple_msg_sum_body *body = dynamic_cast<t_simple_msg_sum_body *>(r->body); + assert(body); + mwi->set_msg_waiting(body->get_msg_waiting()); + + t_msg_summary summary; + if (body->get_msg_summary(MSG_CONTEXT_VOICE, summary)) { + mwi->set_voice_msg_summary(summary); + } else { + mwi->clear_voice_msg_summary(); + } + + mwi->set_status(t_mwi::MWI_KNOWN); + } + + // Verify if there is an usupported body. + if (r->body && r->body->get_type() != BODY_SIMPLE_MSG_SUM) { + unsupported_body = true; + } + + if (state == SS_TERMINATED && !may_resubscribe) { + // The MWI server ended the subscription and indicated + // that resubscription is not possible. So no MWI status + // can be retrieved anymore. This should not happen, so + // present it as a failure to the user. + mwi->set_status(t_mwi::MWI_FAILED); + ui->cb_mwi_terminated(user_config, get_reason_termination()); + } + + t_response *resp; + if (unsupported_body) { + resp = r->create_response(R_415_UNSUPPORTED_MEDIA_TYPE); + SET_MWI_HDR_ACCEPT(r->hdr_accept); + } else { + resp = r->create_response(R_200_OK); + } + send_response(user_config, resp, 0, tid); + MEMMAN_DELETE(resp); + delete resp; + + ui->cb_update_mwi(); + return true; +} + +bool t_mwi_subscription::recv_subscribe_response(t_response *r, t_tuid tuid, t_tid tid) { + // Parent handles the SUBSCRIBE response + (void)t_subscription::recv_subscribe_response(r, tuid, tid); + + // If the subscription is terminated after the SUBSCRIBE response, it means + // that subscription failed. + if (state == SS_TERMINATED) { + ui->cb_mwi_subscribe_failed(user_config, r, mwi->get_status() != t_mwi::MWI_FAILED); + mwi->set_status(t_mwi::MWI_FAILED); + } + + ui->cb_update_mwi(); + return true; +} diff --git a/src/mwi/mwi_subscription.h b/src/mwi/mwi_subscription.h new file mode 100644 index 0000000..1abd8af --- /dev/null +++ b/src/mwi/mwi_subscription.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// RFC 3842 +// message-summary subscription + +#ifndef _MWI_SUBSCRIPTION_H +#define _MWI_SUBSCRIPTION_H + +#include "mwi.h" +#include "mwi_dialog.h" +#include "subscription.h" + +class t_mwi_subscription : public t_subscription { +private: + t_mwi *mwi; + +protected: + virtual t_request *create_subscribe(unsigned long expires) const; + +public: + t_mwi_subscription(t_mwi_dialog *_dialog, t_mwi *_mwi); + + virtual bool recv_notify(t_request *r, t_tuid tuid, t_tid tid); + virtual bool recv_subscribe_response(t_response *r, t_tuid tuid, t_tid tid); +}; + +#endif diff --git a/src/mwi/simple_msg_sum_body.cpp b/src/mwi/simple_msg_sum_body.cpp new file mode 100644 index 0000000..33683f7 --- /dev/null +++ b/src/mwi/simple_msg_sum_body.cpp @@ -0,0 +1,186 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "simple_msg_sum_body.h" + +#include <iostream> +#include <cstdlib> +#include <boost/regex.hpp> + +#include "protocol.h" +#include "util.h" +#include "audits/memman.h" + +t_msg_summary::t_msg_summary() : + newmsgs(0), + newmsgs_urgent(0), + oldmsgs(0), + oldmsgs_urgent(0) +{} + +bool t_msg_summary::parse(const string &s) { + newmsgs = 0; + oldmsgs = 0; + newmsgs_urgent = 0; + oldmsgs_urgent = 0; + + // RFC 3842 5.2 + // msg-summary-line = message-context-class HCOLON newmsgs SLASH oldmsgs + // [ LPAREN new-urgentmsgs SLASH old-urgentmsgs RPAREN ] + // This regex matches the part after HCOLON + boost::regex re("(\\d+)\\s*/\\s*(\\d+)(?:\\s*\\((\\d+)\\s*/\\s*(\\d+)\\s*\\))?"); + + boost::smatch m; + if (!boost::regex_match(s, m, re)) return false; + + if (m.size() == 3) { + newmsgs = strtoul(m.str(1).c_str(), NULL, 10); + oldmsgs = strtoul(m.str(2).c_str(), NULL, 10); + return true; + } else if (m.size() == 5) { + newmsgs = strtoul(m.str(1).c_str(), NULL, 10); + oldmsgs = strtoul(m.str(2).c_str(), NULL, 10); + newmsgs_urgent = strtoul(m.str(3).c_str(), NULL, 10); + oldmsgs_urgent = strtoul(m.str(4).c_str(), NULL, 10); + return true; + } + + return false; +} + +void t_msg_summary::clear(void) { + newmsgs = 0; + newmsgs_urgent = 0; + oldmsgs = 0; + oldmsgs_urgent = 0; +} + +bool t_simple_msg_sum_body::is_context(const string &s) { + return ( s == MSG_CONTEXT_VOICE || + s == MSG_CONTEXT_FAX || + s == MSG_CONTEXT_MULTIMEDIA || + s == MSG_CONTEXT_TEXT || + s == MSG_CONTEXT_NONE); +} + +t_simple_msg_sum_body::t_simple_msg_sum_body() : t_sip_body() +{} + +string t_simple_msg_sum_body::encode(void) const { + string s = "Messages-Waiting: "; + s += (msg_waiting ? "yes" : "no"); + s += CRLF; + + if (msg_account.is_valid()) { + s += "Message-Account: "; + s += msg_account.encode(); + s += CRLF; + } + + for (t_msg_sum_const_iter i = msg_summary.begin(); i != msg_summary.end(); ++i) { + const t_msg_summary &summary = i->second; + s += i->first; + s += ": "; + s += ulong2str(summary.newmsgs); + s += "/"; + s += ulong2str(summary.oldmsgs); + + if (summary.newmsgs_urgent > 0 || summary.oldmsgs_urgent > 0) { + s += " ("; + s += ulong2str(summary.newmsgs_urgent); + s += "/"; + s += ulong2str(summary.oldmsgs_urgent); + s += ")"; + } + + s += CRLF; + } + + return s; +} + +t_sip_body *t_simple_msg_sum_body::copy(void) const { + t_simple_msg_sum_body *body = new t_simple_msg_sum_body(*this); + MEMMAN_NEW(body); + return body; +} + +t_body_type t_simple_msg_sum_body::get_type(void) const { + return BODY_SIMPLE_MSG_SUM; +} + +t_media t_simple_msg_sum_body::get_media(void) const { + return t_media("application", "simple-message-summary"); +} + +void t_simple_msg_sum_body::add_msg_summary(const string &context, const t_msg_summary summary) { + msg_summary.insert(make_pair(context, summary)); +} + +bool t_simple_msg_sum_body::get_msg_waiting(void) const { + return msg_waiting; +} + +t_url t_simple_msg_sum_body::get_msg_account(void) const { + return msg_account; +} + +bool t_simple_msg_sum_body::get_msg_summary(const string &context, t_msg_summary &summary) const { + t_msg_sum_const_iter it = msg_summary.find(context); + if (it == msg_summary.end()) return false; + summary = it->second; + return true; +} + +bool t_simple_msg_sum_body::parse(const string &s) { + bool valid = false; + vector<string> lines = split_linebreak(s); + + for (vector<string>::iterator i = lines.begin(); i != lines.end(); ++i) { + string line = trim(*i); + if (line.empty()) continue; + + vector<string> l = split_on_first(line, ':'); + if (l.size() != 2) continue; + + string header = tolower(trim(l[0])); + string value = tolower(trim(l[1])); + + if (value.empty()) continue; + + if (header == "messages-waiting") { + if (value == "yes") { + msg_waiting = true; + valid = true; + } else if (value == "no") { + msg_waiting = false; + valid = true; + } + } else if (header == "message-account") { + msg_account.set_url(value); + } else if (is_context(header)) { + t_msg_summary summary; + if (summary.parse(value)) { + add_msg_summary(header, summary); + } + } + } + + invalid = !valid; + return valid; +} diff --git a/src/mwi/simple_msg_sum_body.h b/src/mwi/simple_msg_sum_body.h new file mode 100644 index 0000000..48f7584 --- /dev/null +++ b/src/mwi/simple_msg_sum_body.h @@ -0,0 +1,103 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** + * @file + * RFC 3842 simple-message-summary body + */ + +#ifndef SIMPLE_MSG_SUM_BODY_HH +#define SIMPLE_MSG_SUM_BODY_HH + +#include <string> +#include <map> +#include <cc++/config.h> +#include "parser/sip_body.h" +#include "sockets/url.h" + +// RFC 3458 6.2 +// Message contexts +#define MSG_CONTEXT_VOICE "voice-message" +#define MSG_CONTEXT_FAX "fax-message" +#define MSG_CONTEXT_MULTIMEDIA "multimedia-message" +#define MSG_CONTEXT_TEXT "text-message" +#define MSG_CONTEXT_NONE "none" + +using namespace std; + +/** Message summary counters */ +struct t_msg_summary { + uint32 newmsgs; + uint32 newmsgs_urgent; + uint32 oldmsgs; + uint32 oldmsgs_urgent; + + t_msg_summary(); + + /** + * Parse a text representation of a message summary. + * @param s [in] The text to parse. + * @return false if parsing fails, true if it succeeds. + */ + bool parse(const string &s); + + /** Set all counters to zero */ + void clear(void); +}; + +typedef string t_msg_context; +typedef map<t_msg_context, t_msg_summary>::const_iterator t_msg_sum_const_iter; + +class t_simple_msg_sum_body : public t_sip_body { +private: + bool msg_waiting; + t_url msg_account; + map<t_msg_context, t_msg_summary> msg_summary; + + // Returns true if string is a valid message context + bool is_context(const string &s); + +public: + t_simple_msg_sum_body(); + + // Return text encoded body + virtual string encode(void) const; + + // Create a copy of the body + virtual t_sip_body *copy(void) const; + + // Get type of body + virtual t_body_type get_type(void) const; + + virtual t_media get_media(void) const; + + // Add a message summary + void add_msg_summary(const string &context, const t_msg_summary summary); + + bool get_msg_waiting(void) const; + t_url get_msg_account(void) const; + + // Get the message summary for a particular context + // If the context is not present, then false is returned + bool get_msg_summary(const string &context, t_msg_summary &summary) const; + + // Parse a text representation of the body. + bool parse(const string &s); +}; + +#endif |