1 /**
2  * sigcall.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 
24 #include <stdlib.h>
25 #include <string.h>
26 
27 
28 using namespace TelEngine;
29 
30 const TokenDict SignallingCircuit::s_lockNames[] = {
31     {"localhw",            LockLocalHWFail},
32     {"localmaint",         LockLocalMaint},
33     {"lockinghw",          LockingHWFail},
34     {"lockingmaint",       LockingMaint},
35     {"localhwchanged",     LockLocalHWFailChg},
36     {"localmaintchanged",  LockLocalMaintChg},
37     {"resetting",          Resetting},
38     {"remotehw",           LockRemoteHWFail},
39     {"remotemaint",        LockRemoteMaint},
40     {"remotehwchanged",    LockRemoteHWFailChg},
41     {"remotemaintchanged", LockRemoteMaintChg},
42     {0,0},
43 };
44 
45 const TokenDict SignallingCallControl::s_mediaRequired[] = {
46     { "no", SignallingCallControl::MediaNever },
47     { "false", SignallingCallControl::MediaNever },
48     { "off", SignallingCallControl::MediaNever },
49     { "disable", SignallingCallControl::MediaNever },
50     { "answered", SignallingCallControl::MediaAnswered },
51     { "connected", SignallingCallControl::MediaAnswered },
52     { "ringing", SignallingCallControl::MediaRinging },
53     { "progress", SignallingCallControl::MediaRinging },
54     { "yes", SignallingCallControl::MediaAlways },
55     { "true", SignallingCallControl::MediaAlways },
56     { "on", SignallingCallControl::MediaAlways },
57     { "enable", SignallingCallControl::MediaAlways },
58     { 0, 0 }
59 };
60 
61 /**
62  * SignallingCallControl
63  */
SignallingCallControl(const NamedList & params,const char * msgPrefix)64 SignallingCallControl::SignallingCallControl(const NamedList& params,
65 	const char* msgPrefix)
66     : Mutex(true,"SignallingCallControl"),
67       m_mediaRequired(MediaNever),
68       m_verifyEvent(false),
69       m_verifyTimer(0),
70       m_circuits(0),
71       m_strategy(SignallingCircuitGroup::Increment),
72       m_exiting(false)
73 {
74     // Controller location
75     m_location = params.getValue(YSTRING("location"));
76     // Strategy
77     const char* strategy = params.getValue(YSTRING("strategy"),"increment");
78     m_strategy = SignallingCircuitGroup::str2strategy(strategy);
79     String restrict;
80     if (m_strategy != SignallingCircuitGroup::Random)
81 	restrict = params.getValue(YSTRING("strategy-restrict"));
82     if (!restrict.null()) {
83 	if (restrict == "odd")
84 	    m_strategy |= SignallingCircuitGroup::OnlyOdd;
85 	else if (restrict == "even")
86 	    m_strategy |= SignallingCircuitGroup::OnlyEven;
87 	else if (restrict == "odd-fallback")
88 	    m_strategy |= SignallingCircuitGroup::OnlyOdd | SignallingCircuitGroup::Fallback;
89 	else if (restrict == "even-fallback")
90 	    m_strategy |= SignallingCircuitGroup::OnlyEven | SignallingCircuitGroup::Fallback;
91     }
92 
93     // Message prefix
94     m_msgPrefix = params.getValue(YSTRING("message-prefix"),msgPrefix);
95 
96     // Verify event timer
97     m_verifyTimer.interval(params,"verifyeventinterval",10,120,true,true);
98     m_verifyTimer.start();
99 
100     // Media Required
101     m_mediaRequired = (MediaRequired)params.getIntValue(YSTRING("needmedia"),
102 	s_mediaRequired,m_mediaRequired);
103 }
104 
~SignallingCallControl()105 SignallingCallControl::~SignallingCallControl()
106 {
107     attach((SignallingCircuitGroup*)0);
108 }
109 
110 // Attach a signalling circuit group. Set its strategy
attach(SignallingCircuitGroup * circuits)111 SignallingCircuitGroup* SignallingCallControl::attach(SignallingCircuitGroup* circuits)
112 {
113     Lock mylock(this);
114     // Don't attach if it's the same object
115     if (m_circuits == circuits)
116 	return 0;
117     cleanup(circuits ? "circuit group attach" : "circuit group detach");
118     if (m_circuits && circuits)
119 	Debug(DebugNote,
120 	    "SignallingCallControl. Replacing circuit group (%p) with (%p) [%p]",
121 	    m_circuits,circuits,this);
122     SignallingCircuitGroup* tmp = m_circuits;
123     m_circuits = circuits;
124     if (m_circuits) {
125 	Lock lock(m_circuits);
126 	m_circuits->setStrategy(m_strategy);
127     }
128     return tmp;
129 }
130 
131 // Reserve a circuit from a given list in attached group
reserveCircuit(SignallingCircuit * & cic,const char * range,int checkLock,const String * list,bool mandatory,bool reverseRestrict)132 bool SignallingCallControl::reserveCircuit(SignallingCircuit*& cic, const char* range,
133 	int checkLock, const String* list, bool mandatory, bool reverseRestrict)
134 {
135     DDebug(DebugAll,"SignallingCallControl::reserveCircuit(%p,'%s',%d,'%s',%s,%s) [%p]",
136 	cic,range,checkLock,TelEngine::c_safe(list),
137 	String::boolText(mandatory),String::boolText(reverseRestrict),this);
138     Lock mylock(this);
139     releaseCircuit(cic);
140     if (!m_circuits)
141 	return false;
142     if (list) {
143 	int s = -1;
144 	if (!mandatory && reverseRestrict) {
145 	    s = m_circuits->strategy();
146 	    // Use the opposite strategy restriction
147 	    if (s & SignallingCircuitGroup::OnlyEven)
148 		s = (s & ~SignallingCircuitGroup::OnlyEven) | SignallingCircuitGroup::OnlyOdd;
149 	    else if (s & SignallingCircuitGroup::OnlyOdd)
150 		s = (s & ~SignallingCircuitGroup::OnlyOdd) | SignallingCircuitGroup::OnlyEven;
151 	}
152 	cic = m_circuits->reserve(*list,mandatory,checkLock,s,m_circuits->findRange(range));
153     }
154     else if (range) {
155 	const char* nRange = range;
156 	switch (nRange[0]) {
157 	    case '!':
158 		mandatory = true;
159 		nRange++;
160 		break;
161 	    case '?':
162 		mandatory = false;
163 		nRange++;
164 		break;
165 	}
166 	int num = String(nRange).toInteger();
167 	if (num > 0) {
168 	    // Specific circuit required
169 	    SignallingCircuit* circuit = m_circuits->find(num);
170 	    if (circuit && !circuit->locked(checkLock) && circuit->reserve()) {
171 		if (circuit->ref())
172 		    cic = circuit;
173 		else
174 		    m_circuits->release(circuit);
175 	    }
176 	    if (cic || mandatory)
177 		return (cic != 0);
178 	    DDebug(DebugInfo,"SignallingCallControl. Fallback, circuit %u not available [%p]",num,this);
179 	}
180 	cic = m_circuits->reserve(checkLock,-1,m_circuits->findRange(range));
181     }
182     else
183 	cic = m_circuits->reserve(checkLock,-1);
184     return (cic != 0);
185 }
186 
187 // Release a given circuit
releaseCircuit(SignallingCircuit * & cic,bool sync)188 bool SignallingCallControl::releaseCircuit(SignallingCircuit*& cic, bool sync)
189 {
190     if (!cic)
191 	return false;
192     bool ok = cic->status(SignallingCircuit::Idle,sync);
193     DDebug(DebugAll,"SignallingCallControl. Released circuit %u [%p]",cic->code(),this);
194     cic->deref();
195     cic = 0;
196     return ok;
197 }
198 
releaseCircuit(unsigned int code,bool sync)199 bool SignallingCallControl::releaseCircuit(unsigned int code, bool sync)
200 {
201     Lock mylock(this);
202     SignallingCircuit* cic = m_circuits ? m_circuits->find(code) : 0;
203     if (!cic)
204 	return false;
205     return cic->status(SignallingCircuit::Idle,sync);
206 }
207 
208 // Get events from calls
209 // Raise Disable event when no more calls and exiting
getEvent(const Time & when)210 SignallingEvent* SignallingCallControl::getEvent(const Time& when)
211 {
212     lock();
213     // Verify ?
214     if (m_verifyEvent && m_verifyTimer.timeout(when.msec())) {
215 	SignallingMessage* msg = new SignallingMessage;
216 	SignallingEvent* event = new SignallingEvent(SignallingEvent::Verify,msg,this);
217 	buildVerifyEvent(msg->params());
218 	TelEngine::destruct(msg);
219 	setVerify(true,false,&when);
220 	unlock();
221 	return event;
222     }
223     ListIterator iter(m_calls);
224     for (;;) {
225 	SignallingCall* call = static_cast<SignallingCall*>(iter.get());
226 	// End of iteration?
227 	if (!call)
228 	    break;
229 	RefPointer<SignallingCall> callRef = call;
230 	// Dead pointer?
231 	if (!callRef)
232 	    continue;
233 	unlock();
234 	SignallingEvent* event = callRef->getEvent(when);
235 	// Check if this call controller wants the event
236 	if (event && !processEvent(event))
237 	    return event;
238 	lock();
239     }
240     unlock();
241     // Get events from circuits not reserved
242     // TODO: Find a better way to parse circuit list to get events
243     Lock lckCtrl(this);
244     if (m_circuits) {
245 	Lock lckCic(m_circuits);
246 	for (ObjList* o = m_circuits->circuits().skipNull(); o; o = o->skipNext()) {
247 	    SignallingCircuit* cic = static_cast<SignallingCircuit*>(o->get());
248 	    if (cic->status() == SignallingCircuit::Reserved)
249 		continue;
250 	    SignallingCircuitEvent* ev = cic->getEvent(when);
251 	    if (!ev)
252 		continue;
253 	    SignallingEvent* event = processCircuitEvent(ev);
254 	    if (event)
255 		return event;
256 	}
257     }
258     // Terminate if exiting and no more calls
259     //TODO: Make sure we raise this event one time only
260     if (exiting() && !m_calls.skipNull())
261 	return new SignallingEvent(SignallingEvent::Disable,0,this);
262     return 0;
263 }
264 
265 // Clear call list
clearCalls()266 void SignallingCallControl::clearCalls()
267 {
268     lock();
269     m_calls.clear();
270     unlock();
271 }
272 
273 // Remove a call from list
removeCall(SignallingCall * call,bool del)274 void SignallingCallControl::removeCall(SignallingCall* call, bool del)
275 {
276     if (!call)
277 	return;
278     lock();
279     if (m_calls.remove(call,del))
280 	DDebug(DebugAll,
281 	    "SignallingCallControl. Call (%p) removed%s from queue [%p]",
282 	    call,(del ? " and deleted" : ""),this);
283     unlock();
284 }
285 
286 // Set the verify event flag. Restart/fire verify timer
setVerify(bool restartTimer,bool fireNow,const Time * time)287 void SignallingCallControl::setVerify(bool restartTimer, bool fireNow, const Time* time)
288 {
289     m_verifyEvent = true;
290     if (!restartTimer)
291 	return;
292     m_verifyTimer.stop();
293     if (!fireNow)
294 	m_verifyTimer.start(time ? time->msec() : Time::msecNow());
295     else
296 	m_verifyTimer.fire();
297 }
298 
299 
300 /**
301  * SignallingCall
302  */
SignallingCall(SignallingCallControl * controller,bool outgoing,bool signalOnly)303 SignallingCall::SignallingCall(SignallingCallControl* controller, bool outgoing, bool signalOnly)
304     : Mutex(true,"SignallingCall"),
305     m_lastEvent(0),
306     m_overlap(false),
307     m_controller(controller),
308     m_outgoing(outgoing),
309     m_signalOnly(signalOnly),
310     m_inMsgMutex(true,"SignallingCall::inMsg"),
311     m_private(0)
312 {
313 }
314 
~SignallingCall()315 SignallingCall::~SignallingCall()
316 {
317     lock();
318     m_inMsg.clear();
319     if (m_controller)
320 	m_controller->removeCall(this,false);
321     unlock();
322 }
323 
324 // Event termination notification
eventTerminated(SignallingEvent * event)325 void SignallingCall::eventTerminated(SignallingEvent* event)
326 {
327     Lock mylock(this);
328     if (!m_lastEvent || !event || m_lastEvent != event)
329 	return;
330     XDebug(DebugAll,"SignallingCall. Event (%p,'%s') terminated [%p]",event,event->name(),this);
331     m_lastEvent = 0;
332 }
333 
enqueue(SignallingMessage * msg)334 void SignallingCall::enqueue(SignallingMessage* msg)
335 {
336     if (!msg)
337 	return;
338     Lock lock(m_inMsgMutex);
339     m_inMsg.append(msg);
340     XDebug(DebugAll,"SignallingCall. Enqueued message (%p,'%s') [%p]",
341 	msg,msg->name(),this);
342 }
343 
344 // Dequeue a received message
dequeue(bool remove)345 SignallingMessage* SignallingCall::dequeue(bool remove)
346 {
347     Lock lock(m_inMsgMutex);
348     ObjList* obj = m_inMsg.skipNull();
349     if (!obj)
350 	return 0;
351     SignallingMessage* msg = static_cast<SignallingMessage*>(obj->get());
352     if (remove) {
353 	m_inMsg.remove(msg,false);
354 	XDebug(DebugAll,"SignallingCall. Dequeued message (%p,'%s') [%p]",
355 	   msg,msg->name(),this);
356     }
357     return msg;
358 }
359 
360 
361 /**
362  * SignallingEvent
363  */
364 const TokenDict SignallingEvent::s_types[] = {
365 	{"Unknown",  Unknown},
366 	{"Generic",  Generic},
367 	{"NewCall",  NewCall},
368 	{"Accept",   Accept},
369 	{"Connect",  Connect},
370 	{"Complete", Complete},
371 	{"Progress", Progress},
372 	{"Ringing",  Ringing},
373 	{"Answer",   Answer},
374 	{"Transfer", Transfer},
375 	{"Suspend",  Suspend},
376 	{"Resume",   Resume},
377 	{"Release",  Release},
378 	{"Info",     Info},
379 	{"Charge",   Charge},
380 	{"Message",  Message},
381 	{"Facility", Facility},
382 	{"Circuit",  Circuit},
383 	{"Enable",   Enable},
384 	{"Disable",  Disable},
385 	{"Reset",    Reset},
386 	{"Verify",   Verify},
387 	{0,0}
388 	};
389 
SignallingEvent(Type type,SignallingMessage * message,SignallingCall * call)390 SignallingEvent::SignallingEvent(Type type, SignallingMessage* message, SignallingCall* call)
391     : m_type(type), m_message(0), m_call(0), m_controller(0), m_cicEvent(0)
392 {
393     if (call && call->ref()) {
394 	m_call = call;
395 	m_controller = call->controller();
396     }
397     if (message && message->ref())
398 	m_message = message;
399 }
400 
SignallingEvent(Type type,SignallingMessage * message,SignallingCallControl * controller)401 SignallingEvent::SignallingEvent(Type type, SignallingMessage* message, SignallingCallControl* controller)
402     : m_type(type), m_message(0), m_call(0), m_controller(controller), m_cicEvent(0)
403 {
404     if (message && message->ref())
405 	m_message = message;
406 }
407 
408 // Constructor for a signalling circuit related event
SignallingEvent(SignallingCircuitEvent * & event,SignallingCall * call)409 SignallingEvent::SignallingEvent(SignallingCircuitEvent*& event, SignallingCall* call)
410     : m_type(Circuit), m_message(0), m_call(0), m_controller(0), m_cicEvent(event)
411 {
412     event = 0;
413     if (call && call->ref()) {
414 	m_call = call;
415 	m_controller = call->controller();
416     }
417 }
418 
~SignallingEvent()419 SignallingEvent::~SignallingEvent()
420 {
421     m_controller = 0;
422     if (m_message)
423 	m_message->deref();
424     if (m_call) {
425 	m_call->eventTerminated(this);
426 	m_call->deref();
427     }
428     TelEngine::destruct(m_cicEvent);
429 }
430 
sendEvent()431 bool SignallingEvent::sendEvent()
432 {
433     if (m_call)
434 	return m_call->sendEvent(this);
435     delete this;
436     return false;
437 }
438 
439 
440 /**
441  * SignallingCircuitEvent
442  */
SignallingCircuitEvent(SignallingCircuit * cic,Type type,const char * name)443 SignallingCircuitEvent::SignallingCircuitEvent(SignallingCircuit* cic, Type type, const char* name)
444     : NamedList(name),
445     m_circuit(0),
446     m_type(type)
447 {
448     XDebug(DebugAll,"SignallingCircuitEvent::SignallingCircuitEvent() [%p]",this);
449     if (cic && cic->ref())
450 	m_circuit = cic;
451 }
452 
~SignallingCircuitEvent()453 SignallingCircuitEvent::~SignallingCircuitEvent()
454 {
455     if (m_circuit) {
456 	m_circuit->eventTerminated(this);
457 	m_circuit->deref();
458     }
459     XDebug(DebugAll,"SignallingCircuitEvent::~SignallingCircuitEvent() [%p]",this);
460 }
461 
462 // Send this event through the circuit. Release (delete) the event on success
sendEvent()463 bool SignallingCircuitEvent::sendEvent()
464 {
465     bool ok = m_circuit && m_circuit->sendEvent(type(),this);
466     delete this;
467     return ok;
468 }
469 
470 
471 /**
472  * SignallingCircuit
473  */
474 static const TokenDict s_cicTypeDict[] = {
475     {"TDM",     SignallingCircuit::TDM},
476     {"RTP",     SignallingCircuit::RTP},
477     {"IAX",     SignallingCircuit::IAX},
478     {"Unknown", SignallingCircuit::Unknown},
479     {"Local",   SignallingCircuit::Local},
480     {0,0}
481 };
482 
483 static const TokenDict s_cicStatusDict[] = {
484     {"Missing",   SignallingCircuit::Missing},
485     {"Disabled",  SignallingCircuit::Disabled},
486     {"Idle",      SignallingCircuit::Idle},
487     {"Reserved",  SignallingCircuit::Reserved},
488     {"Starting",  SignallingCircuit::Starting},
489     {"Stopping",  SignallingCircuit::Stopping},
490     {"Special",   SignallingCircuit::Special},
491     {"Connected", SignallingCircuit::Connected},
492     {0,0}
493 };
494 
SignallingCircuit(Type type,unsigned int code,SignallingCircuitGroup * group,SignallingCircuitSpan * span)495 SignallingCircuit::SignallingCircuit(Type type, unsigned int code,
496 	SignallingCircuitGroup* group, SignallingCircuitSpan* span)
497     : m_mutex(true,"SignallingCircuit::operations"),
498       m_group(group), m_span(span),
499       m_code(code), m_type(type),
500       m_status(Disabled),
501       m_lock(0), m_lastEvent(0), m_noEvents(true)
502 {
503     XDebug(m_group,DebugAll,"SignallingCircuit::SignallingCircuit [%p]",this);
504 }
505 
SignallingCircuit(Type type,unsigned int code,Status status,SignallingCircuitGroup * group,SignallingCircuitSpan * span)506 SignallingCircuit::SignallingCircuit(Type type, unsigned int code, Status status,
507 	SignallingCircuitGroup* group, SignallingCircuitSpan* span)
508     : m_mutex(true,"SignallingCircuit::operations"),
509       m_group(group), m_span(span),
510       m_code(code), m_type(type),
511       m_status(status),
512       m_lock(0), m_lastEvent(0), m_noEvents(true)
513 {
514     XDebug(m_group,DebugAll,"SignallingCircuit::SignallingCircuit [%p]",this);
515 }
516 
~SignallingCircuit()517 SignallingCircuit::~SignallingCircuit()
518 {
519     clearEvents();
520     XDebug(m_group,DebugAll,"SignallingCircuit::~SignallingCircuit [%p]",this);
521 }
522 
523 // Set circuit data from a list of parameters
setParams(const NamedList & params)524 bool SignallingCircuit::setParams(const NamedList& params)
525 {
526     bool ok = true;
527     unsigned int n = params.length();
528     for (unsigned int i = 0; i < n; i++) {
529 	NamedString* param = params.getParam(i);
530 	if (param && !setParam(param->name(),*param))
531 	    ok = false;
532     }
533     return ok;
534 }
535 
536 // Get first event from queue
getEvent(const Time & when)537 SignallingCircuitEvent* SignallingCircuit::getEvent(const Time& when)
538 {
539     if (m_noEvents)
540 	return 0;
541     Lock lock(m_mutex);
542     if (m_lastEvent)
543 	return 0;
544     ObjList* obj = m_events.skipNull();
545     if (!obj) {
546 	m_noEvents = true;
547 	return 0;
548     }
549     m_lastEvent = static_cast<SignallingCircuitEvent*>(m_events.remove(obj->get(),false));
550     return m_lastEvent;
551 }
552 
sendEvent(SignallingCircuitEvent::Type type,NamedList * params)553 bool SignallingCircuit::sendEvent(SignallingCircuitEvent::Type type, NamedList* params)
554 {
555     XDebug(m_group,DebugStub,"SignallingCircuit::sendEvent(%u,%p) [%p]",type,params,this);
556     return false;
557 }
558 
559 // Set/reset circuit flag(s)
cicFlag(SignallingCircuit * cic,bool set,int flag,int chgFlag,bool setChg)560 inline bool cicFlag(SignallingCircuit* cic, bool set, int flag, int chgFlag, bool setChg)
561 {
562     if (chgFlag) {
563 	if (setChg)
564 	    cic->setLock(chgFlag);
565 	else
566 	    cic->resetLock(chgFlag);
567     }
568     if (set == (0 != cic->locked(flag)))
569 	return false;
570     if (set)
571 	cic->setLock(flag);
572     else
573 	cic->resetLock(flag);
574     return true;
575 }
576 
577 // Set/reset HW failure lock flag
hwLock(bool set,bool remote,bool changed,bool setChanged)578 bool SignallingCircuit::hwLock(bool set, bool remote, bool changed, bool setChanged)
579 {
580     Lock lock(m_mutex);
581     int flag = remote ? LockRemoteHWFail : LockLocalHWFail;
582     int chgFlag = changed ? (remote ? LockRemoteHWFailChg : LockLocalHWFailChg) : 0;
583     return cicFlag(this,set,flag,chgFlag,setChanged);
584 }
585 
586 // Set/reset maintenance lock flag
maintLock(bool set,bool remote,bool changed,bool setChanged)587 bool SignallingCircuit::maintLock(bool set, bool remote, bool changed, bool setChanged)
588 {
589     Lock lock(m_mutex);
590     int flag = remote ? LockRemoteMaint : LockLocalMaint;
591     int chgFlag = changed ? (remote ? LockRemoteMaintChg : LockLocalMaintChg) : 0;
592     return cicFlag(this,set,flag,chgFlag,setChanged);
593 }
594 
595 // Add event to queue
addEvent(SignallingCircuitEvent * event)596 void SignallingCircuit::addEvent(SignallingCircuitEvent* event)
597 {
598     if (!event)
599 	return;
600     Lock lock(m_mutex);
601     m_noEvents = false;
602     m_events.append(event);
603 }
604 
605 // Clear event queue
clearEvents()606 void SignallingCircuit::clearEvents()
607 {
608     Lock lock(m_mutex);
609     m_events.clear();
610 }
611 
612 // Event termination notification
eventTerminated(SignallingCircuitEvent * event)613 void SignallingCircuit::eventTerminated(SignallingCircuitEvent* event)
614 {
615     Lock lock(m_mutex);
616     if (event && m_lastEvent == event) {
617 	XDebug(m_group,DebugAll,"Event (%p) '%s' terminated for cic=%u [%p]",
618 	    event,event->c_str(),code(),this);
619 	m_lastEvent = 0;
620     }
621 }
622 
623 // Get the text associated with a circuit type
lookupType(int type)624 const char* SignallingCircuit::lookupType(int type)
625 {
626     return lookup(type,s_cicTypeDict);
627 }
628 
629 // Get the text associated with a circuit status
lookupStatus(int status)630 const char* SignallingCircuit::lookupStatus(int status)
631 {
632     return lookup(status,s_cicStatusDict);
633 }
634 
635 /**
636  * SignallingCircuitRange
637  */
SignallingCircuitRange(const String & rangeStr,const char * name,int strategy)638 SignallingCircuitRange::SignallingCircuitRange(const String& rangeStr,
639 	const char* name, int strategy)
640     : String(name),
641       m_count(0), m_last(0),
642       m_strategy(strategy),
643       m_used(0)
644 {
645     add(rangeStr);
646 }
647 
648 // Allocate and return an array containing range circuits
copyRange(unsigned int & count) const649 unsigned int* SignallingCircuitRange::copyRange(unsigned int& count) const
650 {
651     if (!m_count)
652 	return 0;
653     count = m_count;
654     unsigned int* tmp = new unsigned int[count];
655     ::memcpy(tmp,range(),m_range.length());
656     return tmp;
657 }
658 
659 // Add codes to this range from a string
add(const String & rangeStr)660 bool SignallingCircuitRange::add(const String& rangeStr)
661 {
662     unsigned int n = 0;
663     unsigned int* p = SignallingUtils::parseUIntArray(rangeStr,0,(unsigned int)-1,n,true);
664     if (!p)
665 	return false;
666     add(p,n);
667     delete[] p;
668     return true;
669 }
670 
671 // Add an array of circuit codes to this range
add(unsigned int * codes,unsigned int len)672 void SignallingCircuitRange::add(unsigned int* codes, unsigned int len)
673 {
674     if (!(codes && len))
675 	return;
676     m_range.append(codes,len*sizeof(unsigned int));
677     m_count += len;
678     updateLast();
679 }
680 
681 // Add a compact range of circuit codes to this range
add(unsigned int first,unsigned int last)682 void SignallingCircuitRange::add(unsigned int first, unsigned int last)
683 {
684     if (first > last)
685 	return;
686     unsigned int count = last - first + 1;
687     DataBlock data(0,count*sizeof(unsigned int));
688     unsigned int* codes = (unsigned int*)data.data();
689     for (unsigned int i = 0; i < count; i++)
690 	codes[i] = first+i;
691     m_range.append(data);
692     m_count += count;
693     updateLast();
694 }
695 
696 // Remove a circuit code from this range
remove(unsigned int code)697 void SignallingCircuitRange::remove(unsigned int code)
698 {
699     unsigned int* d = (unsigned int*)range();
700     for (unsigned int i = 0; i < count(); i++)
701 	if (d[i] == code)
702 	    d[i] = 0;
703     updateLast();
704 }
705 
706 
707 // Check if a circuit code is within this range
find(unsigned int code)708 bool SignallingCircuitRange::find(unsigned int code)
709 {
710     if (!range())
711 	return false;
712     for (unsigned int i = 0; i < count(); i++)
713 	if (range()[i] == code)
714 	    return true;
715     return false;
716 }
717 
718 // Update last circuit code
updateLast()719 void SignallingCircuitRange::updateLast()
720 {
721     m_last = 0;
722     for (unsigned int i = 0; i < count(); i++)
723 	if (m_last <= range()[i])
724 	    m_last = range()[i] + 1;
725 }
726 
727 
728 /**
729  * SignallingCircuitGroup
730  */
731 const TokenDict SignallingCircuitGroup::s_strategy[] = {
732 	{"increment", Increment},
733 	{"decrement", Decrement},
734 	{"lowest",    Lowest},
735 	{"highest",   Highest},
736 	{"random",    Random},
737 	{0,0}
738 	};
739 
SignallingCircuitGroup(unsigned int base,int strategy,const char * name)740 SignallingCircuitGroup::SignallingCircuitGroup(unsigned int base, int strategy, const char* name)
741     : SignallingComponent(name),
742       Mutex(true,"SignallingCircuitGroup"),
743       m_range(String::empty(),name,strategy),
744       m_base(base)
745 {
746     setName(name);
747     XDebug(this,DebugAll,"SignallingCircuitGroup::SignallingCircuitGroup() [%p]",this);
748 }
749 
750 // Set circuits status to Missing. Clear circuit list
751 // Clear span list
~SignallingCircuitGroup()752 SignallingCircuitGroup::~SignallingCircuitGroup()
753 {
754     clearAll();
755     XDebug(this,DebugAll,"SignallingCircuitGroup::~SignallingCircuitGroup() [%p]",this);
756 }
757 
758 // Find a circuit by code
find(unsigned int cic,bool local)759 SignallingCircuit* SignallingCircuitGroup::find(unsigned int cic, bool local)
760 {
761     if (!local) {
762 	if (cic < m_base)
763 	    return 0;
764 	cic -= m_base;
765     }
766     Lock mylock(this);
767     if (cic >= m_range.m_last)
768 	return 0;
769     ObjList* l = m_circuits.skipNull();
770     for (; l; l = l->skipNext()) {
771 	SignallingCircuit* c = static_cast<SignallingCircuit*>(l->get());
772 	if (c->code() == cic)
773 	    return c;
774     }
775     return 0;
776 }
777 
778 // Find a range of circuits owned by this group
findRange(const char * name)779 SignallingCircuitRange* SignallingCircuitGroup::findRange(const char* name)
780 {
781     Lock mylock(this);
782     ObjList* obj = m_ranges.find(name);
783     return obj ? static_cast<SignallingCircuitRange*>(obj->get()) : 0;
784 }
785 
getCicList(String & dest)786 void SignallingCircuitGroup::getCicList(String& dest)
787 {
788     dest = "";
789     Lock mylock(this);
790     for (ObjList* l = m_circuits.skipNull(); l; l = l->skipNext()) {
791 	SignallingCircuit* c = static_cast<SignallingCircuit*>(l->get());
792 	dest.append(String(c->code()),",");
793     }
794 }
795 
796 // Insert a circuit if not already in the list
insert(SignallingCircuit * circuit)797 bool SignallingCircuitGroup::insert(SignallingCircuit* circuit)
798 {
799     if (!circuit)
800 	return false;
801     Lock mylock(this);
802     if (m_circuits.find(circuit) || find(circuit->code(),true))
803 	return false;
804     circuit->m_group = this;
805     m_circuits.append(circuit);
806     m_range.add(circuit->code());
807     return true;
808 }
809 
810 // Remove a circuit from list. Update maximum circuit code
remove(SignallingCircuit * circuit)811 void SignallingCircuitGroup::remove(SignallingCircuit* circuit)
812 {
813     if (!circuit)
814 	return;
815     Lock mylock(this);
816     if (!m_circuits.remove(circuit,false))
817 	return;
818     circuit->m_group = 0;
819     m_range.remove(circuit->code());
820     // TODO: remove from all ranges
821 }
822 
823 // Append a span to the list if not already there
insertSpan(SignallingCircuitSpan * span)824 bool SignallingCircuitGroup::insertSpan(SignallingCircuitSpan* span)
825 {
826     if (!span)
827 	return false;
828     Lock mylock(this);
829     if (!m_spans.find(span))
830 	m_spans.append(span);
831     return true;
832 }
833 
buildSpan(const String & name,unsigned int start,NamedList * param)834 SignallingCircuitSpan* SignallingCircuitGroup::buildSpan(const String& name, unsigned int start, NamedList* param)
835 {
836     // Local class used to pass the circuit group pointer to the span
837     class VoiceParams : public NamedList
838     {
839     public:
840 	inline VoiceParams(const char* name, SignallingCircuitGroup* group)
841 	    : NamedList(name), m_group(group)
842 	    { }
843 	virtual void* getObject(const String& name) const
844 	    { return (name == YSTRING("SignallingCircuitGroup")) ? m_group : NamedList::getObject(name); }
845 	SignallingCircuitGroup* m_group;
846     };
847 
848     VoiceParams params(debugName(),this);
849     params << "/" << name;
850     params.addParam("voice",name);
851     if (param)
852 	params.copyParams(*param);
853     if (start)
854 	params.addParam("start",String(start));
855     return YSIGCREATE(SignallingCircuitSpan,&params);
856 }
857 
858 // Build and insert a range from circuits belonging to a given span
insertRange(SignallingCircuitSpan * span,const char * name,int strategy)859 void SignallingCircuitGroup::insertRange(SignallingCircuitSpan* span, const char* name,
860 	int strategy)
861 {
862     if (!span)
863 	return;
864     if (!name)
865 	name = span->id();
866     Lock mylock(this);
867     String tmp;
868     for (ObjList* o = m_circuits.skipNull(); o; o = o->skipNext()) {
869 	SignallingCircuit* c = static_cast<SignallingCircuit*>(o->get());
870 	if (span == c->span())
871 	    tmp.append(String(c->code()),",");
872     }
873     mylock.drop();
874     insertRange(tmp,name,strategy);
875 }
876 
877 // Build and insert a range contained in a string
insertRange(const String & range,const char * name,int strategy)878 void SignallingCircuitGroup::insertRange(const String& range, const char* name,
879 	int strategy)
880 {
881     Lock mylock(this);
882     if (findRange(name))
883 	return;
884     if (strategy < 0)
885 	strategy = m_range.m_strategy;
886     m_ranges.append(new SignallingCircuitRange(range,name,strategy));
887     Debug(this,DebugNote,"Added range %s: %s [%p]",name,range.c_str(),this);
888 }
889 
890 // Remove a span from list
removeSpan(SignallingCircuitSpan * span,bool delCics,bool delSpan)891 void SignallingCircuitGroup::removeSpan(SignallingCircuitSpan* span, bool delCics, bool delSpan)
892 {
893     if (!span)
894 	return;
895     Lock mylock(this);
896     if (delCics)
897 	removeSpanCircuits(span);
898     m_spans.remove(span,delSpan);
899 }
900 
901 // Remove circuits belonging to a span
removeSpanCircuits(SignallingCircuitSpan * span)902 void SignallingCircuitGroup::removeSpanCircuits(SignallingCircuitSpan* span)
903 {
904     if (!span)
905 	return;
906     Lock mylock(this);
907     ListIterator iter(m_circuits);
908     for (GenObject* obj = 0; (obj = iter.get());) {
909 	SignallingCircuit* c = static_cast<SignallingCircuit*>(obj);
910 	if (span == c->span()) {
911 	    remove(c);
912 	    TelEngine::destruct(c);
913 	}
914     }
915 }
916 
917 // Get the status of a circuit given by its code
status(unsigned int cic)918 SignallingCircuit::Status SignallingCircuitGroup::status(unsigned int cic)
919 {
920     Lock mylock(this);
921     SignallingCircuit* circuit = find(cic);
922     return circuit ? circuit->status() : SignallingCircuit::Missing;
923 }
924 
925 // Change the status of a circuit given by its code
status(unsigned int cic,SignallingCircuit::Status newStat,bool sync)926 bool SignallingCircuitGroup::status(unsigned int cic, SignallingCircuit::Status newStat,
927 	bool sync)
928 {
929     Lock mylock(this);
930     SignallingCircuit* circuit = find(cic);
931     return circuit && circuit->status(newStat,sync);
932 }
933 
adjustParity(unsigned int & n,int strategy,bool up)934 inline void adjustParity(unsigned int& n, int strategy, bool up)
935 {
936     if (((strategy & SignallingCircuitGroup::OnlyEven) && (n & 1)) ||
937 	((strategy & SignallingCircuitGroup::OnlyOdd) && !(n & 1))) {
938 	if (up)
939 	    n++;
940 	else if (n)
941 	    n--;
942 	else
943 	    n = (strategy & SignallingCircuitGroup::OnlyEven) ? 0 : 1;
944     }
945 }
946 
947 // Choose the next circuit code to check, depending on strategy
advance(unsigned int n,int strategy,SignallingCircuitRange & range)948 unsigned int SignallingCircuitGroup::advance(unsigned int n, int strategy,
949 	SignallingCircuitRange& range)
950 {
951     // Increment by 2 when even or odd only circuits are requested
952     unsigned int delta = (strategy & (OnlyOdd|OnlyEven)) ? 2 : 1;
953     switch (strategy & 0xfff) {
954 	case Increment:
955 	case Lowest:
956 	    n += delta;
957 	    if (n >= range.m_last) {
958 		n = 0;
959 		adjustParity(n,strategy,true);
960 	    }
961 	    break;
962 	case Decrement:
963 	case Highest:
964 	    if (n >= delta)
965 		n -= delta;
966 	    else {
967 		n = range.m_last;
968 		adjustParity(n,strategy,false);
969 	    }
970 	    break;
971 	default:
972 	    n = (n + 1) % range.m_last;
973 	    break;
974     }
975     return n;
976 }
977 
978 // Reserve a circuit
reserve(int checkLock,int strategy,SignallingCircuitRange * range)979 SignallingCircuit* SignallingCircuitGroup::reserve(int checkLock, int strategy,
980 	SignallingCircuitRange* range)
981 {
982     DDebug(this,DebugInfo,"SignallingCircuitGroup::reserve(%d,%d,%p) [%p]",
983 	checkLock,strategy,range,this);
984     Lock mylock(this);
985     if (!range)
986 	range = &m_range;
987     if (range->m_last < 1)
988 	return 0;
989     if (strategy < 0)
990 	strategy = range->m_strategy;
991     bool up = true;
992     unsigned int n = range->m_used;
993     // first adjust the last used channel number
994     switch (strategy & 0xfff) {
995 	case Increment:
996 	    n = (n + 1) % range->m_last;
997 	    break;
998 	case Decrement:
999 	    if (n < 2)
1000 		n = range->m_last;
1001 	    else
1002 		n--;
1003 	    up = false;
1004 	    break;
1005 	case Lowest:
1006 	    n = 0;
1007 	    break;
1008 	case Highest:
1009 	    n = range->m_last;
1010 	    up = false;
1011 	    break;
1012 	default:
1013 	    while ((range->m_last > 1) && (n == range->m_used))
1014 		n = Random::random() % range->m_last;
1015     }
1016     // then go to the proper even/odd start circuit
1017     adjustParity(n,strategy,up);
1018     // remember where the scan started
1019     unsigned int start = n;
1020     // try at most how many channels we have, halve that if we only scan even or odd
1021     unsigned int i = range->m_last;
1022     if (strategy & (OnlyOdd|OnlyEven))
1023 	i = (i + 1) / 2;
1024     while (i--) {
1025 	// Check if the circuit is within range
1026 	if (range->find(n)) {
1027 	    SignallingCircuit* circuit = find(n,true);
1028 	    if (circuit && !circuit->locked(checkLock) && circuit->reserve()) {
1029 		if (circuit->ref()) {
1030 		    range->m_used = n;
1031 		    return circuit;
1032 		}
1033 		release(circuit);
1034 		return 0;
1035 	    }
1036 	}
1037 	n = advance(n,strategy,*range);
1038 	// if wrapped around bail out, don't scan again
1039 	if (n == start)
1040 	    break;
1041     }
1042     mylock.drop();
1043     if (strategy & Fallback) {
1044 	if (strategy & OnlyEven) {
1045 	    Debug(this,DebugNote,"No even circuits available, falling back to odd [%p]",this);
1046 	    return reserve(checkLock,OnlyOdd | (strategy & 0xfff),range);
1047 	}
1048 	if (strategy & OnlyOdd) {
1049 	    Debug(this,DebugNote,"No odd circuits available, falling back to even [%p]",this);
1050 	    return reserve(checkLock,OnlyEven | (strategy & 0xfff),range);
1051 	}
1052     }
1053     return 0;
1054 }
1055 
1056 // Reserve a circuit from the given list
1057 // Reserve another one if not found and not mandatory
reserve(const String & list,bool mandatory,int checkLock,int strategy,SignallingCircuitRange * range)1058 SignallingCircuit* SignallingCircuitGroup::reserve(const String& list, bool mandatory,
1059 	int checkLock, int strategy, SignallingCircuitRange* range)
1060 {
1061     DDebug(this,DebugInfo,"SignallingCircuitGroup::reserve('%s',%s,%d,%d,%p) [%p]",
1062 	list.c_str(),String::boolText(mandatory),checkLock,strategy,range,this);
1063     Lock mylock(this);
1064     if (!range)
1065 	range = &m_range;
1066     // Check if any of the given circuits are free
1067     while (true) {
1068 	if (list.null())
1069 	    break;
1070 	ObjList* circuits = list.split(',',false);
1071 	if (!circuits)
1072 	    break;
1073 	SignallingCircuit* circuit = 0;
1074 	for (ObjList* obj = circuits->skipNull(); obj; obj = obj->skipNext()) {
1075 	    int code = (static_cast<String*>(obj->get()))->toInteger(-1);
1076 	    if (code > 0 && range->find(code))
1077 		circuit = find(code,false);
1078 	    if (circuit && !circuit->locked(checkLock) && circuit->reserve()) {
1079 		if (circuit->ref()) {
1080 		    range->m_used = m_base + circuit->code();
1081 		    break;
1082 		}
1083 		release(circuit);
1084 	    }
1085 	    circuit = 0;
1086 	}
1087 	TelEngine::destruct(circuits);
1088 	if (circuit)
1089 	    return circuit;
1090 	break;
1091     }
1092     // Don't try to reserve another one if the given list is mandatory
1093     if (mandatory)
1094 	return 0;
1095     return reserve(checkLock,strategy,range);
1096 }
1097 
1098 // Clear data
clearAll()1099 void SignallingCircuitGroup::clearAll()
1100 {
1101     Lock mylock(this);
1102     // Remove spans and their circuits
1103     ListIterator iter(m_spans);
1104     for (GenObject* obj = 0; (obj = iter.get());)
1105 	removeSpan(static_cast<SignallingCircuitSpan*>(obj),true,true);
1106     // Remove the rest of circuits. Reset circuits' group
1107     // Some of them may continue to exists after clearing the list
1108     for (ObjList* l = m_circuits.skipNull(); l; l = l->skipNext()) {
1109 	SignallingCircuit* c = static_cast<SignallingCircuit*>(l->get());
1110 	c->status(SignallingCircuit::Missing,true);
1111 	c->m_group = 0;
1112     }
1113     m_circuits.clear();
1114     m_ranges.clear();
1115 }
1116 
1117 
1118 /**
1119  * SignallingCircuitSpan
1120  */
SignallingCircuitSpan(const char * id,SignallingCircuitGroup * group)1121 SignallingCircuitSpan::SignallingCircuitSpan(const char* id, SignallingCircuitGroup* group)
1122     : SignallingComponent(id),
1123       m_group(group), m_increment(0), m_id(id)
1124 {
1125     if (m_group)
1126 	m_group->insertSpan(this);
1127     XDebug(DebugAll,"SignallingCircuitSpan::SignallingCircuitSpan() '%s' [%p]",id,this);
1128 }
1129 
~SignallingCircuitSpan()1130 SignallingCircuitSpan::~SignallingCircuitSpan()
1131 {
1132     if (m_group)
1133 	m_group->removeSpan(this,true,false);
1134     XDebug(DebugAll,"SignallingCircuitSpan::~SignallingCircuitSpan() '%s' [%p]",m_id.safe(),this);
1135 }
1136 
1137 
1138 /**
1139  * AnalogLine
1140  */
typeNames()1141 const TokenDict* AnalogLine::typeNames()
1142 {
1143     static const TokenDict names[] = {
1144 	{"FXO",       FXO},
1145 	{"FXS",       FXS},
1146 	{"recorder",  Recorder},
1147 	{"monitor",   Monitor},
1148 	{0,0}
1149     };
1150     return names;
1151 }
1152 
stateNames()1153 const TokenDict* AnalogLine::stateNames()
1154 {
1155     static const TokenDict names[] = {
1156 	{"OutOfService",   OutOfService},
1157 	{"Idle",           Idle},
1158 	{"Dialing",        Dialing},
1159 	{"DialComplete",   DialComplete},
1160 	{"Ringing",        Ringing},
1161 	{"Answered",       Answered},
1162 	{"CallEnded",      CallEnded},
1163 	{"OutOfOrder",     OutOfOrder},
1164 	{0,0}
1165 	};
1166     return names;
1167 }
1168 
csNames()1169 const TokenDict* AnalogLine::csNames() {
1170     static const TokenDict names[] = {
1171 	{"after",  After},
1172 	{"before", Before},
1173 	{"none",   NoCallSetup},
1174 	{0,0}
1175 	};
1176     return names;
1177 }
1178 
getValidInt(const NamedList & params,const char * param,int defVal)1179 inline u_int64_t getValidInt(const NamedList& params, const char* param, int defVal)
1180 {
1181     int tmp = params.getIntValue(param,defVal);
1182     return tmp >= 0 ? tmp : defVal;
1183 }
1184 
1185 // Reserve the line's circuit
AnalogLine(AnalogLineGroup * grp,unsigned int cic,const NamedList & params)1186 AnalogLine::AnalogLine(AnalogLineGroup* grp, unsigned int cic, const NamedList& params)
1187     : Mutex(true,"AnalogLine"),
1188     m_type(Unknown),
1189     m_state(Idle),
1190     m_inband(false),
1191     m_echocancel(0),
1192     m_acceptPulseDigit(true),
1193     m_answerOnPolarity(false),
1194     m_hangupOnPolarity(false),
1195     m_polarityControl(false),
1196     m_callSetup(NoCallSetup),
1197     m_callSetupTimeout(0),
1198     m_noRingTimeout(0),
1199     m_alarmTimeout(0),
1200     m_group(grp),
1201     m_circuit(0),
1202     m_private(0),
1203     m_peer(0),
1204     m_getPeerEvent(false)
1205 {
1206     // Check and set some data
1207     const char* error = 0;
1208     while (true) {
1209 #define CHECK_DATA(test,sError) if (test) { error = sError; break; }
1210 	CHECK_DATA(!m_group,"circuit group is missing")
1211 	CHECK_DATA(m_group->findLine(cic),"circuit already allocated")
1212 	SignallingCircuit* circuit = m_group->find(cic);
1213 	if (circuit && circuit->ref())
1214 	    m_circuit = circuit;
1215 	CHECK_DATA(!m_circuit,"circuit is missing")
1216 	break;
1217 #undef CHECK_DATA
1218     }
1219     if (error) {
1220 	Debug(m_group,DebugNote,"Can't create analog line (cic=%u): %s",
1221 	    cic,error);
1222 	return;
1223     }
1224 
1225     m_type = m_group->type();
1226     if (m_type == Recorder)
1227 	m_type = FXO;
1228     m_address << m_group->toString() << "/" << m_circuit->code();
1229     m_inband = params.getBoolValue(YSTRING("dtmfinband"),false);
1230     String tmp = params.getValue(YSTRING("echocancel"));
1231     if (tmp.isBoolean())
1232 	m_echocancel = tmp.toBoolean() ? 1 : -1;
1233     m_answerOnPolarity = params.getBoolValue(YSTRING("answer-on-polarity"),false);
1234     m_hangupOnPolarity = params.getBoolValue(YSTRING("hangup-on-polarity"),false);
1235     m_polarityControl = params.getBoolValue(YSTRING("polaritycontrol"),false);
1236 
1237     m_callSetup = (CallSetupInfo)lookup(params.getValue(YSTRING("callsetup")),csNames(),After);
1238 
1239     m_callSetupTimeout = getValidInt(params,"callsetup-timeout",2000);
1240     m_noRingTimeout = getValidInt(params,"ring-timeout",10000);
1241     m_alarmTimeout = getValidInt(params,"alarm-timeout",30000);
1242     m_delayDial = getValidInt(params,"delaydial",2000);
1243 
1244     DDebug(m_group,DebugAll,"AnalogLine() addr=%s type=%s [%p]",
1245 	address(),lookup(m_type,typeNames()),this);
1246 
1247     if (!params.getBoolValue(YSTRING("out-of-service"),false)) {
1248 	resetCircuit();
1249 	if (params.getBoolValue(YSTRING("connect"),true))
1250 	    connect(false);
1251     }
1252     else
1253 	enable(false,false);
1254 }
1255 
~AnalogLine()1256 AnalogLine::~AnalogLine()
1257 {
1258     DDebug(m_group,DebugAll,"~AnalogLine() addr=%s [%p]",address(),this);
1259 }
1260 
1261 // Remove old peer's peer. Set this line's peer
setPeer(AnalogLine * line,bool sync)1262 void AnalogLine::setPeer(AnalogLine* line, bool sync)
1263 {
1264     Lock mylock(this);
1265     if (line == this) {
1266 	Debug(m_group,DebugNote,"%s: Attempt to set peer to itself [%p]",
1267 		address(),this);
1268 	return;
1269     }
1270     if (line == m_peer) {
1271 	if (sync && m_peer) {
1272 	    XDebug(m_group,DebugAll,"%s: Syncing with peer (%p) '%s' [%p]",
1273 		address(),m_peer,m_peer->address(),this);
1274 	    m_peer->setPeer(this,false);
1275 	}
1276 	return;
1277     }
1278     AnalogLine* tmp = m_peer;
1279     m_peer = 0;
1280     if (tmp) {
1281 	DDebug(m_group,DebugAll,"%s: Removed peer (%p) '%s' [%p]",
1282 	    address(),tmp,tmp->address(),this);
1283 	if (sync)
1284 	    tmp->setPeer(0,false);
1285     }
1286     m_peer = line;
1287     if (m_peer) {
1288 	DDebug(m_group,DebugAll,"%s: Peer set to (%p) '%s' [%p]",
1289 	    address(),m_peer,m_peer->address(),this);
1290 	if (sync)
1291 	    m_peer->setPeer(this,false);
1292     }
1293 }
1294 
1295 // Reset the line circuit's echo canceller to line default echo canceller state
resetEcho(bool train)1296 void AnalogLine::resetEcho(bool train)
1297 {
1298     if (!(m_circuit || m_echocancel))
1299 	return;
1300     bool enable = (m_echocancel > 0);
1301     m_circuit->setParam("echocancel",String::boolText(enable));
1302     if (enable && train)
1303 	m_circuit->setParam("echotrain",String(""));
1304 }
1305 
1306 // Connect the line's circuit. Reset line echo canceller
connect(bool sync)1307 bool AnalogLine::connect(bool sync)
1308 {
1309     Lock mylock(this);
1310     bool ok = m_circuit && m_circuit->connect();
1311     resetEcho(true);
1312     if (sync && ok && m_peer)
1313 	m_peer->connect(false);
1314     return ok;
1315 }
1316 
1317 // Disconnect the line's circuit. Reset line echo canceller
disconnect(bool sync)1318 bool AnalogLine::disconnect(bool sync)
1319 {
1320     Lock mylock(this);
1321     bool ok = m_circuit && m_circuit->disconnect();
1322     resetEcho(false);
1323     if (sync && ok && m_peer)
1324 	m_peer->disconnect(false);
1325     return ok;
1326 }
1327 
1328 // Send an event through this line
sendEvent(SignallingCircuitEvent::Type type,NamedList * params)1329 bool AnalogLine::sendEvent(SignallingCircuitEvent::Type type, NamedList* params)
1330 {
1331     Lock mylock(this);
1332     if (state() == OutOfService)
1333 	return false;
1334     if (m_inband &&
1335 	(type == SignallingCircuitEvent::Dtmf || type == SignallingCircuitEvent::PulseDigit))
1336 	return false;
1337     return m_circuit && m_circuit->sendEvent(type,params);
1338 }
1339 
1340 // Get events from the line's circuit if not out of service
getEvent(const Time & when)1341 AnalogLineEvent* AnalogLine::getEvent(const Time& when)
1342 {
1343     Lock mylock(this);
1344     if (state() == OutOfService) {
1345 	checkTimeouts(when);
1346 	return 0;
1347     }
1348 
1349     SignallingCircuitEvent* event = m_circuit ? m_circuit->getEvent(when) : 0;
1350     if (!event) {
1351 	checkTimeouts(when);
1352 	return 0;
1353     }
1354 
1355     if ((event->type() == SignallingCircuitEvent::PulseDigit ||
1356 	event->type() == SignallingCircuitEvent::PulseStart) &&
1357 	!m_acceptPulseDigit) {
1358 	DDebug(m_group,DebugInfo,"%s: ignoring pulse event '%s' [%p]",
1359 	    address(),event->c_str(),this);
1360 	delete event;
1361 	return 0;
1362     }
1363 
1364     return new AnalogLineEvent(this,event);
1365 }
1366 
1367 // Alternate get events from this line or peer
getMonitorEvent(const Time & when)1368 AnalogLineEvent* AnalogLine::getMonitorEvent(const Time& when)
1369 {
1370     Lock mylock(this);
1371     m_getPeerEvent = !m_getPeerEvent;
1372     AnalogLineEvent* event = 0;
1373     if (m_getPeerEvent) {
1374 	event = getEvent(when);
1375 	if (!event && m_peer)
1376 	    event = m_peer->getEvent(when);
1377     }
1378     else {
1379 	if (m_peer)
1380 	    event = m_peer->getEvent(when);
1381 	if (!event)
1382 	    event = getEvent(when);
1383     }
1384     return event;
1385 }
1386 
1387 // Change the line state if neither current or new state are OutOfService
changeState(State newState,bool sync)1388 bool AnalogLine::changeState(State newState, bool sync)
1389 {
1390     Lock mylock(this);
1391     bool ok = false;
1392     while (true) {
1393 	if (m_state == newState || m_state == OutOfService || newState == OutOfService)
1394 	    break;
1395 	if (newState != Idle && newState < m_state)
1396 	    break;
1397 	DDebug(m_group,DebugInfo,"%s: changed state from %s to %s [%p]",
1398 	    address(),lookup(m_state,stateNames()),
1399 	    lookup(newState,stateNames()),this);
1400 	m_state = newState;
1401 	ok = true;
1402 	break;
1403     }
1404     if (sync && ok && m_peer)
1405 	m_peer->changeState(newState,false);
1406     return true;
1407 }
1408 
1409 // Enable/disable line. Change circuit's state to Disabled/Reserved when
1410 //  entering/exiting the OutOfService state
enable(bool ok,bool sync,bool connectNow)1411 bool AnalogLine::enable(bool ok, bool sync, bool connectNow)
1412 {
1413     Lock mylock(this);
1414     while (true) {
1415 	if (ok) {
1416 	    if (m_state != OutOfService)
1417 		break;
1418 	    Debug(m_group,DebugInfo,"%s: back in service [%p]",address(),this);
1419 	    m_state = Idle;
1420 	    if (m_circuit) {
1421 		m_circuit->status(SignallingCircuit::Reserved);
1422 		if (connectNow)
1423 		    connect(false);
1424 	    }
1425 	    break;
1426 	}
1427 	// Disable
1428 	if (m_state == OutOfService)
1429 	    break;
1430 	Debug(m_group,DebugNote,"%s: out of service [%p]",address(),this);
1431 	m_state = OutOfService;
1432 	disconnect(false);
1433 	if (m_circuit)
1434 	    m_circuit->status(SignallingCircuit::Disabled);
1435 	break;
1436     }
1437     if (sync && m_peer)
1438 	m_peer->enable(ok,false,connectNow);
1439     return true;
1440 }
1441 
1442 // Deref the circuit
destroyed()1443 void AnalogLine::destroyed()
1444 {
1445     lock();
1446     disconnect(false);
1447     if (m_circuit)
1448 	m_circuit->status(SignallingCircuit::Idle);
1449     setPeer(0,true);
1450     if (m_group)
1451 	m_group->removeLine(this);
1452     TelEngine::destruct(m_circuit);
1453     unlock();
1454     RefObject::destroyed();
1455 }
1456 
1457 
1458 /**
1459  * AnalogLineGroup
1460  */
1461 
1462 // Construct an analog line group owning single lines
AnalogLineGroup(AnalogLine::Type type,const char * name,bool slave)1463 AnalogLineGroup::AnalogLineGroup(AnalogLine::Type type, const char* name, bool slave)
1464     : SignallingCircuitGroup(0,SignallingCircuitGroup::Increment,name),
1465     m_type(type),
1466     m_fxo(0),
1467     m_slave(false)
1468 {
1469     setName(name);
1470     if (m_type == AnalogLine::FXO)
1471 	m_slave = slave;
1472     XDebug(this,DebugAll,"AnalogLineGroup() [%p]",this);
1473 }
1474 
1475 // Constructs an FXS analog line monitor
AnalogLineGroup(const char * name,AnalogLineGroup * fxo)1476 AnalogLineGroup::AnalogLineGroup(const char* name, AnalogLineGroup* fxo)
1477     : SignallingCircuitGroup(0,SignallingCircuitGroup::Increment,name),
1478     m_type(AnalogLine::FXS),
1479     m_fxo(fxo)
1480 {
1481     setName(name);
1482     if (m_fxo)
1483 	m_fxo->debugChain(this);
1484     else
1485 	Debug(this,DebugWarn,"Request to create monitor without fxo group [%p]",this);
1486     XDebug(this,DebugAll,"AnalogLineGroup() monitor fxo=%p [%p]",m_fxo,this);
1487 }
1488 
~AnalogLineGroup()1489 AnalogLineGroup::~AnalogLineGroup()
1490 {
1491     XDebug(this,DebugAll,"~AnalogLineGroup() [%p]",this);
1492 }
1493 
1494 // Append it to the list
appendLine(AnalogLine * line,bool destructOnFail)1495 bool AnalogLineGroup::appendLine(AnalogLine* line, bool destructOnFail)
1496 {
1497     AnalogLine::Type type = m_type;
1498     if (type == AnalogLine::Recorder)
1499 	type = AnalogLine::FXO;
1500     if (!(line && line->type() == type && line->group() == this)) {
1501 	if (destructOnFail)
1502 	    TelEngine::destruct(line);
1503 	return false;
1504     }
1505     Lock mylock(this);
1506     m_lines.append(line);
1507     DDebug(this,DebugAll,"Added line (%p) %s [%p]",line,line->address(),this);
1508     return true;
1509 }
1510 
1511 // Remove a line from the list and destruct it
removeLine(unsigned int cic)1512 void AnalogLineGroup::removeLine(unsigned int cic)
1513 {
1514     Lock mylock(this);
1515     AnalogLine* line = findLine(cic);
1516     if (!line)
1517 	return;
1518     removeLine(line);
1519     TelEngine::destruct(line);
1520 }
1521 
1522 // Remove a line from the list without destroying it
removeLine(AnalogLine * line)1523 void AnalogLineGroup::removeLine(AnalogLine* line)
1524 {
1525     if (!line)
1526 	return;
1527     Lock mylock(this);
1528     if (m_lines.remove(line,false))
1529 	DDebug(this,DebugAll,"Removed line %p %s [%p]",line,line->address(),this);
1530 }
1531 
1532 // Find a line by its circuit
findLine(unsigned int cic)1533 AnalogLine* AnalogLineGroup::findLine(unsigned int cic)
1534 {
1535     Lock mylock(this);
1536     for (ObjList* o = m_lines.skipNull(); o; o = o->skipNext()) {
1537 	AnalogLine* line = static_cast<AnalogLine*>(o->get());
1538 	if (line->circuit() && line->circuit()->code() == cic)
1539 	    return line;
1540     }
1541     return 0;
1542 }
1543 
1544 // Find a line by its address
findLine(const String & address)1545 AnalogLine* AnalogLineGroup::findLine(const String& address)
1546 {
1547     Lock mylock(this);
1548     ObjList* tmp = m_lines.find(address);
1549     return tmp ? static_cast<AnalogLine*>(tmp->get()) : 0;
1550 }
1551 
1552 // Iterate through the line list to get an event
getEvent(const Time & when)1553 AnalogLineEvent* AnalogLineGroup::getEvent(const Time& when)
1554 {
1555     lock();
1556     ListIterator iter(m_lines);
1557     for (;;) {
1558 	AnalogLine* line = static_cast<AnalogLine*>(iter.get());
1559 	// End of iteration?
1560 	if (!line)
1561 	    break;
1562 	RefPointer<AnalogLine> lineRef = line;
1563 	// Dead pointer?
1564 	if (!lineRef)
1565 	    continue;
1566 	unlock();
1567 	AnalogLineEvent* event = !fxo() ? lineRef->getEvent(when) : lineRef->getMonitorEvent(when);
1568 	if (event)
1569 	    return event;
1570 	lock();
1571     }
1572     unlock();
1573     return 0;
1574 }
1575 
1576 // Remove all spans and circuits. Release object
destroyed()1577 void AnalogLineGroup::destroyed()
1578 {
1579     lock();
1580     for (ObjList* o = m_lines.skipNull(); o; o = o->skipNext()) {
1581 	AnalogLine* line = static_cast<AnalogLine*>(o->get());
1582 	Lock lock(line);
1583 	line->m_group = 0;
1584     }
1585     m_lines.clear();
1586     TelEngine::destruct(m_fxo);
1587     unlock();
1588     SignallingCircuitGroup::destroyed();
1589 }
1590 
1591 /* vi: set ts=8 sw=4 sts=4 noet: */
1592