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