1 /*
2 * Copyright (C) 2012 FRAFOS GmbH
3 *
4 * Development sponsored by Sipwise GmbH.
5 *
6 * This file is part of SEMS, a free SIP media server.
7 *
8 * SEMS is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. This program is released under
12 * the GPL with the additional exemption that compiling, linking,
13 * and/or using OpenSSL is allowed.
14 *
15 * For a license to use the SEMS software under conditions
16 * other than those described here, or to purchase support for this
17 * software, please contact iptel.org by e-mail at the following addresses:
18 * info@iptel.org
19 *
20 * SEMS is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30 #include "AmSipSubscriptionContainer.h"
31 #include "AmSession.h"
32 #include "AmEventDispatcher.h"
33
34 #define SUBSCRIPTION_CONTAINER_EVQ_ID "_subscription_container_"
35
_AmSipSubscriptionContainer()36 _AmSipSubscriptionContainer::_AmSipSubscriptionContainer()
37 : initialized(false)
38 {
39 }
40
~_AmSipSubscriptionContainer()41 _AmSipSubscriptionContainer::~_AmSipSubscriptionContainer() {
42 }
43
initialize()44 void _AmSipSubscriptionContainer::initialize() {
45 if (!initialized) {
46 // AmEventDispatcher::instance()->addEventQueue(SUBSCRIPTION_CONTAINER_EVQ_ID, this);
47 initialized = true;
48 DBG("Starting SIP Subscription client thread ([%p])\n", this);
49 start();
50 }
51 }
52
53 string _AmSipSubscriptionContainer::
createSubscription(const AmSipSubscriptionInfo & info,const string & sess_link,unsigned int wanted_expires)54 createSubscription(const AmSipSubscriptionInfo& info,
55 const string& sess_link,
56 unsigned int wanted_expires)
57 {
58 initialize();
59 AmSipSubscriptionDialog* new_sub = new AmSipSubscriptionDialog(info,sess_link,
60 this);
61
62 string handle = new_sub->getLocalTag();
63
64 subscriptions_mut.lock();
65 subscriptions[handle] = new_sub;
66 AmEventDispatcher::instance()->addEventQueue(handle, this);
67 if (new_sub->subscribe(wanted_expires) < 0) {
68 DBG("subscribe failed - removing subscription\b");
69 AmEventDispatcher::instance()->delEventQueue(handle);
70 subscriptions.erase(handle);
71 subscriptions_mut.unlock();
72 delete new_sub;
73 return "";
74 }
75 subscriptions_mut.unlock();
76
77 return handle;
78 }
79
refreshSubscription(const string & sub_handle,unsigned int wanted_expires)80 bool _AmSipSubscriptionContainer::refreshSubscription(const string& sub_handle,
81 unsigned int wanted_expires) {
82 bool res = true;
83 subscriptions_mut.lock();
84 AmSipSubscriptionMapIter it = subscriptions.find(sub_handle);
85 if (it != subscriptions.end()) {
86 DBG("refreshing subscription '%s'\n", sub_handle.c_str());
87 res = it->second->subscribe(wanted_expires);
88 } else {
89 DBG("subscription '%s' already removed\n", sub_handle.c_str());
90 res = false;
91 }
92 subscriptions_mut.unlock();
93 return res;
94 }
95
removeSubscription(const string & sub_handle)96 void _AmSipSubscriptionContainer::removeSubscription(const string& sub_handle) {
97 subscriptions_mut.lock();
98 AmSipSubscriptionMapIter it = subscriptions.find(sub_handle);
99 if (it != subscriptions.end()) {
100 DBG("unsubscribing subscription '%s'\n", sub_handle.c_str());
101 it->second->subscribe(0);
102 } else {
103 DBG("subscription '%s' already removed - ignoring\n", sub_handle.c_str());
104 }
105 subscriptions_mut.unlock();
106 }
107
108 // AmEventProcessingThread
onEvent(AmEvent * event)109 void _AmSipSubscriptionContainer::onEvent(AmEvent* event)
110 {
111 AmSipRequestEvent* sip_req_ev = dynamic_cast<AmSipRequestEvent*>(event);
112 if (sip_req_ev) {
113 // DBG("got SIP request: '%s'\n", sip_req_ev->req.print().c_str());
114 DBG("got SIP request: %s %s\n",
115 sip_req_ev->req.method.c_str(), sip_req_ev->req.r_uri.c_str());
116 string ltag = sip_req_ev->req.to_tag;
117
118 subscriptions_mut.lock();
119 AmSipSubscriptionMapIter it = subscriptions.find(ltag);
120 if (it == subscriptions.end()) {
121 subscriptions_mut.unlock();
122 WARN("got SIP request '%s' for unknown subscription '%s'\n",
123 sip_req_ev->req.print().c_str(), ltag.c_str());
124 AmSipDialog::reply_error(sip_req_ev->req, 481, SIP_REPLY_NOT_EXIST);
125 return;
126 }
127 it->second->onRxRequest(sip_req_ev->req);
128 if (!(it->second->getUsages() > 0)) {
129 DBG("subscription '%s' terminated - removing\n", it->second->getDescription().c_str());
130 delete it->second;
131 subscriptions.erase(it);
132 AmEventDispatcher::instance()->delEventQueue(ltag);
133 }
134 subscriptions_mut.unlock();
135 return;
136 }
137
138 AmSipReplyEvent* sip_reply_ev = dynamic_cast<AmSipReplyEvent*>(event);
139 if (sip_reply_ev) {
140 DBG("got SIP reply: '%s'\n", sip_reply_ev->reply.print().c_str());
141 string ltag = sip_reply_ev->reply.from_tag;
142
143 subscriptions_mut.lock();
144 AmSipSubscriptionMapIter it = subscriptions.find(ltag);
145 if (it == subscriptions.end()) {
146 subscriptions_mut.unlock();
147 WARN("got SIP reply '%s' for unknown subscription '%s'\n",
148 sip_reply_ev->reply.print().c_str(), ltag.c_str());
149
150 return;
151 }
152 it->second->onRxReply(sip_reply_ev->reply);
153 if (!(it->second->getUsages() > 0)) {
154 DBG("subscription '%s' terminated - removing\n", it->second->getDescription().c_str());
155 delete it->second;
156 subscriptions.erase(it);
157 AmEventDispatcher::instance()->delEventQueue(ltag);
158 }
159 subscriptions_mut.unlock();
160 return;
161 }
162
163 SingleSubTimeoutEvent* to_ev = dynamic_cast<SingleSubTimeoutEvent*>(event);
164 if(to_ev) {
165 DBG("got timeout event: %s/%i/%p\n",
166 to_ev->ltag.c_str(), to_ev->timer_id, to_ev->sub);
167
168 string ltag = to_ev->ltag;
169
170 subscriptions_mut.lock();
171 AmSipSubscriptionMapIter it = subscriptions.find(ltag);
172 if (it == subscriptions.end()) {
173 subscriptions_mut.unlock();
174 WARN("got timeout event '%i/%p' for unknown subscription '%s'\n",
175 to_ev->timer_id, to_ev->sub, ltag.c_str());
176
177 return;
178 }
179 it->second->onTimeout(to_ev->timer_id, to_ev->sub);
180 if (!(it->second->getUsages() > 0)) {
181 DBG("subscription '%s' terminated - removing\n", it->second->getDescription().c_str());
182 delete it->second;
183 subscriptions.erase(it);
184 AmEventDispatcher::instance()->delEventQueue(ltag);
185 }
186 subscriptions_mut.unlock();
187 return;
188 }
189 }
190
191
192