1 /*
2 * Copyright (C) 2006 iptego GmbH
3 *
4 * This file is part of SEMS, a free SIP media server.
5 *
6 * SEMS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. This program is released under
10 * the GPL with the additional exemption that compiling, linking,
11 * and/or using OpenSSL is allowed.
12 *
13 * For a license to use the SEMS software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
16 * info@iptel.org
17 *
18 * SEMS is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28 #include "SIPRegistrarClient.h"
29 #include "AmUtils.h"
30 #include "AmPlugIn.h"
31 #include "AmSessionContainer.h"
32 #include "AmEventDispatcher.h"
33
34 #define MOD_NAME "registrar_client"
35
36 #include <unistd.h>
37
38 //EXPORT_SIP_EVENT_HANDLER_FACTORY(SIPRegistrarClient, MOD_NAME);
39 //EXPORT_PLUGIN_CLASS_FACTORY(SIPRegistrarClient, MOD_NAME);
40
plugin_class_create()41 extern "C" void* plugin_class_create()
42 {
43 SIPRegistrarClient* reg_c = SIPRegistrarClient::instance();
44 assert(dynamic_cast<AmDynInvokeFactory*>(reg_c));
45
46 return (AmPluginFactory*)reg_c;
47 }
48
49
50 //-----------------------------------------------------------
51 SIPRegistrarClient* SIPRegistrarClient::_instance=0;
52
instance()53 SIPRegistrarClient* SIPRegistrarClient::instance()
54 {
55 if(_instance == NULL){
56 _instance = new SIPRegistrarClient(MOD_NAME);
57 }
58
59 return _instance;
60 }
61
SIPRegistrarClient(const string & name)62 SIPRegistrarClient::SIPRegistrarClient(const string& name)
63 : AmEventQueue(this),
64 AmDynInvokeFactory(MOD_NAME),
65 uac_auth_i(NULL),
66 stop_requested(false)
67 {
68 }
69
run()70 void SIPRegistrarClient::run() {
71 DBG("SIPRegistrarClient starting...\n");
72 AmDynInvokeFactory* uac_auth_f = AmPlugIn::instance()->getFactory4Di("uac_auth");
73 if (uac_auth_f == NULL) {
74 DBG("unable to get a uac_auth factory. registrations will not be authenticated.\n");
75 DBG("(do you want to load uac_auth module?)\n");
76 } else {
77 uac_auth_i = uac_auth_f->getInstance();
78 }
79
80 while (!stop_requested.get()) {
81 if (registrations.size()) {
82 unsigned int cnt = 250;
83 while (cnt > 0) {
84 usleep(2000); // every 2 ms
85 processEvents();
86 cnt--;
87 }
88 checkTimeouts();
89 } else {
90 waitForEvent();
91 processEvents();
92 }
93 }
94 }
95
checkTimeouts()96 void SIPRegistrarClient::checkTimeouts() {
97 // DBG("checking timeouts...\n");
98 struct timeval now;
99 gettimeofday(&now, NULL);
100 reg_mut.lock();
101 vector<string> remove_regs;
102
103 for (map<string, AmSIPRegistration*>::iterator it = registrations.begin();
104 it != registrations.end(); it++) {
105 if (it->second->active) {
106 if (it->second->registerExpired(now.tv_sec)) {
107 AmSIPRegistration* reg = it->second;
108 reg->onRegisterExpired();
109 } else if (!it->second->waiting_result &&
110 it->second->timeToReregister(now.tv_sec)) {
111 it->second->doRegistration();
112 }
113 } else if (it->second->remove) {
114 remove_regs.push_back(it->first);
115 } else if (it->second->waiting_result &&
116 it->second->registerSendTimeout(now.tv_sec)) {
117 AmSIPRegistration* reg = it->second;
118 reg->onRegisterSendTimeout();
119 }
120 }
121 for (vector<string>::iterator it = remove_regs.begin();
122 it != remove_regs.end(); it++) {
123 DBG("removing registration\n");
124 AmSIPRegistration* reg = registrations[*it];
125 registrations.erase(*it);
126 if (reg)
127 delete reg;
128 }
129
130 reg_mut.unlock();
131 }
132
onLoad()133 int SIPRegistrarClient::onLoad() {
134 instance()->start();
135 return 0;
136 }
137
onServerShutdown()138 void SIPRegistrarClient::onServerShutdown() {
139 // TODO: properly wait until unregistered, with timeout
140 DBG("shutdown SIP registrar client: deregistering\n");
141 for (std::map<std::string, AmSIPRegistration*>::iterator it=
142 registrations.begin(); it != registrations.end(); it++) {
143 it->second->doUnregister();
144 AmEventDispatcher::instance()->delEventQueue(it->first);
145 }
146
147 stop_requested.set(true);
148 //
149 // setStopped();
150 // return;
151 }
152
process(AmEvent * ev)153 void SIPRegistrarClient::process(AmEvent* ev)
154 {
155 if (ev->event_id == E_SYSTEM) {
156 AmSystemEvent* sys_ev = dynamic_cast<AmSystemEvent*>(ev);
157 if(sys_ev){
158 DBG("Session received system Event\n");
159 if (sys_ev->sys_event == AmSystemEvent::ServerShutdown) {
160 onServerShutdown();
161 }
162 return;
163 }
164 }
165
166 AmSipReplyEvent* sip_rep = dynamic_cast<AmSipReplyEvent*>(ev);
167 if (sip_rep) {
168 onSipReplyEvent(sip_rep);
169 return;
170 }
171
172 SIPNewRegistrationEvent* new_reg = dynamic_cast<SIPNewRegistrationEvent*>(ev);
173 if (new_reg) {
174 onNewRegistration(new_reg);
175 return;
176 }
177
178 SIPRemoveRegistrationEvent* rem_reg = dynamic_cast<SIPRemoveRegistrationEvent*>(ev);
179 if (rem_reg) {
180 onRemoveRegistration(rem_reg);
181 return;
182 }
183
184
185 }
186
onSipReplyEvent(AmSipReplyEvent * ev)187 void SIPRegistrarClient::onSipReplyEvent(AmSipReplyEvent* ev) {
188 AmSIPRegistration* reg = get_reg(ev->reply.from_tag);
189 if (reg != NULL) {
190 reg->getDlg()->onRxReply(ev->reply);
191 }
192 }
193
onNewRegistration(SIPNewRegistrationEvent * new_reg)194 void SIPRegistrarClient::onNewRegistration(SIPNewRegistrationEvent* new_reg) {
195
196 AmSIPRegistration* reg = new AmSIPRegistration(new_reg->handle, new_reg->info,
197 new_reg->sess_link);
198
199 if (uac_auth_i != NULL) {
200 DBG("enabling UAC Auth for new registration.\n");
201
202 // get a sessionEventHandler from uac_auth
203 AmArg di_args,ret;
204 AmArg a;
205 a.setBorrowedPointer(reg);
206 di_args.push(a);
207 di_args.push(a);
208 DBG("arg type is %d\n", a.getType());
209
210 uac_auth_i->invoke("getHandler", di_args, ret);
211 if (!ret.size()) {
212 ERROR("Can not add auth handler to new registration!\n");
213 } else {
214 AmObject* p = ret.get(0).asObject();
215 if (p != NULL) {
216 AmSessionEventHandler* h = dynamic_cast<AmSessionEventHandler*>(p);
217 if (h != NULL)
218 reg->setSessionEventHandler(h);
219 }
220 }
221 }
222
223 add_reg(new_reg->handle, reg);
224 reg->doRegistration();
225 }
226
onRemoveRegistration(SIPRemoveRegistrationEvent * new_reg)227 void SIPRegistrarClient::onRemoveRegistration(SIPRemoveRegistrationEvent* new_reg) {
228 AmSIPRegistration* reg = get_reg(new_reg->handle);
229 if (reg)
230 reg->doUnregister();
231 }
232
233
on_stop()234 void SIPRegistrarClient::on_stop() { }
235
236
onSipReply(const AmSipReply & rep,AmSipDialog::Status old_dlg_status)237 bool SIPRegistrarClient::onSipReply(const AmSipReply& rep, AmSipDialog::Status old_dlg_status) {
238 DBG("got reply with tag '%s'\n", rep.from_tag.c_str());
239
240 if (instance()->hasRegistration(rep.from_tag)) {
241 instance()->postEvent(new AmSipReplyEvent(rep));
242 return true;
243 } else
244 return false;
245 }
246
hasRegistration(const string & handle)247 bool SIPRegistrarClient::hasRegistration(const string& handle) {
248 return get_reg(handle) != NULL;
249 }
250
251 AmSIPRegistration* SIPRegistrarClient::
get_reg(const string & reg_id)252 get_reg(const string& reg_id)
253 {
254 DBG("get registration '%s'\n", reg_id.c_str());
255 AmSIPRegistration* res = NULL;
256 reg_mut.lock();
257 map<string, AmSIPRegistration*>::iterator it =
258 registrations.find(reg_id);
259 if (it!=registrations.end())
260 res = it->second;
261 reg_mut.unlock();
262 DBG("get registration : res = '%ld' (this = %ld)\n", (long)res, (long)this);
263 return res;
264 }
265
266 AmSIPRegistration* SIPRegistrarClient::
get_reg_unsafe(const string & reg_id)267 get_reg_unsafe(const string& reg_id)
268 {
269 // DBG("get registration_unsafe '%s'\n", reg_id.c_str());
270 AmSIPRegistration* res = NULL;
271 map<string, AmSIPRegistration*>::iterator it =
272 registrations.find(reg_id);
273 if (it!=registrations.end())
274 res = it->second;
275 // DBG("get registration_unsafe : res = '%ld' (this = %ld)\n", (long)res, (long)this);
276 return res;
277 }
278
279 AmSIPRegistration* SIPRegistrarClient::
remove_reg(const string & reg_id)280 remove_reg(const string& reg_id) {
281 reg_mut.lock();
282 AmSIPRegistration* reg = remove_reg_unsafe(reg_id);
283 reg_mut.unlock();
284 return reg;
285 }
286
287 AmSIPRegistration* SIPRegistrarClient::
remove_reg_unsafe(const string & reg_id)288 remove_reg_unsafe(const string& reg_id) {
289 DBG("removing registration '%s'\n", reg_id.c_str());
290 AmSIPRegistration* reg = NULL;
291 map<string, AmSIPRegistration*>::iterator it =
292 registrations.find(reg_id);
293 if (it!=registrations.end()) {
294 reg = it->second;
295 registrations.erase(it);
296 }
297
298 AmEventDispatcher::instance()->delEventQueue(reg_id);
299
300 return reg;
301 }
302
303 void SIPRegistrarClient::
add_reg(const string & reg_id,AmSIPRegistration * new_reg)304 add_reg(const string& reg_id, AmSIPRegistration* new_reg)
305 {
306 DBG("adding registration '%s' (this = %ld)\n", reg_id.c_str(), (long)this);
307 AmSIPRegistration* reg = NULL;
308 reg_mut.lock();
309 map<string, AmSIPRegistration*>::iterator it =
310 registrations.find(reg_id);
311 if (it!=registrations.end()) {
312 reg = it->second;
313
314 }
315 registrations[reg_id] = new_reg;
316
317 AmEventDispatcher::instance()->addEventQueue(reg_id,this);
318 reg_mut.unlock();
319
320 if (reg != NULL)
321 delete reg; // old one with the same ltag
322
323 }
324
325
326 // API
createRegistration(const string & domain,const string & user,const string & name,const string & auth_user,const string & pwd,const string & sess_link,const string & proxy,const string & contact,const string & handle)327 string SIPRegistrarClient::createRegistration(const string& domain,
328 const string& user,
329 const string& name,
330 const string& auth_user,
331 const string& pwd,
332 const string& sess_link,
333 const string& proxy,
334 const string& contact,
335 const string& handle) {
336
337 string l_handle = handle.empty() ? AmSession::getNewId() : handle;
338 instance()->
339 postEvent(new SIPNewRegistrationEvent(SIPRegistrationInfo(domain, user,
340 name, auth_user, pwd,
341 proxy, contact),
342 l_handle, sess_link));
343
344 return l_handle;
345 }
346
removeRegistration(const string & handle)347 void SIPRegistrarClient::removeRegistration(const string& handle) {
348 instance()->
349 postEvent(new SIPRemoveRegistrationEvent(handle));
350
351 }
352
getRegistrationState(const string & handle,unsigned int & state,unsigned int & expires_left)353 bool SIPRegistrarClient::getRegistrationState(const string& handle,
354 unsigned int& state,
355 unsigned int& expires_left) {
356 bool res = false;
357 reg_mut.lock();
358
359 AmSIPRegistration* reg = get_reg_unsafe(handle);
360 if (reg) {
361 res = true;
362 state = reg->getState();
363 expires_left = reg->getExpiresLeft();
364 }
365
366 reg_mut.unlock();
367 return res;
368 }
369
listRegistrations(AmArg & res)370 void SIPRegistrarClient::listRegistrations(AmArg& res) {
371 reg_mut.lock();
372
373 for (map<string, AmSIPRegistration*>::iterator it =
374 registrations.begin(); it != registrations.end(); it++) {
375 AmArg r;
376 r["handle"] = it->first;
377 r["domain"] = it->second->getInfo().domain;
378 r["user"] = it->second->getInfo().user;
379 r["name"] = it->second->getInfo().name;
380 r["auth_user"] = it->second->getInfo().auth_user;
381 r["proxy"] = it->second->getInfo().proxy;
382 r["event_sink"] = it->second->getEventSink();
383 r["contact"] = it->second->getInfo().contact;
384 res.push(r);
385 }
386
387 reg_mut.unlock();
388 }
389
390
invoke(const string & method,const AmArg & args,AmArg & ret)391 void SIPRegistrarClient::invoke(const string& method, const AmArg& args,
392 AmArg& ret)
393 {
394 if(method == "createRegistration"){
395 string proxy, contact, handle;
396 if (args.size() > 6)
397 proxy = args.get(6).asCStr();
398 if (args.size() > 7)
399 contact = args.get(7).asCStr();
400 if (args.size() > 8)
401 handle = args.get(8).asCStr();
402
403 ret.push(createRegistration(args.get(0).asCStr(),
404 args.get(1).asCStr(),
405 args.get(2).asCStr(),
406 args.get(3).asCStr(),
407 args.get(4).asCStr(),
408 args.get(5).asCStr(),
409 proxy, contact, handle
410 ).c_str());
411 }
412 else if(method == "removeRegistration"){
413 removeRegistration(args.get(0).asCStr());
414 } else if(method == "getRegistrationState"){
415 unsigned int state;
416 unsigned int expires;
417 if (instance()->getRegistrationState(args.get(0).asCStr(),
418 state, expires)){
419 ret.push(1);
420 ret.push((int)state);
421 ret.push((int)expires);
422 } else {
423 ret.push(AmArg((int)0));
424 }
425 } else if(method == "listRegistrations"){
426 listRegistrations(ret);
427 } else if(method == "_list"){
428 ret.push(AmArg("createRegistration"));
429 ret.push(AmArg("removeRegistration"));
430 ret.push(AmArg("getRegistrationState"));
431 ret.push(AmArg("listRegistrations"));
432 } else
433 throw AmDynInvoke::NotImplemented(method);
434 }
435
436