summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLubos Dolezel <lubos@dolezel.info>2015-07-07 23:08:03 +0200
committerLubos Dolezel <lubos@dolezel.info>2015-07-07 23:08:03 +0200
commit38bb6b72da1d3f5cfa4c72d8bc9597229423c0e3 (patch)
tree14186c138dbd8c90dc94f41484c4d1b2ac1d7818
parentea71ccfcfab52f74469231cab4e70552333b590a (diff)
downloadtwinkle-38bb6b72da1d3f5cfa4c72d8bc9597229423c0e3.tar
twinkle-38bb6b72da1d3f5cfa4c72d8bc9597229423c0e3.tar.gz
twinkle-38bb6b72da1d3f5cfa4c72d8bc9597229423c0e3.tar.lz
twinkle-38bb6b72da1d3f5cfa4c72d8bc9597229423c0e3.tar.xz
twinkle-38bb6b72da1d3f5cfa4c72d8bc9597229423c0e3.zip
Partial lock rework in t_phone (#17). If the app starts crashing or freezing, this commit is probably to blame.
-rw-r--r--src/call_history.cpp42
-rw-r--r--src/call_history.h10
-rw-r--r--src/gui/gui.cpp20
-rw-r--r--src/phone.cpp326
-rw-r--r--src/phone.h2
-rw-r--r--src/threads/mutex.cpp37
-rw-r--r--src/threads/mutex.h42
7 files changed, 309 insertions, 170 deletions
diff --git a/src/call_history.cpp b/src/call_history.cpp
index 8d1a02f..cf9ff5c 100644
--- a/src/call_history.cpp
+++ b/src/call_history.cpp
@@ -55,6 +55,8 @@ t_call_record::t_call_record() {
}
void t_call_record::renew() {
+ t_mutex_guard x(mutex);
+
mtx_class.lock();
id = next_id++;
if (next_id == 65535) next_id = 1;
@@ -87,6 +89,7 @@ void t_call_record::start_call(const t_request *invite, t_direction dir,
{
assert(invite->method == INVITE);
+ t_mutex_guard x(mutex);
struct timeval t;
gettimeofday(&t, NULL);
@@ -128,6 +131,7 @@ void t_call_record::fail_call(const t_response *resp) {
assert(resp->get_class() >= 3);
assert(resp->hdr_cseq.method == INVITE);
+ t_mutex_guard x(mutex);
struct timeval t;
gettimeofday(&t, NULL);
@@ -148,6 +152,7 @@ void t_call_record::fail_call(const t_response *resp) {
void t_call_record::answer_call(const t_response *resp) {
assert(resp->is_success());
+ t_mutex_guard x(mutex);
struct timeval t;
gettimeofday(&t, NULL);
@@ -166,6 +171,7 @@ void t_call_record::answer_call(const t_response *resp) {
void t_call_record::end_call(t_rel_cause cause) {
struct timeval t;
+ t_mutex_guard x(mutex);
gettimeofday(&t, NULL);
time_end = t.tv_sec;
@@ -285,6 +291,8 @@ bool t_call_record::create_file_record(vector<string> &v) const {
}
bool t_call_record::populate_from_file_record(const vector<string> &v) {
+ t_mutex_guard x(mutex);
+
// Check number of fields
if (v.size() != 20) return false;
@@ -333,6 +341,40 @@ unsigned short t_call_record::get_id(void) const {
return id;
}
+t_call_record::t_call_record(const t_call_record& that) {
+ *this = that;
+}
+
+t_call_record& t_call_record::operator=(const t_call_record& that) {
+ t_mutex_guard x1(that.mutex);
+ t_mutex_guard x2(this->mutex);
+
+ id = that.id;
+
+ time_start = that.time_start;
+ time_answer = that.time_answer;
+ time_end = that.time_end;
+ direction = that.direction;
+ from_display = that.from_display;
+ from_uri = that.from_uri;
+ from_organization = that.from_organization;
+ to_display = that.to_display;
+ to_uri = that.to_uri;
+ to_organization = that.to_organization;
+ reply_to_display = that.reply_to_display;
+ reply_to_uri = that.reply_to_uri;
+ referred_by_display = that.referred_by_display;
+ referred_by_uri = that.referred_by_uri;
+ subject = that.subject;
+ rel_cause = that.rel_cause;
+ invite_resp_code = that.invite_resp_code;
+ invite_resp_reason = that.invite_resp_reason;
+ far_end_device = that.far_end_device;
+ user_profile = that.user_profile;
+
+ return *this;
+}
+
////////////////////////
// class t_call_history
////////////////////////
diff --git a/src/call_history.h b/src/call_history.h
index b7fd3b6..93db6be 100644
--- a/src/call_history.h
+++ b/src/call_history.h
@@ -82,6 +82,12 @@ public:
/** Constructor. */
t_call_record();
+
+ /** Copy constructor */
+ t_call_record(const t_call_record& that);
+
+ /** Assignment operator */
+ t_call_record& operator=(const t_call_record& that);
/**
* Clear current settings and get a new record id.
@@ -177,6 +183,10 @@ public:
/** Get the record id. */
unsigned short get_id(void) const;
+private:
+ // Guarded by a mutex, because contents of this class are updated from other threads.
+ // The main thread always creates a copy (snapshot) of current state.
+ mutable t_mutex mutex;
};
/** History of calls. */
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index 97b621e..25b2814 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -758,14 +758,14 @@ t_gui::t_gui(t_phone *_phone) : t_userintf(_phone), timerUpdateMessageSessions(N
MEMMAN_NEW(mainWindow);
- connect(this, SIGNAL(update_reg_status()), mainWindow, SLOT(updateRegStatus()));
- connect(this, SIGNAL(update_mwi()), mainWindow, SLOT(updateMwi()));
- connect(this, SIGNAL(update_state()), mainWindow, SLOT(updateState()));
- connect(this, SIGNAL(mw_display(const QString&)), mainWindow, SLOT(display(const QString&)));
- connect(this, SIGNAL(mw_display_header()), mainWindow, SLOT(displayHeader()));
- connect(this, SIGNAL(mw_update_log(bool)), mainWindow, SLOT(updateLog(bool)));
- connect(this, SIGNAL(mw_update_call_history()), mainWindow, SLOT(updateCallHistory()));
- connect(this, SIGNAL(mw_update_missed_call_status(int)), mainWindow, SLOT(updateMissedCallStatus(int)));
+ connect(this, SIGNAL(update_reg_status()), mainWindow, SLOT(updateRegStatus()), Qt::QueuedConnection);
+ connect(this, SIGNAL(update_mwi()), mainWindow, SLOT(updateMwi()), Qt::QueuedConnection);
+ connect(this, SIGNAL(update_state()), mainWindow, SLOT(updateState()), Qt::QueuedConnection);
+ connect(this, SIGNAL(mw_display(const QString&)), mainWindow, SLOT(display(const QString&)), Qt::QueuedConnection);
+ connect(this, SIGNAL(mw_display_header()), mainWindow, SLOT(displayHeader()), Qt::QueuedConnection);
+ connect(this, SIGNAL(mw_update_log(bool)), mainWindow, SLOT(updateLog(bool)), Qt::QueuedConnection);
+ connect(this, SIGNAL(mw_update_call_history()), mainWindow, SLOT(updateCallHistory()), Qt::QueuedConnection);
+ connect(this, SIGNAL(mw_update_missed_call_status(int)), mainWindow, SLOT(updateMissedCallStatus(int)), Qt::QueuedConnection);
}
t_gui::~t_gui() {
@@ -3194,7 +3194,6 @@ void t_gui::open_url_in_browser(const QString &url) {
}
}
#endif
- QProcess process;
bool process_started = false;
QStringList browsers;
@@ -3208,8 +3207,7 @@ void t_gui::open_url_in_browser(const QString &url) {
for (QStringList::Iterator it = browsers.begin(); it != browsers.end(); ++it)
{
- process.start(*it, QStringList(url));
- process_started = process.waitForStarted(1000);
+ process_started = QProcess::startDetached(*it, QStringList(url));
if (process_started) break;
}
diff --git a/src/phone.cpp b/src/phone.cpp
index 96882c6..0022298 100644
--- a/src/phone.cpp
+++ b/src/phone.cpp
@@ -80,6 +80,8 @@ t_phone_user *t_transfer_data::get_phone_user(void) const {
///////////
void t_phone::move_line_to_background(unsigned short lineno) {
+ // R/W lock is held by callers
+
// The line will be released in the background. It should
// immediately release its RTP ports as these maybe needed
// for new calls.
@@ -115,6 +117,8 @@ void t_phone::move_line_to_background(unsigned short lineno) {
}
void t_phone::cleanup_dead_lines(void) {
+ t_rwmutex_writer x(lines_mtx);
+
// Only remove idle lines at the end of the dead pool to avoid
// moving lines in the vector.
while (lines.size() > NUM_CALL_LINES && lines.back()->get_state() == LS_IDLE)
@@ -134,6 +138,8 @@ void t_phone::cleanup_dead_lines(void) {
}
void t_phone::move_releasing_lines_to_background(void) {
+ t_rwmutex_writer x(lines_mtx);
+
// NOTE: the line on the REFERRER position is not moved to the
// background as a subscription may still be active.
for (int i = 0; i < NUM_USER_LINES; i++) {
@@ -209,6 +215,8 @@ void t_phone::cleanup_3way(void) {
void t_phone::invite(t_phone_user *pu, const t_url &to_uri, const string &to_display,
const string &subject, bool no_fork, bool anonymous)
{
+ t_rwmutex_reader x(lines_mtx);
+
// Ignore if active line is not idle
if (lines[active_line]->get_state() != LS_IDLE) {
return;
@@ -218,6 +226,8 @@ void t_phone::invite(t_phone_user *pu, const t_url &to_uri, const string &to_dis
}
void t_phone::answer(void) {
+ t_rwmutex_reader x(lines_mtx);
+
// Ignore if active line is idle
if (lines[active_line]->get_state() == LS_IDLE) return;
@@ -225,6 +235,8 @@ void t_phone::answer(void) {
}
void t_phone::reject(void) {
+ t_rwmutex_reader x(lines_mtx);
+
// Ignore if active line is idle
if (lines[active_line]->get_state() == LS_IDLE) return;
@@ -232,6 +244,8 @@ void t_phone::reject(void) {
}
void t_phone::reject(unsigned short line) {
+ t_rwmutex_reader x(lines_mtx);
+
if (line > NUM_USER_LINES) return;
if (lines[line]->get_state() == LS_IDLE) return;
@@ -240,6 +254,8 @@ void t_phone::reject(unsigned short line) {
void t_phone::redirect(const list<t_display_url> &destinations, int code, string reason)
{
+ t_rwmutex_reader x(lines_mtx);
+
// Ignore if active line is idle
if (lines[active_line]->get_state() == LS_IDLE) return;
@@ -247,6 +263,8 @@ void t_phone::redirect(const list<t_display_url> &destinations, int code, string
}
void t_phone::end_call(void) {
+ t_rwmutex_writer x(lines_mtx);
+
// If 3-way is active then end call on both lines
if (is_3way && (
active_line == line1_3way->get_line_number() ||
@@ -263,6 +281,8 @@ void t_phone::end_call(void) {
move_line_to_background(lineno1);
move_line_to_background(lineno2);
} else {
+ t_rwmutex_reader x(lines_mtx);
+
// Hangup the active line, and make the next
// line active.
int l = active_line;
@@ -278,6 +298,7 @@ void t_phone::end_call(void) {
if (lines.at(active_line)->get_state() == LS_IDLE) return;
lines.at(active_line)->end_call();
+
move_line_to_background(active_line);
}
@@ -292,6 +313,8 @@ void t_phone::options(t_phone_user *pu, const t_url &to_uri, const string &to_di
}
void t_phone::options(void) {
+ t_rwmutex_reader x(lines_mtx);
+
lines[active_line]->options();
}
@@ -304,19 +327,24 @@ bool t_phone::hold(bool rtponly) {
return false;
}
+ t_rwmutex_reader x(lines_mtx);
return lines[active_line]->hold(rtponly);
}
void t_phone::retrieve(void) {
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->retrieve();
}
void t_phone::refer(const t_url &uri, const string &display) {
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->refer(uri, display);
}
void t_phone::refer(unsigned short lineno_from, unsigned short lineno_to)
{
+ t_rwmutex_reader x(lines_mtx);
+
// The nicest transfer is an attended transfer. An attended transfer
// is only possible of the transfer target supports the 'replaces'
// extension (RFC 3891).
@@ -349,6 +377,8 @@ void t_phone::refer(unsigned short lineno_from, unsigned short lineno_to)
// See draft-ietf-sipping-cc-transfer-07 7.3
void t_phone::refer_attended(unsigned short lineno_from, unsigned short lineno_to)
{
+ t_rwmutex_reader x(lines_mtx);
+
t_line *line = lines.at(lineno_to);
switch (line->get_substate())
@@ -435,6 +465,7 @@ void t_phone::refer_attended(unsigned short lineno_from, unsigned short lineno_t
// See draft-ietf-sipping-cc-transfer-07 7
void t_phone::refer_consultation(unsigned short lineno_from, unsigned short lineno_to)
{
+ t_rwmutex_writer x(lines_mtx);
t_line *line = lines.at(lineno_to);
if (line->get_substate() != LSSUB_ESTABLISHED) {
@@ -447,6 +478,7 @@ void t_phone::refer_consultation(unsigned short lineno_from, unsigned short line
// End consultation call
line->end_call();
+
move_line_to_background(lineno_to);
// Transfer call
@@ -506,6 +538,7 @@ void t_phone::setup_consultation_call(const t_url &uri, const string &display) {
invite(pu, uri, display, subject, no_fork, false);
+ t_rwmutex_reader x(lines_mtx);
lines.at(consult_line)->set_is_transfer_consult(true, xfer_line);
lines.at(xfer_line)->set_to_be_transferred(true, consult_line);
@@ -562,6 +595,8 @@ void t_phone::activate_line(unsigned short l) {
set_active_line(l);
+ t_rwmutex_reader x(lines_mtx);
+
// Retrieve the call on the new active line unless that line
// is transferring a call and the user profile indicates that
// the referrer holds the call during call transfer.
@@ -582,6 +617,7 @@ void t_phone::activate_line(unsigned short l) {
}
void t_phone::send_dtmf(char digit, bool inband, bool info) {
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->send_dtmf(digit, inband, info);
}
@@ -686,6 +722,8 @@ void t_phone::handle_response_out_of_dialog(StunMessage *r, t_tuid tuid) {
}
t_phone_user *t_phone::find_phone_user(const string &profile_name) const {
+ t_rwmutex_reader x(phone_users_mtx);
+
for (list<t_phone_user *>::const_iterator i = phone_users.begin();
i != phone_users.end(); ++i)
{
@@ -701,6 +739,8 @@ t_phone_user *t_phone::find_phone_user(const string &profile_name) const {
}
t_phone_user *t_phone::find_phone_user(const t_url &user_uri) const {
+ t_rwmutex_reader x(phone_users_mtx);
+
for (list<t_phone_user *>::const_iterator i = phone_users.begin();
i != phone_users.end(); ++i)
{
@@ -716,6 +756,8 @@ t_phone_user *t_phone::find_phone_user(const t_url &user_uri) const {
}
t_phone_user *t_phone::match_phone_user(t_response *r, t_tuid tuid, bool active_only) {
+ t_rwmutex_reader x(phone_users_mtx);
+
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); ++i)
{
@@ -727,6 +769,8 @@ t_phone_user *t_phone::match_phone_user(t_response *r, t_tuid tuid, bool active_
}
t_phone_user *t_phone::match_phone_user(t_request *r, bool active_only) {
+ t_rwmutex_reader x(phone_users_mtx);
+
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); ++i)
{
@@ -738,6 +782,8 @@ t_phone_user *t_phone::match_phone_user(t_request *r, bool active_only) {
}
t_phone_user *t_phone::match_phone_user(StunMessage *r, t_tuid tuid, bool active_only) {
+ t_rwmutex_reader x(phone_users_mtx);
+
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); ++i)
{
@@ -749,6 +795,8 @@ t_phone_user *t_phone::match_phone_user(StunMessage *r, t_tuid tuid, bool active
}
int t_phone::hunt_line(void) {
+ t_rwmutex_reader x(lines_mtx);
+
// Send incoming call to active line if it is idle.
if (lines.at(active_line)->get_substate() == LSSUB_IDLE) {
return active_line;
@@ -771,6 +819,8 @@ int t_phone::hunt_line(void) {
//////////////
void t_phone::recvd_provisional(t_response *r, t_tuid tuid, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r, tuid)) {
lines[i]->recvd_provisional(r, tuid, tid);
@@ -785,6 +835,8 @@ void t_phone::recvd_provisional(t_response *r, t_tuid tuid, t_tid tid) {
}
void t_phone::recvd_success(t_response *r, t_tuid tuid, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r, tuid)) {
lines[i]->recvd_success(r, tuid, tid);
@@ -797,6 +849,8 @@ void t_phone::recvd_success(t_response *r, t_tuid tuid, t_tid tid) {
}
void t_phone::recvd_redirect(t_response *r, t_tuid tuid, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r, tuid)) {
lines[i]->recvd_redirect(r, tuid, tid);
@@ -809,6 +863,8 @@ void t_phone::recvd_redirect(t_response *r, t_tuid tuid, t_tid tid) {
}
void t_phone::recvd_client_error(t_response *r, t_tuid tuid, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r, tuid)) {
lines[i]->recvd_client_error(r, tuid, tid);
@@ -821,6 +877,8 @@ void t_phone::recvd_client_error(t_response *r, t_tuid tuid, t_tid tid) {
}
void t_phone::recvd_server_error(t_response *r, t_tuid tuid, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r, tuid)) {
lines[i]->recvd_server_error(r, tuid, tid);
@@ -833,6 +891,8 @@ void t_phone::recvd_server_error(t_response *r, t_tuid tuid, t_tid tid) {
}
void t_phone::recvd_global_error(t_response *r, t_tuid tuid, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r, tuid)) {
lines[i]->recvd_global_error(r, tuid, tid);
@@ -851,6 +911,8 @@ void t_phone::post_process_response(t_response *r, t_tuid tuid, t_tid tid) {
}
void t_phone::recvd_invite(t_request *r, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
// Check if this INVITE is a retransmission.
// Once the TU sent a 2XX repsonse on an INVITE it has to deal
// with retransmissions.
@@ -927,6 +989,8 @@ void t_phone::recvd_initial_invite(t_request *r, t_tid tid) {
r->hdr_request_disposition.is_populated() &&
r->hdr_request_disposition.fork_directive == t_hdr_request_disposition::NO_FORK;
+ t_rwmutex_reader x(lines_mtx);
+
for (size_t i = 0; i < lines.size(); i++) {
if (lines.at(i)->match_replaces(r->hdr_replaces.call_id,
r->hdr_replaces.to_tag,
@@ -1214,6 +1278,7 @@ void t_phone::recvd_initial_invite(t_request *r, t_tid tid) {
log_file->write_report("End call due to Replaces header.",
"t_phone::recvd_initial_invite");
+ t_rwmutex_writer x(lines_mtx);
if (lines.at(replace_line)->get_substate() == LSSUB_INCOMING_PROGRESS) {
ui->cb_stop_call_notification(replace_line);
lines.at(replace_line)->reject();
@@ -1229,6 +1294,7 @@ void t_phone::recvd_initial_invite(t_request *r, t_tid tid) {
if (hunted_line == active_line) {
// Auto-answer is only applicable to the active line.
+ t_rwmutex_reader x(lines_mtx);
if (replace_line >= 0 && auto_answer_replace_call) {
// RFC 3891
// This call replaces an existing established call, answer immediate.
@@ -1243,6 +1309,7 @@ void t_phone::recvd_initial_invite(t_request *r, t_tid tid) {
}
}
+ t_rwmutex_reader x(lines_mtx);
// Send INVITE to hunted line
if (hunted_line >= 0) {
lines.at(hunted_line)->recvd_invite(pu, r, tid,
@@ -1293,6 +1360,7 @@ void t_phone::recvd_initial_invite(t_request *r, t_tid tid) {
void t_phone::recvd_re_invite(t_request *r, t_tid tid) {
t_response *resp;
list <string> unsupported;
+ t_rwmutex_reader x(lines_mtx);
// RFC 3261 12.2.2
// A To-header with a tag is a mid-dialog request.
@@ -1329,6 +1397,7 @@ void t_phone::recvd_re_invite(t_request *r, t_tid tid) {
void t_phone::recvd_ack(t_request *r, t_tid tid) {
t_response *resp;
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r)) {
@@ -1347,6 +1416,7 @@ void t_phone::recvd_cancel(t_request *r, t_tid cancel_tid,
t_tid target_tid)
{
t_response *resp;
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match_cancel(r, target_tid)) {
@@ -1364,6 +1434,7 @@ void t_phone::recvd_cancel(t_request *r, t_tid cancel_tid,
void t_phone::recvd_bye(t_request *r, t_tid tid) {
t_response *resp;
list <string> unsupported;
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r)) {
@@ -1444,6 +1515,7 @@ t_phone_user *t_phone::find_phone_user_out_dialog_request(t_request *r, t_tid ti
t_line *t_phone::find_line_in_dialog_request(t_request *r, t_tid tid) {
t_response *resp;
list <string> unsupported;
+ t_rwmutex_reader x(lines_mtx);
// RFC 3261 12.2.2
// A To-header with a tag is a mid-dialog request.
@@ -1551,6 +1623,7 @@ void t_phone::recvd_register(t_request *r, t_tid tid) {
void t_phone::recvd_prack(t_request *r, t_tid tid) {
t_response *resp;
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r)) {
@@ -1578,6 +1651,7 @@ void t_phone::recvd_subscribe(t_request *r, t_tid tid) {
return;
}
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r)) {
lines[i]->recvd_subscribe(r, tid);
@@ -1636,6 +1710,7 @@ void t_phone::recvd_notify(t_request *r, t_tid tid) {
}
// REFER notification
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r)) {
lines[i]->recvd_notify(r, tid);
@@ -1697,6 +1772,7 @@ void t_phone::recvd_notify(t_request *r, t_tid tid) {
void t_phone::recvd_refer(t_request *r, t_tid tid) {
t_response *resp;
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r)) {
@@ -1801,6 +1877,7 @@ void t_phone::recvd_refer_permission(bool permission) {
t_phone_user *pu = incoming_refer_data->get_phone_user();
t_user *user_config = pu->get_user_profile();
+ t_rwmutex_reader x(lines_mtx);
lines[i]->recvd_refer_permission(permission, r);
if (!permission) {
@@ -1896,6 +1973,7 @@ void t_phone::recvd_refer_permission(bool permission) {
void t_phone::recvd_info(t_request *r, t_tid tid) {
t_response *resp;
list <string> unsupported;
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r)) {
@@ -1952,6 +2030,8 @@ void t_phone::failure(t_failure failure, t_tid tid) {
}
void t_phone::recvd_stun_resp(StunMessage *r, t_tuid tuid, t_tid tid) {
+ t_rwmutex_reader x(lines_mtx);
+
for (unsigned short i = 0; i < lines.size(); i++) {
if (lines[i]->match(r, tuid)) {
lines[i]->recvd_stun_resp(r, tuid, tid);
@@ -2031,6 +2111,8 @@ void t_phone::line_timeout_sub(t_object_id id, t_subscribe_timer timer, t_object
void t_phone::subscription_timeout(t_subscribe_timer timer, t_object_id id_timer)
{
+ t_rwmutex_reader x(phone_users_mtx);
+
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); i++)
{
@@ -2041,6 +2123,8 @@ void t_phone::subscription_timeout(t_subscribe_timer timer, t_object_id id_timer
}
void t_phone::publication_timeout(t_publish_timer timer, t_object_id id_timer) {
+ t_rwmutex_reader x(phone_users_mtx);
+
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); i++)
{
@@ -2051,7 +2135,7 @@ void t_phone::publication_timeout(t_publish_timer timer, t_object_id id_timer) {
}
void t_phone::timeout(t_phone_timer timer, unsigned short id_timer) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
switch (timer) {
case PTMR_REGISTRATION:
@@ -2084,11 +2168,11 @@ void t_phone::timeout(t_phone_timer timer, unsigned short id_timer) {
default:
assert(false);
}
-
- unlock();
}
void t_phone::handle_broken_connection(t_event_broken_connection *e) {
+ t_rwmutex_reader x(phone_users_mtx);
+
// Find the phone user that was associated with the connection.
// This phone user has to handle the event.
t_phone_user *pu = find_phone_user(e->get_user_uri());
@@ -2151,6 +2235,7 @@ t_phone::~t_phone() {
delete lines[i];
}
+ t_rwmutex_writer x(phone_users_mtx);
// Delete all phone users
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); i++)
@@ -2164,7 +2249,7 @@ void t_phone::pub_invite(t_user *user,
const t_url &to_uri, const string &to_display,
const string &subject, bool anonymous)
{
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2175,8 +2260,6 @@ void t_phone::pub_invite(t_user *user,
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_answer(void) {
@@ -2214,7 +2297,7 @@ void t_phone::pub_registration(t_user *user,
t_register_type register_type,
unsigned long expires)
{
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2225,14 +2308,12 @@ void t_phone::pub_registration(t_user *user,
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_options(t_user *user,
const t_url &to_uri, const string &to_display)
{
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2243,8 +2324,6 @@ void t_phone::pub_options(t_user *user,
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_options(void) {
@@ -2297,6 +2376,7 @@ void t_phone::mute(bool enable) {
}
else
{
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->mute(enable);
}
@@ -2317,10 +2397,9 @@ void t_phone::pub_send_dtmf(char digit, bool inband, bool info) {
bool t_phone::pub_seize(void) {
bool retval;
+ t_rwmutex_reader x(lines_mtx);
- lock();
retval = lines[active_line]->seize();
- unlock();
return retval;
}
@@ -2328,75 +2407,66 @@ bool t_phone::pub_seize(void) {
bool t_phone::pub_seize(unsigned short line) {
assert(line < NUM_USER_LINES);
bool retval;
+ t_rwmutex_reader x(lines_mtx);
- lock();
retval = lines[line]->seize();
- unlock();
return retval;
}
void t_phone::pub_unseize(void) {
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->unseize();
- unlock();
}
void t_phone::pub_unseize(unsigned short line) {
assert(line < NUM_USER_LINES);
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[line]->unseize();
- unlock();
}
void t_phone::pub_confirm_zrtp_sas(unsigned short line) {
assert(line < NUM_USER_LINES);
- lock();
+
+ t_rwmutex_reader x(lines_mtx);
lines[line]->confirm_zrtp_sas();
- unlock();
}
void t_phone::pub_confirm_zrtp_sas(void) {
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->confirm_zrtp_sas();
- unlock();
}
void t_phone::pub_reset_zrtp_sas_confirmation(unsigned short line) {
assert(line < NUM_USER_LINES);
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[line]->reset_zrtp_sas_confirmation();
- unlock();
}
void t_phone::pub_reset_zrtp_sas_confirmation(void) {
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->reset_zrtp_sas_confirmation();
- unlock();
}
void t_phone::pub_enable_zrtp(void) {
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->enable_zrtp();
- unlock();
}
void t_phone::pub_zrtp_request_go_clear(void) {
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[active_line]->zrtp_request_go_clear();
- unlock();
}
void t_phone::pub_zrtp_go_clear_ok(unsigned short line) {
assert(line < NUM_USER_LINES);
- lock();
+ t_rwmutex_reader x(lines_mtx);
lines[line]->zrtp_go_clear_ok();
- unlock();
}
void t_phone::pub_subscribe_mwi(t_user *user) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2407,12 +2477,10 @@ void t_phone::pub_subscribe_mwi(t_user *user) {
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_unsubscribe_mwi(t_user *user) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2423,12 +2491,10 @@ void t_phone::pub_unsubscribe_mwi(t_user *user) {
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_subscribe_presence(t_user *user) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2439,12 +2505,10 @@ void t_phone::pub_subscribe_presence(t_user *user) {
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_unsubscribe_presence(t_user *user) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2455,12 +2519,10 @@ void t_phone::pub_unsubscribe_presence(t_user *user) {
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_publish_presence(t_user *user, t_presence_state::t_basic_state basic_state) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2471,12 +2533,10 @@ void t_phone::pub_publish_presence(t_user *user, t_presence_state::t_basic_state
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
void t_phone::pub_unpublish_presence(t_user *user) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2487,8 +2547,6 @@ void t_phone::pub_unpublish_presence(t_user *user) {
log_file->write_raw(user->get_profile_name());
log_file->write_footer();
}
-
- unlock();
}
bool t_phone::pub_send_message(t_user *user, const t_url &to_uri, const string &to_display,
@@ -2496,7 +2554,7 @@ bool t_phone::pub_send_message(t_user *user, const t_url &to_uri, const string &
{
bool retval = true;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2511,8 +2569,6 @@ bool t_phone::pub_send_message(t_user *user, const t_url &to_uri, const string &
retval = false;
}
- unlock();
-
return retval;
}
@@ -2521,7 +2577,7 @@ bool t_phone::pub_send_im_iscomposing(t_user *user, const t_url &to_uri, const s
{
bool retval = true;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
@@ -2536,13 +2592,11 @@ bool t_phone::pub_send_im_iscomposing(t_user *user, const t_url &to_uri, const s
retval = false;
}
- unlock();
-
return retval;
}
t_phone_state t_phone::get_state(void) const {
- lock();
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < NUM_USER_LINES; i++) {
if (lines[i]->get_state() == LS_IDLE) {
unlock();
@@ -2551,12 +2605,11 @@ t_phone_state t_phone::get_state(void) const {
}
// All lines are busy, so the phone is busy.
- unlock();
return PS_BUSY;
}
bool t_phone::all_lines_idle(void) const {
- lock();
+ t_rwmutex_reader x(lines_mtx);
for (unsigned short i = 0; i < NUM_USER_LINES; i++) {
if (lines[i]->get_substate() != LSSUB_IDLE) {
unlock();
@@ -2565,12 +2618,11 @@ bool t_phone::all_lines_idle(void) const {
}
// All lines are idle
- unlock();
return true;
}
bool t_phone::get_idle_line(unsigned short &lineno) const {
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool found_idle_line = false;
for (unsigned short i = 0; i < NUM_USER_LINES; i++) {
@@ -2581,15 +2633,13 @@ bool t_phone::get_idle_line(unsigned short &lineno) const {
}
}
- unlock();
return found_idle_line;
}
void t_phone::set_active_line(unsigned short l) {
- lock();
+ t_rwmutex_reader x(lines_mtx);
assert (l < NUM_USER_LINES);
active_line = l;
- unlock();
}
unsigned short t_phone::get_active_line(void) const {
@@ -2597,6 +2647,7 @@ unsigned short t_phone::get_active_line(void) const {
}
t_line *t_phone::get_line_by_id(t_object_id id) const {
+ t_rwmutex_reader x(lines_mtx);
for (size_t i = 0; i < lines.size(); i++) {
if (lines[i]->get_object_id() == id) {
return lines[i];
@@ -2615,28 +2666,25 @@ bool t_phone::authorize(t_user *user, t_request *r, t_response *resp)
{
bool result = false;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) result = pu->authorize(r, resp);
- unlock();
return result;
}
void t_phone::remove_cached_credentials(t_user *user, const string &realm) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) pu->remove_cached_credentials(realm);
- unlock();
}
bool t_phone::get_is_registered(t_user *user) {
bool result = false;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) result = pu->get_is_registered();
- unlock();
return result;
}
@@ -2644,10 +2692,9 @@ bool t_phone::get_is_registered(t_user *user) {
bool t_phone::get_last_reg_failed(t_user *user) {
bool result = false;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) result = pu->get_last_reg_failed();
- unlock();
return result;
}
@@ -2655,36 +2702,32 @@ bool t_phone::get_last_reg_failed(t_user *user) {
t_line_state t_phone::get_line_state(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
t_line_state s = get_line(lineno)->get_state();
- unlock();
return s;
}
t_line_substate t_phone::get_line_substate(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
t_line_substate s = get_line(lineno)->get_substate();
- unlock();
return s;
}
bool t_phone::is_line_on_hold(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool b = get_line(lineno)->get_is_on_hold();
- unlock();
return b;
}
bool t_phone::is_line_muted(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool b = get_line(lineno)->get_is_muted();
- unlock();
return b;
}
@@ -2693,9 +2736,8 @@ bool t_phone::is_line_transfer_consult(unsigned short lineno,
{
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool b = get_line(lineno)->get_is_transfer_consult(transfer_from_line);
- unlock();
return b;
}
@@ -2704,63 +2746,56 @@ bool t_phone::line_to_be_transferred(unsigned short lineno,
{
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool b = get_line(lineno)->get_to_be_transferred(transfer_to_line);
- unlock();
return b;
}
bool t_phone::is_line_encrypted(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool b = get_line(lineno)->get_is_encrypted();
- unlock();
return b;
}
bool t_phone::is_line_auto_answered(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool b = get_line(lineno)->get_auto_answer();
- unlock();
return b;
}
t_refer_state t_phone::get_line_refer_state(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
t_refer_state s = get_line(lineno)->get_refer_state();
- unlock();
return s;
}
t_user *t_phone::get_line_user(unsigned short lineno) {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
t_user *user = get_line(lineno)->get_user();
- unlock();
return user;
}
bool t_phone::has_line_media(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
bool b = get_line(lineno)->has_media();
- unlock();
return b;
}
bool t_phone::is_mwi_subscribed(t_user *user) const {
bool result = false;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) result = pu->is_mwi_subscribed();
- unlock();
return result;
}
@@ -2768,10 +2803,9 @@ bool t_phone::is_mwi_subscribed(t_user *user) const {
bool t_phone::is_mwi_terminated(t_user *user) const {
bool result = false;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) result = pu->is_mwi_terminated();
- unlock();
return result;
}
@@ -2779,10 +2813,9 @@ bool t_phone::is_mwi_terminated(t_user *user) const {
t_mwi t_phone::get_mwi(t_user *user) const {
t_mwi result;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) result = pu->mwi;
- unlock();
return result;
}
@@ -2790,10 +2823,9 @@ t_mwi t_phone::get_mwi(t_user *user) const {
bool t_phone::is_presence_terminated(t_user *user) const {
bool result = false;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) result = pu->is_presence_terminated();
- unlock();
return result;
}
@@ -2801,18 +2833,16 @@ bool t_phone::is_presence_terminated(t_user *user) const {
t_url t_phone::get_remote_uri(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
t_url uri = get_line(lineno)->get_remote_uri();
- unlock();
return uri;
}
string t_phone::get_remote_display(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
string display = get_line(lineno)->get_remote_display();
- unlock();
return display;
}
@@ -2860,6 +2890,7 @@ bool t_phone::join_3way(unsigned short lineno1, unsigned short lineno2) {
assert(lineno2 < NUM_USER_LINES);
lock();
+ t_rwmutex_reader x(lines_mtx);
// Check if there isn't a 3-way already
if (is_3way) {
@@ -2914,6 +2945,8 @@ bool t_phone::join_3way(unsigned short lineno1, unsigned short lineno2) {
}
void t_phone::notify_refer_progress(t_response *r, unsigned short referee_lineno) {
+ t_rwmutex_reader x(lines_mtx);
+
if (lines[LINENO_REFERRER]->get_state() != LS_IDLE) {
lines[LINENO_REFERRER]->notify_refer_progress(r);
@@ -2976,27 +3009,24 @@ void t_phone::notify_refer_progress(t_response *r, unsigned short referee_lineno
t_call_info t_phone::get_call_info(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
t_call_info call_info = get_line(lineno)->get_call_info();
- unlock();
return call_info;
}
t_call_record t_phone::get_call_hist(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
t_call_record call_hist = get_line(lineno)->call_hist_record;
- unlock();
return call_hist;
}
string t_phone::get_ringtone(unsigned short lineno) const {
assert(lineno < lines.size());
- lock();
+ t_rwmutex_reader x(lines_mtx);
string ringtone = get_line(lineno)->get_ringtone();
- unlock();
return ringtone;
}
@@ -3005,16 +3035,17 @@ time_t t_phone::get_startup_time(void) const {
}
void t_phone::init_rtp_ports(void) {
+ t_rwmutex_reader x(lines_mtx);
for (size_t i = 0; i < lines.size(); i++) {
lines[i]->init_rtp_port();
}
}
bool t_phone::add_phone_user(const t_user &user_config, t_user **dup_user) {
- lock();
t_phone_user *existing_phone_user = NULL;
-
+ t_rwmutex_writer x(phone_users_mtx);
+
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); i++)
{
@@ -3036,7 +3067,6 @@ bool t_phone::add_phone_user(const t_user &user_config, t_user **dup_user) {
(*i)->is_active())
{
*dup_user = user;
- unlock();
return false;
}
@@ -3047,7 +3077,6 @@ bool t_phone::add_phone_user(const t_user &user_config, t_user **dup_user) {
(*i)->is_active())
{
*dup_user = user;
- unlock();
return false;
}
}
@@ -3065,29 +3094,26 @@ bool t_phone::add_phone_user(const t_user &user_config, t_user **dup_user) {
t_phone_user *pu = new t_phone_user(user_config);
MEMMAN_NEW(pu);
phone_users.push_back(pu);
- unlock();
return true;
}
void t_phone::remove_phone_user(const t_user &user_config) {
- lock();
+ t_rwmutex_writer x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user_config.get_profile_name());
if (pu) pu->deactivate();
- unlock();
}
list<t_user *> t_phone::ref_users(void) {
list<t_user *> l;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); i++)
{
if (!(*i)->is_active()) continue;
l.push_back((*i)->get_user_profile());
}
- unlock();
return l;
}
@@ -3095,7 +3121,7 @@ list<t_user *> t_phone::ref_users(void) {
t_user *t_phone::ref_user_display_uri(const string &display_uri) {
t_user *u = NULL;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); i++)
{
@@ -3105,7 +3131,6 @@ t_user *t_phone::ref_user_display_uri(const string &display_uri) {
break;
}
}
- unlock();
return u;
}
@@ -3113,10 +3138,9 @@ t_user *t_phone::ref_user_display_uri(const string &display_uri) {
t_user *t_phone::ref_user_profile(const string &profile_name) {
t_user *u = NULL;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(profile_name);
if (pu) u = pu->get_user_profile();
- unlock();
return u;
}
@@ -3125,10 +3149,9 @@ t_service *t_phone::ref_service(t_user *user) {
assert(user);
t_service *srv = NULL;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) srv = pu->service;
- unlock();
return srv;
}
@@ -3137,10 +3160,9 @@ t_buddy_list *t_phone::ref_buddy_list(t_user *user) {
assert(user);
t_buddy_list *l = NULL;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) l = pu->get_buddy_list();
- unlock();
return l;
}
@@ -3149,10 +3171,9 @@ t_presence_epa *t_phone::ref_presence_epa(t_user *user) {
assert(user);
t_presence_epa *epa = NULL;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) epa = pu->get_presence_epa();
- unlock();
return epa;
}
@@ -3160,14 +3181,13 @@ t_presence_epa *t_phone::ref_presence_epa(t_user *user) {
string t_phone::get_ip_sip(const t_user *user, const string &auto_ip) const {
string result;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
result = pu->get_ip_sip(auto_ip);
} else {
result = LOCAL_IP;
}
- unlock();
if (result == AUTO_IP4_ADDRESS) result = auto_ip;
@@ -3177,14 +3197,13 @@ string t_phone::get_ip_sip(const t_user *user, const string &auto_ip) const {
unsigned short t_phone::get_public_port_sip(const t_user *user) const {
unsigned short result;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
result = pu->get_public_port_sip();
} else {
result = sys_config->get_sip_port();
}
- unlock();
return result;
}
@@ -3192,14 +3211,13 @@ unsigned short t_phone::get_public_port_sip(const t_user *user) const {
bool t_phone::use_stun(t_user *user) {
bool result;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
result = pu->use_stun;
} else {
result = false;
}
- unlock();
return result;
}
@@ -3207,36 +3225,33 @@ bool t_phone::use_stun(t_user *user) {
bool t_phone::use_nat_keepalive(t_user *user) {
bool result;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
result = pu->use_nat_keepalive;
} else {
result = false;
}
- unlock();
return result;
}
void t_phone::disable_stun(t_user *user) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) pu->use_stun = false;
- unlock();
}
void t_phone::sync_nat_keepalive(t_user *user) {
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) pu->sync_nat_keepalive();
- unlock();
}
bool t_phone::stun_discover_nat(list<string> &msg_list) {
bool retval = true;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
for (list<t_phone_user *>::iterator i = phone_users.begin();
i != phone_users.end(); ++i)
{
@@ -3264,7 +3279,6 @@ bool t_phone::stun_discover_nat(list<string> &msg_list) {
}
}
}
- unlock();
return retval;
}
@@ -3272,7 +3286,7 @@ bool t_phone::stun_discover_nat(list<string> &msg_list) {
bool t_phone::stun_discover_nat(t_user *user, string &msg) {
bool retval = true;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
if (user->get_sip_transport() == SIP_TRANS_UDP ||
user->get_sip_transport() == SIP_TRANS_AUTO)
{
@@ -3285,7 +3299,6 @@ bool t_phone::stun_discover_nat(t_user *user, string &msg) {
if (pu) pu->use_nat_keepalive = user->get_enable_nat_keepalive();
}
}
- unlock();
return retval;
}
@@ -3295,20 +3308,18 @@ t_response *t_phone::create_options_response(t_user *user, t_request *r,
{
t_response *resp;
- lock();
+ t_rwmutex_reader x(phone_users_mtx);
t_phone_user *pu = find_phone_user(user->get_profile_name());
if (pu) {
resp = pu->create_options_response(r, in_dialog);
} else {
resp = r->create_response(R_500_INTERNAL_SERVER_ERROR);
}
- unlock();
return resp;
}
void t_phone::init(void) {
- lock();
list<t_user *> user_list = ref_users();
@@ -3326,8 +3337,6 @@ void t_phone::init(void) {
// This way STUN will have set the correct
// IP adres (STUN is done as part of registration.)
}
-
- unlock();
}
void t_phone::init_extensions(t_user *user_config) {
@@ -3361,8 +3370,8 @@ bool t_phone::set_sighandler(void) const {
void t_phone::terminate(void) {
string msg;
- lock();
+ lines_mtx.lockRead();
// Clear all lines
log_file->write_report("Clear all lines.",
"t_phone::terminate", LOG_NORMAL, LOG_DEBUG);
@@ -3387,6 +3396,7 @@ void t_phone::terminate(void) {
break;
}
}
+ lines_mtx.unlock();
// Deactivate phone
is_active = false;
@@ -3422,8 +3432,6 @@ void t_phone::terminate(void) {
}
}
- unlock();
-
// Wait till phone is deregistered.
for (list<t_user *>::iterator i = user_list.begin(); i != user_list.end(); i++)
{
@@ -3473,7 +3481,7 @@ void t_phone::terminate(void) {
// Force lines to idle state if they could not be cleared
// gracefully
- lock();
+ lines_mtx.lockRead();
for (size_t i = 0; i < lines.size(); i++) {
if (lines[i]->get_substate() != LSSUB_IDLE) {
msg = "Force line %1 to idle state.";
@@ -3483,10 +3491,10 @@ void t_phone::terminate(void) {
lines[i]->force_idle();
}
}
+ lines_mtx.unlock();
log_file->write_report("Finished phone termination.",
"t_phone::terminate", LOG_NORMAL, LOG_DEBUG);
- unlock();
}
void *phone_uas_main(void *arg) {
diff --git a/src/phone.h b/src/phone.h
index 2a08936..c85e895 100644
--- a/src/phone.h
+++ b/src/phone.h
@@ -116,11 +116,13 @@ private:
// Phone users
list<t_phone_user *> phone_users;
+ mutable t_rwmutex phone_users_mtx;
// Phone lines
// The first NUM_CALL_LINES are for making phone calls.
// The tail of the vector is for releasing lines in the background.
vector<t_line *> lines;
+ mutable t_rwmutex lines_mtx;
// Operations like invite, end_call work on the active line
unsigned short active_line;
diff --git a/src/threads/mutex.cpp b/src/threads/mutex.cpp
index 0ae2a99..159f887 100644
--- a/src/threads/mutex.cpp
+++ b/src/threads/mutex.cpp
@@ -20,6 +20,7 @@
#include <iostream>
#include "mutex.h"
#include "thread.h"
+#include <stdexcept>
using namespace std;
@@ -88,3 +89,39 @@ t_mutex_guard::t_mutex_guard(t_mutex &mutex) : mutex_(mutex) {
t_mutex_guard::~t_mutex_guard() {
mutex_.unlock();
}
+
+
+///////////////////////////
+// t_rwmutex
+///////////////////////////
+
+t_rwmutex::t_rwmutex()
+{
+ int ret = pthread_rwlock_init(&_lock, nullptr);
+ if (ret != 0) throw string(
+ "t_rwmutex::t_rwmutex failed to create a r/w mutex.");
+}
+
+t_rwmutex::~t_rwmutex()
+{
+ pthread_rwlock_destroy(&_lock);
+}
+
+void t_rwmutex::lockRead()
+{
+ int err = pthread_rwlock_rdlock(&_lock);
+ if (err != 0)
+ throw std::logic_error("Mutex lock failed");
+}
+
+void t_rwmutex::lockWrite()
+{
+ int err = pthread_rwlock_wrlock(&_lock);
+ if (err != 0)
+ throw std::logic_error("Mutex lock failed");
+}
+
+void t_rwmutex::unlock()
+{
+ pthread_rwlock_unlock(&_lock);
+}
diff --git a/src/threads/mutex.h b/src/threads/mutex.h
index 9970e08..16f314d 100644
--- a/src/threads/mutex.h
+++ b/src/threads/mutex.h
@@ -21,6 +21,7 @@
#include <errno.h>
#include <pthread.h>
+// #include <iostream>
/**
* @file
@@ -83,4 +84,45 @@ public:
~t_mutex_guard();
};
+class t_rwmutex {
+protected:
+ pthread_rwlock_t _lock;
+public:
+ t_rwmutex();
+ ~t_rwmutex();
+
+ void lockRead();
+ void lockWrite();
+ void unlock();
+};
+
+class t_rwmutex_reader {
+private:
+ t_rwmutex& _mutex;
+public:
+ t_rwmutex_reader(t_rwmutex& mutex) : _mutex(mutex) {
+ // std::cout << "mtx rd lock " << (void*)&_mutex << std::endl;
+ _mutex.lockRead();
+ }
+ ~t_rwmutex_reader() {
+ // std::cout << "mtx rd unlock " << (void*)&_mutex << std::endl;
+ _mutex.unlock();
+ }
+};
+
+class t_rwmutex_writer {
+private:
+ t_rwmutex& _mutex;
+public:
+ t_rwmutex_writer(t_rwmutex& mutex) : _mutex(mutex) {
+ // std::cout << "mtx wr lock " << (void*)&_mutex << std::endl;
+ _mutex.lockWrite();
+ }
+ ~t_rwmutex_writer() {
+ // std::cout << "mtx wr unlock " << (void*)&_mutex << std::endl;
+ _mutex.unlock();
+ }
+};
+
+
#endif