1 /**
2 * engine.cpp
3 * This file is part of the YATE Project http://YATE.null.ro
4 *
5 * Yet Another Signalling Stack - implements the support for SS7, ISDN and PSTN
6 *
7 * Yet Another Telephony Engine - a fully featured software PBX and IVR
8 * Copyright (C) 2004-2014 Null Team
9 *
10 * This software is distributed under multiple licenses;
11 * see the COPYING file in the main directory for licensing
12 * information for this specific distribution.
13 *
14 * This use of this software may be subject to additional restrictions.
15 * See the LEGAL file in the main directory for details.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #include "yatesig.h"
23 #include <yateversn.h>
24
25 #include <string.h>
26
27 // Maximum wait for a non-critical mutex acquisition
28 #ifndef MAX_LOCK_WAIT
29 #define MAX_LOCK_WAIT 10000
30 #endif
31
32 #define MIN_TICK_SLEEP 500
33 #define DEF_TICK_SLEEP 5000
34 #define MAX_TICK_SLEEP 50000
35
36 namespace TelEngine {
37
38 class SignallingThreadPrivate : public Thread
39 {
40 public:
SignallingThreadPrivate(SignallingEngine * engine,const char * name,Priority prio)41 inline SignallingThreadPrivate(SignallingEngine* engine, const char* name, Priority prio)
42 : Thread(name,prio), m_engine(engine)
43 { }
44 virtual ~SignallingThreadPrivate();
45 virtual void run();
46
47 private:
48 SignallingEngine* m_engine;
49 };
50
51 };
52
53
54 using namespace TelEngine;
55
56 static ObjList s_factories;
57 static Mutex s_mutex(true,"SignallingFactory");
58
59 // Retrieve a value from a list
60 // Shift it if upper bits are set and mask is not set
61 // Mask it with a given mask
fixValue(const NamedList & list,const String & param,const TokenDict * dict,unsigned char mask,unsigned char upperMask,unsigned char shift)62 static inline unsigned char fixValue(const NamedList& list, const String& param,
63 const TokenDict* dict, unsigned char mask, unsigned char upperMask, unsigned char shift)
64 {
65 unsigned char val = (unsigned char)list.getIntValue(param,dict,0);
66 if (0 != (val & upperMask) && 0 == (val & mask))
67 val >>= shift;
68 return val & mask;
69 }
70
SignallingFactory(bool fallback)71 SignallingFactory::SignallingFactory(bool fallback)
72 {
73 s_mutex.lock();
74 if (!s_factories.find(this)) {
75 ObjList* l = fallback ? s_factories.append(this) : s_factories.insert(this);
76 l->setDelete(false);
77 }
78 s_mutex.unlock();
79 }
80
~SignallingFactory()81 SignallingFactory::~SignallingFactory()
82 {
83 s_mutex.lock();
84 s_factories.remove(this,false);
85 s_mutex.unlock();
86 }
87
build(const String & type,NamedList * name)88 SignallingComponent* SignallingFactory::build(const String& type, NamedList* name)
89 {
90 if (type.null())
91 return 0;
92 NamedList dummy(type);
93 if (!name)
94 name = &dummy;
95 Lock lock(s_mutex);
96 for (ObjList* l = &s_factories; l; l = l->next()) {
97 SignallingFactory* f = static_cast<SignallingFactory*>(l->get());
98 if (!f)
99 continue;
100 DDebug(DebugAll,"Attempting to create a '%s' %s using factory %p",
101 name->c_str(),type.c_str(),f);
102 SignallingComponent* obj = f->create(type,*name);
103 if (obj)
104 return obj;
105 }
106 lock.drop();
107 DDebug(DebugInfo,"Factory creating default '%s' named '%s'",type.c_str(),name->c_str());
108 // now build some objects we know about
109 if (type == YSTRING("SS7MTP2"))
110 return new SS7MTP2(*name);
111 else if (type == YSTRING("SS7M2PA"))
112 return new SS7M2PA(*name);
113 else if (type == YSTRING("SS7MTP3"))
114 return new SS7MTP3(*name);
115 else if (type == YSTRING("SS7Router"))
116 return new SS7Router(*name);
117 else if (type == YSTRING("SS7Management"))
118 return new SS7Management(*name);
119 else if (type == YSTRING("ISDNQ921"))
120 return new ISDNQ921(*name,*name);
121 else if (type == YSTRING("ISDNQ931"))
122 return new ISDNQ931(*name,*name);
123 else if (type == YSTRING("ISDNQ931Monitor"))
124 return new ISDNQ931Monitor(*name,*name);
125 Debug(DebugMild,"Factory could not create '%s' named '%s'",type.c_str(),name->c_str());
126 return 0;
127 }
128
buildInternal(const String & type,NamedList * name)129 void* SignallingFactory::buildInternal(const String& type, NamedList* name)
130 {
131 SignallingComponent* c = build(type,name);
132 if (!c)
133 return 0;
134 void* raw = c->getObject(type);
135 if (!raw)
136 Debug(DebugFail,"Built component %p could not be casted back to type '%s'",c,type.c_str());
137 #ifdef DEBUG
138 else
139 Debug(DebugAll,"Built component %p type '%s' interface at %p",c,type.c_str(),raw);
140 #endif
141 return raw;
142 }
143
144
SignallingComponent(const char * name,const NamedList * params,const char * type)145 SignallingComponent::SignallingComponent(const char* name, const NamedList* params, const char* type)
146 : m_engine(0), m_compType(type)
147 {
148 if (params) {
149 name = params->getValue(YSTRING("debugname"),name);
150 m_compType = params->getValue(YSTRING("type"),m_compType);
151 debugLevel(params->getIntValue(YSTRING("debuglevel"),-1));
152 }
153 DDebug(engine(),DebugAll,"Component '%s' created [%p]",name,this);
154 setName(name);
155 }
156
setName(const char * name)157 void SignallingComponent::setName(const char* name)
158 {
159 debugName(0);
160 m_name = name;
161 debugName(m_name);
162 }
163
~SignallingComponent()164 SignallingComponent::~SignallingComponent()
165 {
166 DDebug(engine(),DebugAll,"Component '%s' deleted [%p]",toString().c_str(),this);
167 }
168
destroyed()169 void SignallingComponent::destroyed()
170 {
171 detach();
172 }
173
toString() const174 const String& SignallingComponent::toString() const
175 {
176 return m_name;
177 }
178
initialize(const NamedList * config)179 bool SignallingComponent::initialize(const NamedList* config)
180 {
181 return true;
182 }
183
resolveConfig(const String & cmpName,NamedList & params,const NamedList * config)184 bool SignallingComponent::resolveConfig(const String& cmpName, NamedList& params, const NamedList* config)
185 {
186 if (!config)
187 return false;
188 String name = config->getValue(cmpName,params);
189 if (!(name && !name.toBoolean(false)))
190 return false;
191 static_cast<String&>(params) = name;
192 NamedString* param = config->getParam(params);
193 NamedPointer* ptr = YOBJECT(NamedPointer,param);
194 NamedList* ifConfig = ptr ? YOBJECT(NamedList,ptr->userData()) : 0;
195 if (ifConfig)
196 params.copyParams(*ifConfig);
197 else {
198 if (config->hasSubParams(params + "."))
199 params.copySubParams(*config,params + ".");
200 else
201 params.addParam("local-config","true");
202 }
203 return true;
204 }
205
control(NamedList & params)206 bool SignallingComponent::control(NamedList& params)
207 {
208 return false;
209 }
210
controlCreate(const char * oper)211 NamedList* SignallingComponent::controlCreate(const char* oper)
212 {
213 if (m_name.null())
214 return 0;
215 NamedList* params = new NamedList("chan.control");
216 params->addParam("component",m_name);
217 if (!TelEngine::null(oper))
218 params->addParam("operation",oper);
219 return params;
220 }
221
controlExecute(NamedList * params)222 bool SignallingComponent::controlExecute(NamedList* params)
223 {
224 bool ok = false;
225 if (params) {
226 ok = control(*params);
227 TelEngine::destruct(params);
228 }
229 return ok;
230 }
231
232
engine(SignallingEngine * eng)233 void SignallingComponent::engine(SignallingEngine* eng)
234 {
235 if (eng == m_engine)
236 return;
237 if (eng)
238 eng->insert(this);
239 else
240 detach();
241 }
242
insert(SignallingComponent * component)243 void SignallingComponent::insert(SignallingComponent* component)
244 {
245 if (!component)
246 return;
247 if (m_engine) {
248 // we have an engine - force the other component in the same
249 m_engine->insert(component);
250 return;
251 }
252 if (component->engine())
253 // insert ourselves in the other's engine
254 component->engine()->insert(this);
255 }
256
detach()257 void SignallingComponent::detach()
258 {
259 debugChain();
260 if (m_engine) {
261 m_engine->remove(this);
262 m_engine = 0;
263 }
264 }
265
timerTick(const Time & when)266 void SignallingComponent::timerTick(const Time& when)
267 {
268 XDebug(engine(),DebugAll,"Timer ticked for component '%s' [%p]",
269 toString().c_str(),this);
270 }
271
tickSleep(unsigned long usec) const272 unsigned long SignallingComponent::tickSleep(unsigned long usec) const
273 {
274 return m_engine ? m_engine->tickSleep(usec) : 0;
275 }
276
notify(NamedList & notifs)277 void SignallingNotifier::notify(NamedList& notifs)
278 {
279 DDebug(DebugInfo,"SignallingNotifier::notify() [%p] stub",this);
280 }
281
cleanup()282 void SignallingNotifier::cleanup()
283 {
284 DDebug(DebugInfo,"SignallingNotifier::cleanup() [%p] stub",this);
285 }
286
287
288 static SignallingEngine* s_self = 0;
289 long SignallingEngine::s_maxLockWait = MAX_LOCK_WAIT;
290
SignallingEngine(const char * name)291 SignallingEngine::SignallingEngine(const char* name)
292 : Mutex(true,"SignallingEngine"),
293 m_thread(0),
294 m_usecSleep(DEF_TICK_SLEEP), m_tickSleep(0)
295 {
296 debugName(name);
297 }
298
~SignallingEngine()299 SignallingEngine::~SignallingEngine()
300 {
301 if (m_thread) {
302 Debug(this,DebugCrit,
303 "Engine destroyed with worker thread still running [%p]",this);
304 stop();
305 }
306 lock();
307 if (s_self == this)
308 s_self = 0;
309 unsigned int n = m_components.count();
310 if (n)
311 Debug(this,DebugNote,"Cleaning up %u components [%p]",n,this);
312 m_components.clear();
313 unlock();
314 }
315
self(bool create)316 SignallingEngine* SignallingEngine::self(bool create)
317 {
318 if (create && !s_self) {
319 // if mutex debugging is in force don't limit the lock time
320 if (Lockable::wait())
321 s_maxLockWait = -1;
322 s_self = new SignallingEngine;
323 }
324 return s_self;
325 }
326
find(const String & name)327 SignallingComponent* SignallingEngine::find(const String& name)
328 {
329 Lock mylock(this);
330 return static_cast<SignallingComponent*>(m_components[name]);
331 }
332
find(const String & name,const String & type,const SignallingComponent * start)333 SignallingComponent* SignallingEngine::find(const String& name, const String& type, const SignallingComponent* start)
334 {
335 XDebug(this,DebugAll,"Engine finding '%s' of type %s from %p [%p]",
336 name.c_str(),type.c_str(),start,this);
337 Lock mylock(this);
338 ObjList* l = m_components.skipNull();
339 if (start) {
340 l = m_components.find(start);
341 if (!l)
342 return 0;
343 l = l->skipNext();
344 }
345 for (; l; l = l->skipNext()) {
346 SignallingComponent* c = static_cast<SignallingComponent*>(l->get());
347 if ((name.null() || (c->toString() == name)) &&
348 (type.null() || c->getObject(type)))
349 return c;
350 }
351 return 0;
352 }
353
find(const SignallingComponent * component)354 bool SignallingEngine::find(const SignallingComponent* component)
355 {
356 if (!component)
357 return false;
358 Lock mylock(this);
359 DDebug(this,DebugAll,"Engine finding component @%p [%p]",component,this);
360 return m_components.find(component) != 0;
361 }
362
build(const String & type,NamedList & params,bool init,bool ref)363 SignallingComponent* SignallingEngine::build(const String& type, NamedList& params, bool init, bool ref)
364 {
365 XDebug(this,DebugAll,"Engine building '%s' of type %s [%p]",
366 params.c_str(),type.c_str(),this);
367 Lock mylock(this);
368 SignallingComponent* c = find(params,type);
369 if (c && (ref ? c->ref() : c->alive())) {
370 DDebug(this,DebugAll,"Engine returning existing component '%s' @%p (%d) [%p]",
371 c->toString().c_str(),c,c->refcount(),this);
372 return c;
373 }
374 c = SignallingFactory::build(type,¶ms);
375 DDebug(this,DebugAll,"Created new component '%s' @%p [%p]",
376 c->toString().c_str(),c,this);
377 insert(c);
378 if (init && c)
379 c->initialize(¶ms);
380 return c;
381 }
382
insert(SignallingComponent * component)383 void SignallingEngine::insert(SignallingComponent* component)
384 {
385 if (!component)
386 return;
387 Lock mylock(this);
388 if (component->engine() == this)
389 return;
390 #ifdef DEBUG
391 const char* dupl = m_components.find(component->toString()) ? " (duplicate)" : "";
392 Debug(this,DebugAll,"Engine inserting component '%s'%s @%p [%p]",
393 component->toString().c_str(),dupl,component,this);
394 #endif
395 component->detach();
396 component->m_engine = this;
397 component->debugChain(this);
398 m_components.append(component);
399 }
400
remove(SignallingComponent * component)401 void SignallingEngine::remove(SignallingComponent* component)
402 {
403 if (!component)
404 return;
405 Lock mylock(this);
406 if (component->engine() != this)
407 return;
408 DDebug(this,DebugAll,"Engine removing component @%p '%s' [%p]",
409 component,component->toString().c_str(),this);
410 m_components.remove(component,false);
411 component->m_engine = 0;
412 component->detach();
413 }
414
remove(const String & name)415 bool SignallingEngine::remove(const String& name)
416 {
417 if (name.null())
418 return false;
419 Lock mylock(this);
420 SignallingComponent* component = find(name);
421 if (!component)
422 return false;
423 DDebug(this,DebugAll,"Engine removing component '%s' @%p [%p]",
424 component->toString().c_str(),component,this);
425 component->m_engine = 0;
426 component->detach();
427 m_components.remove(component);
428 return true;
429 }
430
notify(SignallingComponent * component,NamedList notifs)431 void SignallingEngine::notify(SignallingComponent* component, NamedList notifs)
432 {
433 if (!(m_notifier && component))
434 return;
435 Debug(this,DebugAll,"Engine [%p] sending notify from '%s' [%p]",this,component->toString().c_str(),component);
436 m_notifier->notify(notifs);
437 }
438
control(NamedList & params)439 bool SignallingEngine::control(NamedList& params)
440 {
441 bool ok = false;
442 Lock mylock(this);
443 for (ObjList* l = m_components.skipNull(); l; l = l->skipNext())
444 ok = static_cast<SignallingComponent*>(l->get())->control(params) || ok;
445 // Do not add operation-status here !!
446 // The handler should return false because the message wasn't processed
447 // by any component
448 return ok;
449 }
450
start(const char * name,Thread::Priority prio,unsigned long usec)451 bool SignallingEngine::start(const char* name, Thread::Priority prio, unsigned long usec)
452 {
453 Lock mylock(this);
454 if (m_thread)
455 return m_thread->running();
456 // defaults and sanity checks
457 if (usec == 0)
458 usec = DEF_TICK_SLEEP;
459 else if (usec < MIN_TICK_SLEEP)
460 usec = MIN_TICK_SLEEP;
461 else if (usec > MAX_TICK_SLEEP)
462 usec = MAX_TICK_SLEEP;
463
464 SignallingThreadPrivate* tmp = new SignallingThreadPrivate(this,name,prio);
465 if (tmp->startup()) {
466 m_usecSleep = usec;
467 m_thread = tmp;
468 DDebug(this,DebugInfo,"Engine started worker thread [%p]",this);
469 return true;
470 }
471 delete tmp;
472 Debug(this,DebugCrit,"Engine failed to start worker thread [%p]",this);
473 return false;
474 }
475
stop()476 void SignallingEngine::stop()
477 {
478 // TODO: experimental: remove commented if it's working
479 if (!m_thread)
480 return;
481 m_thread->cancel(false);
482 while (m_thread)
483 Thread::yield(true);
484 Debug(this,DebugAll,"Engine stopped worker thread [%p]",this);
485 #if 0
486 lock();
487 SignallingThreadPrivate* tmp = m_thread;
488 m_thread = 0;
489 if (tmp) {
490 delete tmp;
491 DDebug(this,DebugInfo,"Engine stopped worker thread [%p]",this);
492 }
493 unlock();
494 #endif
495 }
496
thread() const497 Thread* SignallingEngine::thread() const
498 {
499 return m_thread;
500 }
501
tickSleep(unsigned long usec)502 unsigned long SignallingEngine::tickSleep(unsigned long usec)
503 {
504 if (m_tickSleep > usec)
505 m_tickSleep = usec;
506 return m_tickSleep;
507 }
508
timerTick(const Time & when)509 unsigned long SignallingEngine::timerTick(const Time& when)
510 {
511 RefPointer<SignallingComponent> c;
512 lock();
513 m_tickSleep = m_usecSleep;
514 ListIterator iter(m_components);
515 while ((c = static_cast<SignallingComponent*>(iter.get()))) {
516 unlock();
517 c->timerTick(when);
518 c = 0;
519 lock();
520 }
521 unsigned long rval = m_tickSleep;
522 m_tickSleep = m_usecSleep;
523 unlock();
524 return rval;
525 }
526
maxLockWait(long maxWait)527 void SignallingEngine::maxLockWait(long maxWait)
528 {
529 if (maxWait < 0)
530 maxWait = -1;
531 else if (maxWait < MIN_TICK_SLEEP)
532 maxWait = MIN_TICK_SLEEP;
533 s_maxLockWait = maxWait;
534 }
535
~SignallingThreadPrivate()536 SignallingThreadPrivate::~SignallingThreadPrivate()
537 {
538 if (m_engine)
539 m_engine->m_thread = 0;
540 }
541
run()542 void SignallingThreadPrivate::run()
543 {
544 for (;;) {
545 if (m_engine) {
546 Time t;
547 unsigned long sleepTime = m_engine->timerTick(t);
548 if (sleepTime) {
549 usleep(sleepTime,true);
550 continue;
551 }
552 }
553 yield(true);
554 }
555 }
556
557
558 /*
559 * SignallingTimer
560 */
561 // Retrieve a timer interval from a list of parameters
getInterval(const NamedList & params,const char * param,unsigned int minVal,unsigned int defVal,unsigned int maxVal,bool allowDisable)562 unsigned int SignallingTimer::getInterval(const NamedList& params, const char* param,
563 unsigned int minVal, unsigned int defVal, unsigned int maxVal, bool allowDisable)
564 {
565 unsigned int val = (unsigned int)params.getIntValue(param,defVal);
566 if (!val)
567 return allowDisable ? 0 : minVal;
568 if (val < minVal)
569 return minVal;
570 if (maxVal && val > maxVal)
571 return maxVal;
572 return val;
573 }
574
575
576 /**
577 * SignallingUtils
578 */
579
580 // Coding standard as defined in Q.931/Q.850
581 static const TokenDict s_dict_codingStandard[] = {
582 {"CCITT", 0x00},
583 {"ISO/IEC", 0x01},
584 {"national", 0x02},
585 {"network specific", 0x03},
586 {0,0}
587 };
588
589 // Locations as defined in Q.850
590 static const TokenDict s_dict_location[] = {
591 {"U", 0x00}, // User
592 {"LPN", 0x01}, // Private network serving the local user
593 {"LN", 0x02}, // Public network serving the local user
594 {"TN", 0x03}, // Transit network
595 {"RLN", 0x04}, // Public network serving the remote user
596 {"RPN", 0x05}, // Private network serving the remote user
597 {"INTL", 0x07}, // International network
598 {"BI", 0x0a}, // Network beyond the interworking point
599 {0,0}
600 };
601
602 // Q.850 2.2.5. Cause class: Bits 4-6
603 // Q.850 Table 1. Cause value: Bits 0-6
604 // Defined for CCITT coding standard
605 static const TokenDict s_dict_causeCCITT[] = {
606 // normal-event class
607 {"normal-event", 0x00},
608 {"unallocated", 0x01}, // Unallocated (unassigned) number
609 {"noroute-to-network", 0x02}, // No route to specified transit network
610 {"noroute", 0x03}, // No route to destination
611 {"send-info-tone", 0x04}, // Send special information tone
612 {"misdialed-trunk-prefix", 0x05}, // Misdialed trunk prefix
613 {"channel-unacceptable", 0x06}, // Channel unacceptable
614 {"call-delivered", 0x07}, // Call awarded and being delivered in an established channel
615 {"preemption", 0x08}, // Preemption
616 {"preemption-circuit-reserved", 0x09}, // Preemption circuit reserved for re-use
617 {"ported-number", 0x0e}, // QoR: ported number Q.850 Addendum 1 (06/2000)
618 {"excess-digits", 0x0e}, // Excess digits received, call is proceeding
619 {"normal-clearing", 0x10}, // Normal Clearing
620 {"busy", 0x11}, // User busy
621 {"noresponse", 0x12}, // No user responding
622 {"noanswer", 0x13}, // No answer from user (user alerted)
623 {"offline", 0x14}, // Subscriber absent
624 {"rejected", 0x15}, // Call Rejected
625 {"moved", 0x16}, // Number changed
626 {"redirection", 0x17}, // Redirection to new destination Q.850 05/98
627 {"rejected-by-feature", 0x18}, // Call rejected due to feature at the destination Q.850 Amendment 1 (07/2001)
628 {"looping", 0x19}, // Exchange routing error (hop counter) Q.850 05/98
629 {"answered", 0x1a}, // Non-selected user clearing (answered elsewhere)
630 {"out-of-order", 0x1b}, // Destination out of order
631 {"invalid-number", 0x1c}, // Invalid number format
632 {"facility-rejected", 0x1d}, // Facility rejected
633 {"status-enquiry-rsp", 0x1e}, // Response to STATUS ENQUIRY
634 {"normal", 0x1f}, // Normal, unspecified
635 // resource-unavailable class
636 {"resource-unavailable", 0x20}, // Resource unavailable
637 {"congestion", 0x22}, // No circuit/channel available
638 {"channel-congestion", 0x22},
639 {"net-out-of-order", 0x26}, // Network out of order
640 {"frame-mode-conn-down", 0x27}, // Permanent frame mode connection out of service
641 {"frame-mode-conn-up", 0x28}, // Permanent frame mode connection operational
642 {"noconn", 0x29},
643 {"temporary-failure", 0x29}, // Temporary failure
644 {"congestion", 0x2a}, // Switching equipment congestion
645 {"switch-congestion", 0x2a},
646 {"access-info-discarded", 0x2b}, // Access information discarded
647 {"channel-unavailable", 0x2c}, // Requested channel not available
648 {"preemption-congestion", 0x2e}, // Precedence call blocked
649 {"noresource", 0x2f}, // Resource unavailable, unspecified
650 {"service-unavailable", 0x30}, // Service or option not available
651 {"qos-unavailable", 0x31}, // Quality of service unavailable
652 {"facility-not-subscribed", 0x32}, // Requested facility not subscribed
653 {"forbidden-out", 0x35}, // Outgoing call barred within CUG
654 {"forbidden-in", 0x37}, // Incoming call barred within CUG
655 {"bearer-cap-not-auth", 0x39}, // Bearer capability not authorized
656 {"bearer-cap-not-available", 0x3a}, // Bearer capability not presently available
657 {"nomedia", 0x3a},
658 {"invalid-access-info-out", 0x3e}, // Inconsistency in designated outgoing access information and subscriber class
659 {"service-unavailable", 0x3f}, // Service or option not available
660 // service-not-implemented class
661 {"bearer-cap-not-implemented", 0x41}, // Bearer capability not implemented
662 {"channel-type-not-implemented", 0x42}, // Channel type not implemented
663 {"facility-not-implemented", 0x45}, // Requested facility not implemented
664 {"restrict-bearer-cap-avail", 0x46}, // Only restricted digital information bearer capability is available
665 {"service-not-implemented", 0x4f}, // Service or option not implemented, unspecified
666 // invalid-message class
667 {"invalid-callref", 0x51}, // Invalid call reference value
668 {"unknown-channel", 0x52}, // Identified channel does not exist
669 {"unknown-callid", 0x53}, // A suspended call exists, but this call identity does not
670 {"duplicate-callid", 0x54}, // Call identity in use
671 {"no-call-suspended", 0x55}, // No call suspended
672 {"suspended-call-cleared", 0x56}, // Call having the requested call identity has been cleared
673 {"not-subscribed", 0x57}, // User not member of CUG
674 {"incompatible-dest", 0x58}, // Incompatible destination
675 {"unknown-group", 0x5a}, // Non-existent CUG
676 {"invalid-transit-net", 0x5b}, // Invalid transit network selection
677 {"invalid-message", 0x5f}, // Invalid message, unspecified
678 // protocol-error class
679 {"missing-mandatory-ie", 0x60}, // Mandatory information element is missing
680 {"unknown-message", 0x61}, // Message type non-existent or not implemented
681 {"wrong-message", 0x62}, // Message not compatible with call state, non-existent or not implemented
682 {"unknown-ie", 0x63}, // Information element non-existent or not implemented
683 {"invalid-ie", 0x64}, // Invalid information element contents
684 {"wrong-state-message", 0x65}, // Message not compatible with call state
685 {"timeout", 0x66}, // Recovery on timer expiry
686 {"unknown-param-passed-on", 0x67}, // Parameter non-existent or not implemented, passed on
687 {"unknown-param-message-droppped", 0x6e}, // Message with unrecognized parameter, discarded
688 {"protocol-error", 0x6f}, // Protocol error, unspecified
689 // interworking class
690 {"interworking", 0x7f}, // Interworking, unspecified
691 {0,0}
692 };
693
694 // Q.931 4.5.5. Information transfer capability: Bits 0-4
695 // Defined for CCITT coding standard
696 static const TokenDict s_dict_transferCapCCITT[] = {
697 {"speech", 0x00}, // Speech
698 {"udi", 0x08}, // Unrestricted digital information
699 {"rdi", 0x09}, // Restricted digital information
700 {"3.1khz-audio", 0x10}, // 3.1 khz audio
701 {"udi-ta", 0x11}, // Unrestricted digital information with tone/announcements
702 {"video", 0x18}, // Video
703 {0,0}
704 };
705
706 // Q.931 4.5.5. Transfer mode: Bits 5,6
707 // Defined for CCITT coding standard
708 static const TokenDict s_dict_transferModeCCITT[] = {
709 {"circuit", 0x00}, // Circuit switch mode
710 {"packet", 0x02}, // Packet mode
711 {0,0}
712 };
713
714 // Q.931 4.5.5. Transfer rate: Bits 0-4
715 // Defined for CCITT coding standard
716 static const TokenDict s_dict_transferRateCCITT[] = {
717 {"packet", 0x00}, // Packet mode only
718 {"64kbit", 0x10}, // 64 kbit/s
719 {"2x64kbit", 0x11}, // 2x64 kbit/s
720 {"384kbit", 0x13}, // 384 kbit/s
721 {"1536kbit", 0x15}, // 1536 kbit/s
722 {"1920kbit", 0x17}, // 1920 kbit/s
723 {"multirate", 0x18}, // Multirate (64 kbit/s base rate)
724 {0,0}
725 };
726
727 // Q.931 4.5.5. User information Layer 1 protocol: Bits 0-4
728 // Defined for CCITT coding standard
729 static const TokenDict s_dict_formatCCITT[] = {
730 {"v110", 0x01}, // Recomendation V.110 and X.30
731 {"mulaw", 0x02}, // Recomendation G.711 mu-law
732 {"alaw", 0x03}, // Recomendation G.711 A-law
733 {"g721", 0x04}, // Recomendation G.721 32kbit/s ADPCM and I.460
734 {"h221", 0x05}, // Recomendation H.221 and H.242
735 {"h223", 0x06}, // Recomendation H.223 and H.245 videoconference
736 {"non-CCITT", 0x07}, // Non CCITT standardized rate adaption
737 {"v120", 0x08}, // Recomendation V.120
738 {"x31", 0x09}, // Recomendation X.31 HDLC flag stuffing
739 {0,0}
740 };
741
742 const TokenDict* SignallingUtils::s_dictCCITT[5] = {
743 s_dict_causeCCITT,
744 s_dict_formatCCITT,
745 s_dict_transferCapCCITT,
746 s_dict_transferModeCCITT,
747 s_dict_transferRateCCITT
748 };
749
750 // Check if a comma separated list of flags has a given flag
hasFlag(const String & flags,const char * flag)751 bool SignallingUtils::hasFlag(const String& flags, const char* flag)
752 {
753 ObjList* obj = flags.split(',',false);
754 bool found = (obj->find(flag) != 0);
755 TelEngine::destruct(obj);
756 return found;
757 }
758
759 // Append a flag to a comma separated list of flags
appendFlag(String & flags,const char * flag)760 bool SignallingUtils::appendFlag(String& flags, const char* flag)
761 {
762 if (TelEngine::null(flag) || hasFlag(flags,flag))
763 return false;
764 flags.append(flag,",");
765 return true;
766 }
767
768 // Remove a flag from a comma separated list of flags
removeFlag(String & flags,const char * flag)769 bool SignallingUtils::removeFlag(String& flags, const char* flag)
770 {
771 ObjList* obj = flags.split(',',false);
772 ObjList* found = obj->find(flag);
773 if (found) {
774 obj->remove(found,true);
775 flags = "";
776 for (ObjList* o = obj->skipNull(); o; o = o->skipNext())
777 flags.append(*static_cast<String*>(o->get()),",");
778 }
779 TelEngine::destruct(obj);
780 return (found != 0);
781 }
782
783 // Check if a list's parameter (comma separated list of flags) has a given flag
hasFlag(const NamedList & list,const char * param,const char * flag)784 bool SignallingUtils::hasFlag(const NamedList& list, const char* param, const char* flag)
785 {
786 const String* s = list.getParam(param);
787 return s && hasFlag(*s,flag);
788 }
789
790 // Append a flag to a list parameter, create parameter if missing
appendFlag(NamedList & list,const char * param,const char * flag)791 bool SignallingUtils::appendFlag(NamedList& list, const char* param, const char* flag)
792 {
793 String* s = list.getParam(param);
794 if (s)
795 return appendFlag(*s,flag);
796 list.addParam(param,flag);
797 return true;
798 }
799
800 // Add string (keyword) if found or integer parameter to a named list
addKeyword(NamedList & list,const char * param,const TokenDict * tokens,unsigned int val)801 void SignallingUtils::addKeyword(NamedList& list, const char* param, const TokenDict* tokens, unsigned int val)
802 {
803 const char* value = lookup(val,tokens);
804 if (value)
805 list.addParam(param,value);
806 else
807 list.addParam(param,String(val));
808 }
809
810 // Dump a buffer to a list of parameters
dumpData(const SignallingComponent * comp,NamedList & list,const char * param,const unsigned char * buf,unsigned int len,char sep)811 void SignallingUtils::dumpData(const SignallingComponent* comp, NamedList& list, const char* param,
812 const unsigned char* buf, unsigned int len, char sep)
813 {
814 String raw;
815 raw.hexify((void*)buf,len,sep);
816 list.addParam(param,raw);
817 DDebug(comp,DebugAll,"Utils::dumpData dumped %s='%s'",param,raw.safe());
818 }
819
820 // Dump data from a buffer to a list of parameters. The buffer is parsed until (and including)
821 // the first byte with the extension bit (the most significant one) set
dumpDataExt(const SignallingComponent * comp,NamedList & list,const char * param,const unsigned char * buf,unsigned int len,char sep)822 unsigned int SignallingUtils::dumpDataExt(const SignallingComponent* comp, NamedList& list, const char* param,
823 const unsigned char* buf, unsigned int len, char sep)
824 {
825 if (!(buf && len))
826 return 0;
827 unsigned int count = 0;
828 for (; count < len && !(buf[count] & 0x80); count++) ;
829 if (count == len) {
830 Debug(comp,DebugMild,"Utils::dumpDataExt invalid ext bits for %s (len=%u)",param,len);
831 return 0;
832 }
833 count++;
834 dumpData(comp,list,param,buf,count,sep);
835 return count;
836 }
837
838 // Decode a received buffer to a comma separated list of flags
decodeFlags(const SignallingComponent * comp,NamedList & list,const char * param,const SignallingFlags * flags,const unsigned char * buf,unsigned int len)839 bool SignallingUtils::decodeFlags(const SignallingComponent* comp, NamedList& list, const char* param,
840 const SignallingFlags* flags, const unsigned char* buf, unsigned int len)
841 {
842 if (!(flags && buf && len <= sizeof(unsigned int)))
843 return false;
844 unsigned int val = 0;
845 int shift = 0;
846 while (len--) {
847 val |= ((unsigned int)*buf++) << shift;
848 shift += 8;
849 }
850 String tmp;
851 for (; flags->mask; flags++)
852 if ((val & flags->mask) == flags->value)
853 tmp.append(flags->name,",");
854 DDebug(comp,DebugAll,"Utils::decodeFlags. Decoded %s='%s' from %u",param,tmp.safe(),val);
855 list.addParam(param,tmp);
856 return true;
857 }
858
codings()859 const TokenDict* SignallingUtils::codings()
860 {
861 return s_dict_codingStandard;
862 }
863
locations()864 const TokenDict* SignallingUtils::locations()
865 {
866 return s_dict_location;
867 }
868
869 #define Q850_MAX_CAUSE 32
870
871 // Q.850 2.1
decodeCause(const SignallingComponent * comp,NamedList & list,const unsigned char * buf,unsigned int len,const char * prefix,bool isup)872 bool SignallingUtils::decodeCause(const SignallingComponent* comp, NamedList& list,
873 const unsigned char* buf, unsigned int len, const char* prefix, bool isup)
874 {
875 if (!buf)
876 return false;
877 if (len < 2) {
878 Debug(comp,DebugNote,"Utils::decodeCause. Invalid length %u",len);
879 return false;
880 }
881 String causeName = prefix;
882 // Byte 0: Coding standard (bit 5,6), location (bit 0-3)
883 unsigned char coding = (buf[0] & 0x60) >> 5;
884 addKeyword(list,causeName + ".coding",codings(),coding);
885 addKeyword(list,causeName + ".location",locations(),buf[0] & 0x0f);
886 unsigned int crt = 1;
887 // If bit 7 is 0, the next byte should contain the recomendation
888 unsigned char rec = 0;
889 if (!(buf[0] & 0x80)) {
890 rec = buf[1] & 0x7f;
891 // For ISUP there shouldn't be a recomendation byte
892 if (isup)
893 Debug(comp,DebugMild,"Utils::decodeCause. Found recomendation %u for ISUP cause",rec);
894 crt = 2;
895 }
896 if (rec)
897 list.addParam(causeName + ".rec",String(rec));
898 if (crt >= len) {
899 Debug(comp,DebugMild,"Utils::decodeCause. Invalid length %u. Cause value is missing",len);
900 list.addParam(causeName,"");
901 return false;
902 }
903 // Current byte: bits 0..6: cause, bits 5,6: cause class
904 addKeyword(list,causeName,dict(0,coding),buf[crt] & 0x7f);
905 // Rest of data: diagnostic
906 crt++;
907 if (crt < len)
908 dumpData(comp,list,causeName + ".diagnostic",buf + crt,len - crt);
909 return true;
910 }
911
912 // Decode bearer capabilities as defined in Q.931 (Bearer Capabilities) and Q.763 (User Service Information)
913 // Q.931 - 4.5.5 / Q.763 - 3.57
914 // The given sections in comments are from Q.931
decodeCaps(const SignallingComponent * comp,NamedList & list,const unsigned char * buf,unsigned int len,const char * prefix,bool isup)915 bool SignallingUtils::decodeCaps(const SignallingComponent* comp, NamedList& list, const unsigned char* buf,
916 unsigned int len, const char* prefix, bool isup)
917 {
918 if (!buf)
919 return false;
920 if (len < 2) {
921 Debug(comp,DebugMild,"Utils::decodeCaps. Invalid length %u",len);
922 return false;
923 }
924 String capsName = prefix;
925 // Byte 0: Coding standard (bit 5,6), Information transfer capability (bit 0-4)
926 // Byte 1: Transfer mode (bit 5,6), Transfer rate (bit 0-4)
927 unsigned char coding = (buf[0] & 0x60) >> 5;
928 addKeyword(list,capsName + ".coding",codings(),coding);
929 addKeyword(list,capsName + ".transfercap",dict(2,coding),buf[0] & 0x1f);
930 addKeyword(list,capsName + ".transfermode",dict(3,coding),(buf[1] & 0x60) >> 5);
931 u_int8_t rate = buf[1] & 0x1f;
932 addKeyword(list,capsName + ".transferrate",dict(4,coding),rate);
933 // Figure 4.11 Note 1: Next byte is the rate multiplier if the transfer rate is 'multirate' (0x18)
934 u_int8_t crt = 2;
935 if (rate == 0x18) {
936 if (len < 3) {
937 Debug(comp,DebugMild,"Utils::decodeCaps. Invalid length %u. No rate multiplier",len);
938 return false;
939 }
940 addKeyword(list,capsName + ".multiplier",0,buf[2] & 0x7f);
941 crt = 3;
942 }
943 // Get optional extra information
944 // Layer 1 data
945 if (len <= crt)
946 return true;
947 u_int8_t ident = (buf[crt] & 0x60) >> 5;
948 if (ident != 1) {
949 Debug(comp,DebugNote,"Utils::decodeCaps. Invalid layer 1 ident %u",ident);
950 return true;
951 }
952 addKeyword(list,capsName,dict(1,coding),buf[crt] & 0x1f);
953 //TODO: Decode the rest of Layer 1, Layer 2 and Layer 3 data
954 return true;
955 }
956
957 // Encode a comma separated list of flags. Flags can be prefixed with the '-'
958 // character to be reset if previously set
encodeFlags(const SignallingComponent * comp,int & dest,const String & flags,const TokenDict * dict)959 void SignallingUtils::encodeFlags(const SignallingComponent* comp,
960 int& dest, const String& flags, const TokenDict* dict)
961 {
962 if (flags.null() || !dict)
963 return;
964 ObjList* list = flags.split(',',false);
965 DDebug(comp,DebugAll,"Utils::encodeFlags '%s' dest=0x%x",flags.c_str(),dest);
966 for (ObjList* o = list->skipNull(); o; o = o->skipNext()) {
967 String* s = static_cast<String*>(o->get());
968 bool set = !s->startSkip("-",false);
969 const TokenDict* p = dict;
970 for (; p->token && *s != p->token; p++) ;
971 if (!p->token) {
972 DDebug(comp,DebugAll,"Utils::encodeFlags '%s' not found",s->c_str());
973 continue;
974 }
975 DDebug(comp,DebugAll,"Utils::encodeFlags %sset %s=0x%x",
976 set?"":"re",p->token,p->value);
977 if (set)
978 dest |= p->value;
979 else
980 dest &= ~p->value;
981 }
982 TelEngine::destruct(list);
983 }
984
985 // Encode a comma separated list of signalling flags
encodeFlags(const SignallingComponent * comp,const String & flags,const SignallingFlags * dict,const char * paramName)986 unsigned int SignallingUtils::encodeFlags(const SignallingComponent* comp, const String& flags,
987 const SignallingFlags* dict, const char* paramName)
988 {
989 if (!dict)
990 return 0;
991 unsigned int v = 0;
992 ObjList* l = flags.split(',',false);
993 for (ObjList* o = l->skipNull(); o; o = o->skipNext()) {
994 const String* s = static_cast<const String*>(o->get());
995 for (const SignallingFlags* d = dict; d->mask; d++) {
996 if (*s == d->name) {
997 if (v & d->mask) {
998 Debug(comp,DebugMild,"Flag %s. %s overwriting bits 0x%x",
999 paramName,d->name,v & d->mask);
1000 v &= d->mask;
1001 }
1002 v |= d->value;
1003 }
1004 }
1005 }
1006 TelEngine::destruct(l);
1007 return v;
1008 }
1009
1010 // Q.850 2.1
encodeCause(const SignallingComponent * comp,DataBlock & buf,const NamedList & params,const char * prefix,bool isup,bool fail)1011 bool SignallingUtils::encodeCause(const SignallingComponent* comp, DataBlock& buf,
1012 const NamedList& params, const char* prefix, bool isup, bool fail)
1013 {
1014 u_int8_t data[4] = {2,0x80,0x80,0x80};
1015 String causeName = prefix;
1016 // Coding standard (0: CCITT) + location. If no location, set it to 0x0a: "BI"
1017 unsigned char coding = fixValue(params,causeName + ".coding",codings(),0x03,0x60,5);
1018 unsigned char loc = (unsigned char)params.getIntValue(causeName + ".location",locations(),0x0a);
1019 data[1] |= (coding << 5) | (loc & 0x0f);
1020 // Recommendation (only for Q.931)
1021 if (!isup) {
1022 unsigned char rec = (unsigned char)params.getIntValue(causeName + ".rec",0,0);
1023 // Add recommendation. Clear bit 7 of the first byte
1024 data[1] &= 0x7f;
1025 data[2] |= (rec & 0x7f);
1026 data[0] = 3;
1027 }
1028 // Value. Set to normal-clearing if missing for CCITT encoding or
1029 // to 0 for other encoding standards
1030 unsigned char val = (unsigned char)params.getIntValue(causeName,dict(0,coding),!coding ? 0x10 : 0);
1031 data[data[0]] |= (val & 0x7f);
1032 // Diagnostic
1033 DataBlock diagnostic;
1034 const char* tmp = params.getValue(causeName + ".diagnostic");
1035 if (tmp)
1036 diagnostic.unHexify(tmp,strlen(tmp),' ');
1037 // Set data
1038 if (!isup && diagnostic.length() + data[0] + 1 > 32) {
1039 Debug(comp,fail?DebugNote:DebugMild,
1040 "Utils::encodeCause. Cause length %u > 32. %s",
1041 diagnostic.length() + data[0] + 1,fail?"Fail":"Skipping diagnostic");
1042 if (fail)
1043 return false;
1044 diagnostic.clear();
1045 }
1046 u_int8_t len = data[0] + 1;
1047 data[0] += diagnostic.length();
1048 buf.assign(data,len);
1049 buf += diagnostic;
1050 return true;
1051 }
1052
encodeCaps(const SignallingComponent * comp,DataBlock & buf,const NamedList & params,const char * prefix,bool isup)1053 bool SignallingUtils::encodeCaps(const SignallingComponent* comp, DataBlock& buf, const NamedList& params,
1054 const char* prefix, bool isup)
1055 {
1056 u_int8_t data[5] = {2,0x80,0x80,0x80,0x80};
1057 String capsName = prefix;
1058 // Byte 1: Coding standard (bit 5,6), Information transfer capability (bit 0-4)
1059 // Byte 2: Transfer mode (bit 5,6), Transfer rate (bit 0-4)
1060 unsigned char coding = fixValue(params,capsName + ".coding",codings(),0x03,0x60,5);
1061 unsigned char cap = (unsigned char)params.getIntValue(capsName + ".transfercap",dict(2,coding),0);
1062 unsigned char mode = fixValue(params,capsName + ".transfermode",dict(3,coding),0x03,0x60,5);
1063 unsigned char rate = (unsigned char)params.getIntValue(capsName + ".transferrate",dict(4,coding),0x10);
1064 data[1] |= (coding << 5) | (cap & 0x1f);
1065 data[2] |= (mode << 5) | (rate & 0x1f);
1066 if (rate == 0x18) {
1067 data[0] = 3;
1068 rate = (unsigned char)params.getIntValue(capsName + ".multiplier",0,0);
1069 data[3] |= rate & 0x7f;
1070 }
1071 // User information layer data
1072 // Bit 7 = 1, Bits 5,6 = layer (1), Bits 0-4: the value
1073 int format = params.getIntValue(capsName,dict(1,coding),-1);
1074 if (format != -1) {
1075 data[data[0] + 1] |= 0x20 | (((unsigned char)format) & 0x1f);
1076 data[0]++;
1077 }
1078 buf.assign(data,data[0] + 1);
1079 return true;
1080 }
1081
1082 // Parse a list of integers or integer intervals. Source elements must be separated by a
1083 // '.' or ',' character. Integer intervals must be separated by a '-' character.
1084 // Empty elements are silently discarded
parseUIntArray(const String & source,unsigned int min,unsigned int max,unsigned int & count,bool discardDup)1085 unsigned int* SignallingUtils::parseUIntArray(const String& source,
1086 unsigned int min, unsigned int max,
1087 unsigned int& count, bool discardDup)
1088 {
1089 count = 0;
1090 ObjList* list = source.split(((-1!=source.find(','))?',':'.'),false);
1091 if (!list->count()) {
1092 TelEngine::destruct(list);
1093 return 0;
1094 }
1095
1096 unsigned int maxArray = 0;
1097 unsigned int* array = 0;
1098 bool ok = true;
1099 int first, last;
1100
1101 for (ObjList* o = list->skipNull(); o; o = o->skipNext()) {
1102 String* s = static_cast<String*>(o->get());
1103 // Get the interval (may be a single value)
1104 int sep = s->find('-');
1105 if (sep == -1)
1106 first = last = s->toInteger(-1);
1107 else {
1108 first = s->substr(0,sep).toInteger(-1);
1109 last = s->substr(sep + 1).toInteger(-2);
1110 }
1111 if (first < 0 || last < 0 || last < first) {
1112 ok = false;
1113 break;
1114 }
1115 // Resize and copy array if not enough room
1116 unsigned int len = (unsigned int)(last - first + 1);
1117 if (count + len > maxArray) {
1118 maxArray = count + len;
1119 unsigned int* tmp = new unsigned int[maxArray];
1120 if (array) {
1121 ::memcpy(tmp,array,sizeof(unsigned int) * count);
1122 delete[] array;
1123 }
1124 array = tmp;
1125 }
1126 // Add to array code list
1127 for (; first <= last; first++) {
1128 // Check interval
1129 if ((unsigned int)first < min || max < (unsigned int)first) {
1130 ok = false;
1131 break;
1132 }
1133 // Check duplicates
1134 if (discardDup) {
1135 bool dup = false;
1136 for (unsigned int i = 0; i < count; i++)
1137 if (array[i] == (unsigned int)first) {
1138 dup = true;
1139 break;
1140 }
1141 if (dup)
1142 continue;
1143 }
1144 array[count++] = first;
1145 }
1146 if (!ok)
1147 break;
1148 }
1149 TelEngine::destruct(list);
1150
1151 if (ok && count)
1152 return array;
1153 count = 0;
1154 if (array)
1155 delete[] array;
1156 return 0;
1157 }
1158
1159
1160 /*
1161 * SignallingMessageTimerList
1162 */
1163 // Add a pending operation to the list. Start its timer
add(SignallingMessageTimer * m,const Time & when)1164 SignallingMessageTimer* SignallingMessageTimerList::add(SignallingMessageTimer* m,
1165 const Time& when)
1166 {
1167 if (!m)
1168 return 0;
1169 m->stop();
1170 m->start(when.msec());
1171 if (m->global().interval() && !m->global().started())
1172 m->global().start(when.msec());
1173 ObjList* ins = skipNull();
1174 for (; ins; ins = ins->skipNext()) {
1175 SignallingMessageTimer* crt = static_cast<SignallingMessageTimer*>(ins->get());
1176 if (m->fireTime() < crt->fireTime())
1177 break;
1178 }
1179 if (!ins)
1180 append(m);
1181 else
1182 ins->insert(m);
1183 return m;
1184 }
1185
1186 // Check if the first operation timed out
timeout(const Time & when)1187 SignallingMessageTimer* SignallingMessageTimerList::timeout(const Time& when)
1188 {
1189 ObjList* o = skipNull();
1190 if (!o)
1191 return 0;
1192 SignallingMessageTimer* m = static_cast<SignallingMessageTimer*>(o->get());
1193 if (!(m->timeout(when.msec()) || m->global().timeout(when.msec())))
1194 return 0;
1195 o->remove(false);
1196 return m;
1197 }
1198
1199 /* vi: set ts=8 sw=4 sts=4 noet: */
1200