1 /**
2  * analog.cpp
3  * This file is part of the YATE Project http://YATE.null.ro
4  *
5  * Yet Another Analog Channel
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 <yatephone.h>
23 #include <yatesig.h>
24 
25 using namespace TelEngine;
26 namespace { // anonymous
27 
28 class ModuleLine;                        // Module's interface to an analog line or recorder
29                                          // Manages the call setup detector and sends call setup info
30 class ModuleGroup;                       // Module's interface to a group of lines
31 class AnalogChannel;                     // Channel associated with an analog line
32 class AnalogCallRec;                     // Recorder call endpoint associated with an analog line monitor
33 class AnalogDriver;                      // Analog driver
34 class AnalogWorkerThread;                // Worker thread to get events from a group
35 class ChanNotifyHandler;                 // chan.notify handler (notify lines on detector events)
36 class EngineStartHandler;                // engine.start handler (start detectors on lines expectind data before ring)
37 
38 // Value for m_ringTimer interval. The timer is used to ignore some ring events
39 // Some ring patterns might raise multiple ring events for the same logical ring
40 // e.g. ring-ring....ring-ring...
41 #define RING_PATTERN_TIME 750
42 
43 // Module's interface to an analog line or monitor
44 class ModuleLine : public AnalogLine
45 {
46 public:
47     ModuleLine(ModuleGroup* grp, unsigned int cic, const NamedList& params, const NamedList& groupParams);
48     // Get the module group representation of this line's owner
49     ModuleGroup* moduleGroup();
caller() const50     inline const String& caller() const
51 	{ return m_caller; }
callerName() const52     inline const String& callerName() const
53 	{ return m_callerName; }
called()54     inline String& called()
55 	{ return m_called; }
noRingTimer()56     inline SignallingTimer& noRingTimer()
57 	{ return m_noRingTimer; }
58     // Send call setup data
59     void sendCallSetup(bool privacy);
60     // Set call setup detector
61     void setCallSetupDetector();
62     // Remove call setup detector
63     void removeCallSetupDetector();
64     // Process notifications from detector
65     void processNotify(Message& msg);
66     // Set the caller, callername and called parameters
setCall(const char * caller=0,const char * callername=0,const char * called=0)67     inline void setCall(const char* caller = 0, const char* callername = 0,
68 	const char* called = 0)
69 	{ m_caller = caller; m_callerName = callername; m_called = called; }
70     // Set the caller, callername and called parameters
71     void copyCall(NamedList& dest, bool privacy = false);
72     // Fill a string with line status parameters
73     void statusParams(String& str);
74     // Fill a string with line status detail parameters
75     void statusDetail(String& str);
76 protected:
77     virtual void checkTimeouts(const Time& when);
78     // Remove detector. Call parent's destructor
destroyed()79     virtual void destroyed() {
80 	    removeCallSetupDetector();
81 	    AnalogLine::destroyed();
82 	}
83     // Set the FXO line. Start detector if waiting call setup before first ring
84     void setFXO(AnalogLine* fxo);
85 
86     String m_called;                     // Called's extension
87     // Call setup (caller id)
88     String m_caller;                     // Caller's extension
89     String m_callerName;                 // Caller's name
90     String m_detector;                   // Call setup detector resource
91     DataConsumer* m_callSetupDetector;   // The call setup detector
92     SignallingTimer m_noRingTimer;       // No more rings detected on unanswered line
93     SignallingTimer m_callSetupTimer;    // Timeout of call setup data received before the first ring
94                                          // Stop detector if started and timeout
95 };
96 
97 // Module's interface to a group of lines
98 class ModuleGroup : public AnalogLineGroup
99 {
100     friend class AnalogWorkerThread;     // Set worker thread variable
101 public:
102     // Create an FXS/FXO group of analog lines
ModuleGroup(AnalogLine::Type type,const char * name)103     inline ModuleGroup(AnalogLine::Type type, const char* name)
104 	: AnalogLineGroup(type,name),
105 	  m_init(false), m_ringback(false), m_thread(0), m_callEndedPlayTime(0)
106 	{ m_prefix << name << "/"; }
107     // Create a group of analog lines used to record
ModuleGroup(const char * name,ModuleGroup * fxo)108     inline ModuleGroup(const char* name, ModuleGroup* fxo)
109 	: AnalogLineGroup(name,fxo), m_init(false), m_thread(0), m_callEndedPlayTime(0)
110 	{ m_prefix << name << "/"; }
111     // Create an FXO group of analog lines to be attached to a group of recorders
ModuleGroup(const char * name)112     inline ModuleGroup(const char* name)
113 	: AnalogLineGroup(AnalogLine::FXO,name), m_init(false), m_thread(0), m_callEndedPlayTime(0)
114 	{ m_prefix << name << "/"; }
~ModuleGroup()115     virtual ~ModuleGroup()
116 	{}
fxoRec()117     inline ModuleGroup* fxoRec()
118 	{ return static_cast<ModuleGroup*>(fxo()); }
prefix()119     inline const String& prefix()
120 	{ return m_prefix; }
ringback() const121     inline bool ringback() const
122 	{ return m_ringback; }
123     // Remove all channels associated with this group and stop worker thread
124     virtual void destruct();
125     // Process an event geberated by a line
126     void handleEvent(ModuleLine& line, SignallingCircuitEvent& event);
127     // Process an event generated by a monitor
128     void handleRecEvent(ModuleLine& line, SignallingCircuitEvent& event);
129     // Apply debug level. Call create and create worker thread on first init
130     // Re(load) lines and calls specific group reload
131     // Return false on failure
132     bool initialize(const NamedList& params, const NamedList& defaults, String& error);
133     // Copy some data to a module's channel
134     void copyData(AnalogChannel* chan);
135     // Append/remove endpoints from list
136     void setEndpoint(CallEndpoint* ep, bool add);
137     // Find a recorder by its line
138     AnalogCallRec* findRecorder(ModuleLine* line);
139     // Check timers for endpoints owned by this group
140     void checkTimers(Time& when);
141     // Fill a string with group status parameters
142     void statusParams(String& str);
143     // Fill a string with group status detail parameters
144     void statusDetail(String& str);
145 protected:
146     // Disconnect all group's endpoints
147     void clearEndpoints(const char* reason = 0);
148 private:
149     // Create FXS/FXO group data: called by initialize() on first init
150     bool create(const NamedList& params, const NamedList& defaults,
151 	String& error);
152     // Reload FXS/FXO data: called by initialize() (not called on first init if create failed)
153     bool reload(const NamedList& params, const NamedList& defaults,
154 	String& error);
155     // Create recorder group data: called by initialize() on first init
156     bool createRecorder(const NamedList& params, const NamedList& defaults,
157 	String& error);
158     // Reload recorder data: called by initialize() (not called on first init if create failed)
159     bool reloadRecorder(const NamedList& params, const NamedList& defaults,
160 	String& error);
161     // Reload existing line's parameters
162     void reloadLine(ModuleLine* line, const NamedList& params);
163     // Build the group of circuits (spans)
164     void buildGroup(ModuleGroup* group, ObjList& spanList, String& error);
165     // Complete missing line parameters from other list of parameters
completeLineParams(NamedList & dest,const NamedList & src,const NamedList & defaults)166     inline void completeLineParams(NamedList& dest, const NamedList& src, const NamedList& defaults) {
167 	    for (unsigned int i = 0; lineParams[i]; i++)
168 		if (!dest.getParam(lineParams[i]))
169 		    dest.addParam(lineParams[i],src.getValue(lineParams[i],
170 			defaults.getValue(lineParams[i])));
171 	}
172     // Line parameters that can be overridden
173     static const char* lineParams[];
174 
175     bool m_init;                         // Init flag
176     bool m_ringback;                     // Lines need to provide ringback
177     String m_prefix;                     // Line prefix used to complete commands
178     AnalogWorkerThread* m_thread;        // The worker thread
179     // FXS/FXO group data
180     String m_callEndedTarget;            // callto when an FXS line was disconnected
181     String m_oooTarget;                  // callto when out-of-order (hook is off for a long time after call ended)
182     String m_lang;                       // Language for played tones
183     u_int64_t m_callEndedPlayTime;       // Time to play call ended prompt
184     // Recorder group data
185     ObjList m_endpoints;                 // Record data endpoints
186 };
187 
188 // Channel associated with an analog line
189 class AnalogChannel : public Channel
190 {
191     friend class ModuleGroup;            // Copy data
192 public:
193     enum RecordTrigger {
194 	None = 0,
195 	FXO,
196 	FXS
197     };
198     AnalogChannel(ModuleLine* line, Message* msg, RecordTrigger recorder = None);
199     virtual ~AnalogChannel();
line() const200     inline ModuleLine* line() const
201         { return m_line; }
202     // Start outgoing media and echo train if earlymedia or got peer with data source
203     virtual bool msgProgress(Message& msg);
204     // Start outgoing media and echo train if earlymedia or got peer with data source
205     virtual bool msgRinging(Message& msg);
206     // Terminate ringing on line. Start echo train. Open audio streams
207     virtual bool msgAnswered(Message& msg);
208     // Send tones or flash
209     virtual bool msgTone(Message& msg, const char* tone);
210     // Hangup line
211     virtual bool msgDrop(Message& msg, const char* reason);
212     // Update echo canceller and/or start echo training
213     virtual bool msgUpdate(Message& msg);
214     // Set tone detector
215     virtual bool callRouted(Message& msg);
216     // Open media if not answered
217     virtual void callAccept(Message& msg);
218     // Hangup
219     virtual void callRejected(const char* error, const char* reason = 0,
220 	const Message* msg = 0);
221     // Disconnected notification
222     virtual void disconnected(bool final, const char* reason);
223     // Hangup
224     bool disconnect(const char* reason = 0);
225     // Hangup call
226     // Keep call alive to play announcements on FXS line not set on hook by the remote FXO
227     void hangup(bool local, const char* status = 0, const char* reason = 0);
228     // Enqueue chan.dtmf message
229     void evDigits(const char* text, bool tone);
230     // Line got off hook. Terminate ringing
231     // Outgoing: answer it (call outCallAnswered()). Incoming: start echo train
232     void evOffHook();
233     // Line ring on/off notification. Ring off is ignored
234     // Outgoing: enqueue call.ringing
235     // Incoming: FXO: Route the call if delayed. Remove line's detector and start ring timer
236     void evRing(bool on);
237     // Line started (initialized) notification
238     // Answer outgoing FXO calls on lines not expecting polarity changes to answer
239     // Send called number if any
240     void evLineStarted();
241     // Dial complete notification. Enqueue call.progress
242     // Answer outgoing FXO calls on lines not expecting polarity changes to answer
243     void evDialComplete();
244     // Line polarity change notification
245     // Terminate call if:
246     //   - no line or line is not FXO,
247     //   - Outgoing: don't answer on polarity or already answered and should hangup on polarity change
248     //   - Incoming: don't answer on polarity or polarity already changed and should hangup on polarity change
249     // Outgoing: don't answer on polarity or already answered: call outCallAnswered()
250     void evPolarity();
251     // Line ok: stop alarm timer
252     // Terminate channel if not answered; otherwise: start timer if not already started
253     void evAlarm(bool alarm, const char* alarms);
254     // Check timers. Return false to terminate
255     bool checkTimeouts(const Time& when);
256 protected:
257     // Set reason if not already set
setReason(const char * reason)258     inline void setReason(const char* reason)
259 	{ if (!m_reason) m_reason = reason; }
260     // Route incoming. If first is false the router is started on second ring
261     void startRouter(bool first);
262     // Set data source and consumer
263     bool setAudio(bool in);
264     // Set call status. Return true
265     bool setStatus(const char* newStat = 0);
266     // Set tones to the remote end of the line
267     bool setAnnouncement(const char* status, const char* callto);
268     // Outgoing call answered: set call state, start echo train, open data source/consumer
269     void outCallAnswered(bool stopDial = true);
270     // Hangup. Release memory
271     virtual void destroyed();
272     // Detach the line from this channel and reset it
273     void detachLine();
274     // Send tones (DTMF or dial number)
275     bool sendTones(const char* tone, bool dial = true);
276     // Set line polarity
polarityControl(bool state)277     inline void polarityControl(bool state) {
278 	    if (!(m_line && m_line->type() == AnalogLine::FXS &&
279 		m_line->polarityControl() && state != m_polarity))
280 		return;
281 	    m_polarity = state;
282 	    m_line->setCircuitParam("polarity",String::boolText(m_polarity));
283 	}
284 private:
285     ModuleLine* m_line;                  // The analog line associated with this channel
286     bool m_hungup;                       // Hang up flag
287     bool m_ringback;                     // Circuit ringback provider flag
288     bool m_routeOnSecondRing;            // Delay router if waiting callerid
289     RecordTrigger m_recording;           // Recording trigger source
290     String m_reason;                     // Hangup reason
291     SignallingTimer m_callEndedTimer;    // Call ended notification to the FXO
292     SignallingTimer m_ringTimer;         // Timer used to fix some ring patterns
293     SignallingTimer m_alarmTimer;        // How much time a channel may stay with its line in alarm
294     SignallingTimer m_dialTimer;         // FXO: delay dialing the number
295                                          // FXS: send call setup after first ring
296     String m_callEndedTarget;            // callto when an FXS line was disconnected
297     String m_oooTarget;                  // callto when out-of-order (hook is off for a long time after call ended)
298     String m_lang;                       // Language for played tones
299     unsigned int m_polarityCount;        // The number of polarity changes received
300     bool m_polarity;                     // The last value we've set for the line polarity
301     bool m_privacy;                      // Send caller identity
302     int m_callsetup;                     // Send callsetup before/after first ring
303 };
304 
305 // Recorder call endpoint associated with an analog line monitor
306 class AnalogCallRec : public CallEndpoint, public DebugEnabler
307 {
308 public:
309     // Append to driver's list
310     AnalogCallRec(ModuleLine* m_line, bool fxsCaller, const char* id);
line()311     inline ModuleLine* line()
312 	{ return m_line; }
fxo() const313     inline ModuleLine* fxo() const
314 	{ return m_line ? static_cast<ModuleLine*>(m_line->getPeer()) : 0; }
startOnSecondRing()315     inline bool startOnSecondRing()
316 	{ return m_startOnSecondRing; }
317     void hangup(const char* reason = "normal");
318     bool disconnect(const char* reason);
319     virtual void* getObject(const String& name) const;
reason()320     inline const char* reason()
321 	{ return m_reason; }
322     // Create data source. Route and execute
323     // Return false to hangup
324     bool startRecording();
325     // Call answered: start recording
326     bool answered();
327     // Process rings: start recording if delayed
328     // Return false to hangup
329     bool ringing(bool fxsEvent);
330     // Enqueue chan.dtmf
331     void evDigits(bool fxsEvent, const char* text, bool tone);
332     // Process line polarity changes. Return false to hangup
333     bool evPolarity(bool fxsEvent);
334     // Line alarms changed
335     bool evAlarm(bool fxsEvent, bool alarm, const char* alarms);
336     // Check timers. Return false to terminate
337     bool checkTimeouts(const Time& when);
338     // Fill a string with recorder status parameters
339     void statusParams(String& str);
340     // Fill a string with recorder status detail parameters
341     void statusDetail(String& str);
342 protected:
343     // Remove from driver's list
344     virtual void destroyed();
345     virtual void disconnected(bool final, const char *reason);
346     // Create a message to be enqueued/dispatched to the engine
347     // @param peers True to add caller and called parameters
348     // @param userdata True to add this call endpoint as user data
349     Message* message(const char* name, bool peers = true, bool userdata = false);
350 private:
351     ModuleLine* m_line;                  // The monitored lines
352     bool m_fxsCaller;                    // True if the call originated from the FXS
353     bool m_answered;                     // True if answered
354     bool m_hungup;                       // Already hungup flag
355     unsigned int m_polarityCount;        // The number of polarity changes received
356     bool m_startOnSecondRing;            // Start recording on second ring if waiting callerid
357     SignallingTimer m_ringTimer;         // Timer used to fix some ring patterns
358     String m_reason;                     // Hangup reason
359     String m_status;                     // Call status
360     String m_address;                    // Call enspoint's address
361 };
362 
363 // The driver
364 class AnalogDriver : public Driver
365 {
366 public:
367     // Additional driver commands
368     enum Commands {
369 	CmdCount = 0
370     };
371     // Additional driver status commands
372     enum StatusCommands {
373 	Groups         = 0,              // Show all groups
374 	Lines          = 1,              // Show all lines
375 	Recorders      = 2,              // Show all active recorders
376 	StatusCmdCount = 3
377     };
378     AnalogDriver();
379     ~AnalogDriver();
recPrefix()380     inline const String& recPrefix()
381 	{ return m_recPrefix; }
382     virtual void initialize();
383     virtual bool msgExecute(Message& msg, String& dest);
384     virtual void dropAll(Message& msg);
385     // Check timers for recorders owned by the given group
386     void checkTimers(Time& when, ModuleGroup* recGrp);
387     // Notification of line service state change or removal
388     // Return true if a channel or recorder was found
389     bool lineUnavailable(ModuleLine* line);
390     // Disconnect or deref a channel
391     void terminateChan(AnalogChannel* ch, const char* reason = "normal");
392     // Destroy a monitor endpoint
393     void terminateChan(AnalogCallRec* ch, const char* reason = "normal");
394     // Attach detectors after engine started
395     void engineStart(Message& msg);
396     // Notify lines on detector events
397     bool chanNotify(Message& msg);
398     // Get an id for a recorder
nextRecId()399     inline unsigned int nextRecId() {
400 	    Lock lock(this);
401 	    return ++m_recId;
402 	}
403     // Append/remove recorders from list
404     void setRecorder(AnalogCallRec* rec, bool add);
405     // Find a group by its name
findGroup(const String & name)406     inline ModuleGroup* findGroup(const String& name) {
407 	    Lock lock(this);
408 	    ObjList* obj = m_groups.find(name);
409 	    return obj ? static_cast<ModuleGroup*>(obj->get()) : 0;
410 	}
411     // Find a recorder by its id
findRecorder(const String & name)412     inline AnalogCallRec* findRecorder(const String& name) {
413 	    Lock lock(this);
414 	    ObjList* obj = m_recorders.find(name);
415 	    return obj ? static_cast<AnalogCallRec*>(obj->get()) : 0;
416 	}
417     // Additional driver status commands
418     static String s_statusCmd[StatusCmdCount];
419 protected:
420     virtual bool received(Message& msg, int id);
421     // Handle command complete requests
422     virtual bool commandComplete(Message& msg, const String& partLine,
423 	const String& partWord);
424     // Execute commands
425     virtual bool commandExecute(String& retVal, const String& line);
426     // Complete channels/recorders IDs from partial command word
completeChanRec(String & dest,const String & partWord,bool chans,bool all)427     inline void completeChanRec(String& dest, const String& partWord,
428 	bool chans, bool all) {
429 	    ObjList* o = (chans ? channels().skipNull() : m_recorders.skipNull());
430 	    for (; o; o = o->skipNext()) {
431 		CallEndpoint* c = static_cast<CallEndpoint*>(o->get());
432 		if (all || c->id().startsWith(partWord))
433 		    dest.append(c->id(),"\t");
434 	    }
435 	}
436     // Complete group names from partial command word
437     void completeGroups(String& dest, const String& partWord);
438     // Complete line names from partial command word
439     void completeLines(String& dest, const String& partWord);
440     // Remove a group from list
441     void removeGroup(ModuleGroup* group);
442     // Find a group or recorder by its name
443     // Set useFxo to true to find a recorder by its fxo's name
444     ModuleGroup* findGroup(const char* name, bool useFxo);
445 private:
446     bool m_init;                         // Init flag
447     String m_recPrefix;                  // Prefix used for recorders
448     unsigned int m_recId;                // Next recorder id
449     ObjList m_groups;                    // Analog line groups
450     ObjList m_recorders;                 // Recorders created by monitor groups
451     String m_statusCmd;                  // Prefix for status commands
452 };
453 
454 // Get events from a group. Check timers for lines
455 class AnalogWorkerThread : public Thread
456 {
457 public:
458     AnalogWorkerThread(ModuleGroup* group);
459     virtual ~AnalogWorkerThread();
460     virtual void run();
461 private:
462     ModuleGroup* m_client;               // The module's group client
463     String m_groupName;                  // Group's name (saved to be printed in destructor)
464 };
465 
466 
467 /**
468  * Module data and functions
469  */
470 static AnalogDriver plugin;
471 static Configuration s_cfg;
472 static bool s_engineStarted = false;               // Received engine.start message
473 static const char* s_lineSectPrefix = "line ";     // Prefix for line sections in config
474 static const char* s_unk = "unknown";              // Used to set caller
475 // Status detail formats
476 static const char* s_lineStatusDetail = "format=State|UsedBy";
477 static const char* s_groupStatusDetail = "format=Type|Lines";
478 static const char* s_recStatusDetail = "format=Status|Address|Peer";
479 
480 
481 // engine.start handler (start detectors on lines expectind data before ring)
482 class EngineStartHandler : public MessageHandler
483 {
484 public:
EngineStartHandler()485     inline EngineStartHandler()
486 	: MessageHandler("engine.start",100,plugin.name())
487 	{}
488     virtual bool received(Message& msg);
489 };
490 
491 // chan.notify handler (notify lines on detector events)
492 class ChanNotifyHandler : public MessageHandler
493 {
494 public:
ChanNotifyHandler()495     inline ChanNotifyHandler()
496 	: MessageHandler("chan.notify",100,plugin.name())
497 	{}
498     virtual bool received(Message& msg);
499 };
500 
501 
502 // Decode a line address into group name and circuit code
503 // Set first to decode group name until first '/'
504 // Return:
505 //   -1 if src is the name of the group
506 //   -2 if src contains invalid circuit code
507 //   Otherwise: The integer part of the circuit code
decodeAddr(const String & src,String & group,bool first)508 inline int decodeAddr(const String& src, String& group, bool first)
509 {
510     int pos = first ? src.find("/") : src.rfind('/');
511     if (pos == -1) {
512 	group = src;
513 	return -1;
514     }
515     group = src.substr(0,pos);
516     return src.substr(pos+1).toInteger(-2);
517 }
518 
519 // Get FXS/FXO type string
callertype(bool fxs)520 inline const char* callertype(bool fxs)
521 {
522     return fxs ? "fxs" : "fxo";
523 }
524 
525 // Get privacy from message
526 // Return true if caller's identity is private (screened)
getPrivacy(const Message & msg)527 static inline bool getPrivacy(const Message& msg)
528 {
529     String tmp = msg.getValue("privacy");
530     if (!tmp)
531 	return false;
532     if (!tmp.isBoolean())
533 	return true;
534     return tmp.toBoolean();
535 }
536 
537 
538 /**
539  * ModuleLine
540  */
ModuleLine(ModuleGroup * grp,unsigned int cic,const NamedList & params,const NamedList & groupParams)541 ModuleLine::ModuleLine(ModuleGroup* grp, unsigned int cic, const NamedList& params, const NamedList& groupParams)
542     : AnalogLine(grp,cic,params),
543     m_callSetupDetector(0),
544     m_noRingTimer(0),
545     m_callSetupTimer(callSetupTimeout())
546 {
547     m_detector = groupParams.getValue("analogdetect","analogdetect/callsetup");
548     m_detector = params.getValue("analogdetect",m_detector);
549     if (type() == AnalogLine::FXO && callSetup() == AnalogLine::Before && s_engineStarted)
550 	setCallSetupDetector();
551 }
552 
moduleGroup()553 inline ModuleGroup* ModuleLine::moduleGroup()
554 {
555     return static_cast<ModuleGroup*>(group());
556 }
557 
558 // Send call setup data through the FXS line
sendCallSetup(bool privacy)559 void ModuleLine::sendCallSetup(bool privacy)
560 {
561     if (type() != AnalogLine::FXS)
562 	return;
563     Lock lock(this);
564     if (callSetup() == AnalogLine::NoCallSetup)
565 	return;
566 
567     Message msg("chan.attach");
568     if (userdata())
569 	msg.userData(static_cast<RefObject*>(userdata()));
570     msg.addParam("source",m_detector);
571     msg.addParam("single",String::boolText(true));
572     String tmp;
573     tmp << plugin.prefix() << address();
574     msg.addParam("notify",tmp);
575     copyCall(msg,privacy);
576 
577     if (Engine::dispatch(msg))
578 	return;
579     Debug(group(),DebugNote,"%s: failed to send call setup reason='%s' [%p]",
580 	address(),msg.getValue("reason"),this);
581 }
582 
583 // Set the call setup detector
setCallSetupDetector()584 void ModuleLine::setCallSetupDetector()
585 {
586     removeCallSetupDetector();
587     m_callerName = "";
588 
589     Lock lock(this);
590     if (callSetup() == AnalogLine::NoCallSetup)
591 	return;
592 
593     // Dispatch message
594     DataSource* src = 0;
595     if (circuit())
596 	src = static_cast<DataSource*>(circuit()->getObject(YATOM("DataSource")));
597     Message msg("chan.attach");
598     msg.userData(src);
599     msg.addParam("consumer",m_detector);
600     msg.addParam("single",String::boolText(true));
601     String tmp;
602     tmp << plugin.prefix() << address();
603     msg.addParam("notify",tmp);
604 
605     const char* error = 0;
606     while (true) {
607 	if (!Engine::dispatch(msg)) {
608 	    error = msg.getValue("reason");
609 	    if (!error)
610 		error = "chan.attach failed";
611 	    break;
612 	}
613 	DataConsumer* cons = 0;
614 	if (msg.userData())
615 	    cons = static_cast<DataConsumer*>(msg.userData()->getObject(YATOM("DataConsumer")));
616 	if (cons && cons->ref())
617 	    m_callSetupDetector = cons;
618 	else
619 	    error = "chan.attach returned without consumer";
620 	break;
621     }
622 
623     if (!error)
624 	DDebug(group(),DebugAll,"%s: attached detector (%p) [%p]",
625 	    address(),m_callSetupDetector,this);
626     else
627 	Debug(group(),DebugNote,"%s: failed to attach detector error='%s' [%p]",
628 	    address(),error,this);
629 }
630 
631 // Remove the call setup detector from FXO line
removeCallSetupDetector()632 void ModuleLine::removeCallSetupDetector()
633 {
634     Lock lock(this);
635     if (!m_callSetupDetector)
636 	return;
637 
638     m_callSetupTimer.stop();
639     DataSource* src = m_callSetupDetector->getConnSource();
640     if (src)
641 	src->detach(m_callSetupDetector);
642     DDebug(group(),DebugAll,"%s: removed detector (%p) [%p]",
643 	address(),m_callSetupDetector,this);
644     TelEngine::destruct(m_callSetupDetector);
645 }
646 
647 // Process notifications from detector
processNotify(Message & msg)648 void ModuleLine::processNotify(Message& msg)
649 {
650     String operation = msg.getValue("operation");
651 
652     Lock lock(this);
653 
654     if (operation == "setup") {
655 	DDebug(group(),DebugAll,
656 	    "%s: received setup info detector=%p caller=%s callername=%s called=%s [%p]",
657 	    address(),m_callSetupDetector,
658 	    msg.getValue("caller"),msg.getValue("callername"),
659 	    msg.getValue("called"),this);
660 	if (!m_callSetupDetector)
661 	    return;
662 	m_called = msg.getValue("called",m_called);
663 	m_caller = msg.getValue("caller");
664 	m_callerName = msg.getValue("callername");
665     }
666     else if (operation == "terminate") {
667 	DDebug(group(),DebugAll,"%s: detector (%p) terminated reason=%s [%p]",
668 	    address(),m_callSetupDetector,msg.getValue("reason"),this);
669 	removeCallSetupDetector();
670     }
671     else if (operation == "start") {
672 	DDebug(group(),DebugAll,"%s: detector (%p) started [%p]",
673 	    address(),m_callSetupDetector,this);
674 	if (callSetup() == AnalogLine::Before && m_callSetupDetector)
675 	    m_callSetupTimer.start();
676     }
677     else
678 	DDebug(group(),DebugStub,
679 	    "%s: received notification with operation=%s [%p]",
680 	    address(),operation.c_str(),this);
681 }
682 
683 // Set the caller, callername and called parameters
copyCall(NamedList & dest,bool privacy)684 void ModuleLine::copyCall(NamedList& dest, bool privacy)
685 {
686     if (privacy)
687 	dest.addParam("callerpres","restricted");
688     else {
689 	if (m_caller)
690 	    dest.addParam("caller",m_caller);
691 	if (m_callerName)
692 	    dest.addParam("callername",m_callerName);
693     }
694     if (m_called)
695 	dest.addParam("called",m_called);
696 }
697 
698 // Fill a string with line status parameters
statusParams(String & str)699 void ModuleLine::statusParams(String& str)
700 {
701     str.append("module=",";") << plugin.name();
702     str << ",address=" << address();
703     str << ",type=" << lookup(type(),typeNames());
704     str << ",state=" << lookup(state(),stateNames());
705     str  << ",usedby=";
706     if (userdata())
707 	str << (static_cast<CallEndpoint*>(userdata()))->id();
708     str << ",polaritycontrol=" << polarityControl();
709     if (type() == AnalogLine::FXO) {
710 	str << ",answer-on-polarity=" << answerOnPolarity();
711 	str << ",hangup-on-polarity=" << hangupOnPolarity();
712     }
713     else
714 	str << ",answer-on-polarity=not-defined,hangup-on-polarity=not-defined";
715     str << ",callsetup=" << lookup(callSetup(),AnalogLine::csNames());
716     // Lines with peer are used in recorders (don't send DTMFs)
717     if (!getPeer())
718 	str << ",dtmf=" << (outbandDtmf() ? "outband" : "inband");
719     else
720 	str << ",dtmf=not-defined";
721 
722     // Fill peer status
723     bool master = (type() == AnalogLine::FXS && getPeer());
724     if (master)
725 	(static_cast<ModuleLine*>(getPeer()))->statusParams(str);
726 }
727 
728 // Fill a string with line status detail parameters
statusDetail(String & str)729 void ModuleLine::statusDetail(String& str)
730 {
731     // format=State|UsedBy
732     Lock lock(this);
733     str.append(address(),";") << "=";
734     str << lookup(state(),AnalogLine::stateNames()) << "|";
735     if (userdata())
736 	str << (static_cast<CallEndpoint*>(userdata()))->id();
737 }
738 
739 // Check detector timeout. Calls line's timeout check method
checkTimeouts(const Time & when)740 void ModuleLine::checkTimeouts(const Time& when)
741 {
742     if (m_callSetupTimer.timeout(when.msec())) {
743 	m_callSetupTimer.stop();
744 	DDebug(group(),DebugNote,"%s: call setup timed out [%p]",address(),this);
745 	// Reset detector
746 	setCallSetupDetector();
747     }
748     AnalogLine::checkTimeouts(when);
749 }
750 
751 
752 /**
753  * ModuleGroup
754  */
755 // Line parameters that can be overridden
756 const char* ModuleGroup::lineParams[] = {"echocancel","dtmfinband","answer-on-polarity",
757     "hangup-on-polarity","ring-timeout","callsetup","alarm-timeout","delaydial",
758     "polaritycontrol",0};
759 
760 // Remove all channels associated with this group and stop worker thread
destruct()761 void ModuleGroup::destruct()
762 {
763     clearEndpoints(Engine::exiting()?"shutdown":"out-of-service");
764     if (m_thread) {
765 	XDebug(this,DebugInfo,"Terminating worker thread [%p]",this);
766 	m_thread->cancel(false);
767 	while (m_thread)
768 	    Thread::yield(true);
769 	Debug(this,DebugInfo,"Worker thread terminated [%p]",this);
770     }
771     AnalogLineGroup::destruct();
772 }
773 
774 // Process an event generated by a line
handleEvent(ModuleLine & line,SignallingCircuitEvent & event)775 void ModuleGroup::handleEvent(ModuleLine& line, SignallingCircuitEvent& event)
776 {
777     Lock lock(&plugin);
778     AnalogChannel* ch = static_cast<AnalogChannel*>(line.userdata());
779     DDebug(this,DebugInfo,"Processing event %u '%s' line=%s channel=%s",
780 	event.type(),event.c_str(),line.address(),ch?ch->id().c_str():"");
781 
782     switch (event.type()) {
783 	case SignallingCircuitEvent::OffHook:
784 	case SignallingCircuitEvent::Wink:
785 	    // Line got offhook - clear the ring timer
786 	    line.noRingTimer().stop();
787 	default: ;
788     }
789     if (ch) {
790 	switch (event.type()) {
791 	    case SignallingCircuitEvent::Dtmf:
792 		ch->evDigits(event.getValue("tone"),true);
793 		break;
794 	    case SignallingCircuitEvent::PulseDigit:
795 		ch->evDigits(event.getValue("pulse"),false);
796 		break;
797 	    case SignallingCircuitEvent::OnHook:
798 		ch->hangup(false);
799 		plugin.terminateChan(ch);
800 		break;
801 	    case SignallingCircuitEvent::OffHook:
802 	    case SignallingCircuitEvent::Wink:
803 		ch->evOffHook();
804 		break;
805 	    case SignallingCircuitEvent::RingBegin:
806 	    case SignallingCircuitEvent::RingerOn:
807 		ch->evRing(true);
808 		break;
809 	    case SignallingCircuitEvent::RingEnd:
810 	    case SignallingCircuitEvent::RingerOff:
811 		ch->evRing(false);
812 		break;
813 	    case SignallingCircuitEvent::LineStarted:
814 		ch->evLineStarted();
815 		break;
816 	    case SignallingCircuitEvent::DialComplete:
817 		ch->evDialComplete();
818 		break;
819 	    case SignallingCircuitEvent::Polarity:
820 		ch->evPolarity();
821 		break;
822 	    case SignallingCircuitEvent::Flash:
823 		ch->evDigits("F",true);
824 		break;
825 	    case SignallingCircuitEvent::PulseStart:
826 		DDebug(ch,DebugAll,"Pulse dialing started [%p]",ch);
827 		break;
828 	    case SignallingCircuitEvent::Alarm:
829 	    case SignallingCircuitEvent::NoAlarm:
830 		ch->evAlarm(event.type() == SignallingCircuitEvent::Alarm,event.getValue("alarms"));
831 		break;
832 	    default:
833 		Debug(this,DebugStub,"handleEvent(%u,'%s') not implemented [%p]",
834 		    event.type(),event.c_str(),this);
835 	}
836     }
837     else
838 	if ((line.type() == AnalogLine::FXS &&
839 		event.type() == SignallingCircuitEvent::OffHook) ||
840 	    (line.type() == AnalogLine::FXO &&
841 		((event.type() == SignallingCircuitEvent::RingBegin) ||
842 		(type() == AnalogLine::Recorder && event.type() == SignallingCircuitEvent::Wink)))) {
843 	    if (!line.ref()) {
844 		Debug(this,DebugWarn,"Incoming call on line '%s' failed [%p]",
845 		    line.address(),this);
846 		return;
847 	    }
848 	    if (line.noRingTimer().started()) {
849 		if (line.noRingTimer().timeout())
850 		    line.noRingTimer().stop();
851 		else {
852 		    DDebug(this,DebugNote,
853 			"Ring timer still active on line (%p,%s) without channel [%p]",
854 			&line,line.address(),this);
855 		    // Restart the timer
856 		    line.noRingTimer().start();
857 		    return;
858 		}
859 	    }
860 	    AnalogChannel::RecordTrigger rec =
861 		(type() == AnalogLine::Recorder)
862 		    ? ((event.type() == SignallingCircuitEvent::RingBegin)
863 			? AnalogChannel::FXS : AnalogChannel::FXO)
864 		    : AnalogChannel::None;
865 	    ch = new AnalogChannel(&line,0,rec);
866 	    ch->initChan();
867 	    if (!ch->line())
868 		plugin.terminateChan(ch);
869 	}
870 	else
871 	    DDebug(this,DebugNote,
872 		"Event (%p,%u,%s) from line (%p,%s) without channel [%p]",
873 		&event,event.type(),event.c_str(),&line,line.address(),this);
874 }
875 
876 // Process an event generated by a recorder
handleRecEvent(ModuleLine & line,SignallingCircuitEvent & event)877 void ModuleGroup::handleRecEvent(ModuleLine& line, SignallingCircuitEvent& event)
878 {
879     Lock lock(&plugin);
880     AnalogCallRec* rec = static_cast<AnalogCallRec*>(line.userdata());
881     DDebug(this,DebugInfo,"Processing event %u '%s' line=%s recorder=%s",
882 	event.type(),event.c_str(),line.address(),rec?rec->id().c_str():"");
883     if (event.type() == SignallingCircuitEvent::OffHook)
884 	    line.noRingTimer().stop();
885     if (rec) {
886 	// FXS event: our FXO receiver is watching the FXS end of the monitored line
887 	bool fxsEvent = (line.type() == AnalogLine::FXO);
888 	bool terminate = false;
889 	switch (event.type()) {
890 	    case SignallingCircuitEvent::Dtmf:
891 		rec->evDigits(fxsEvent,event.getValue("tone"),true);
892 		break;
893 	    case SignallingCircuitEvent::PulseDigit:
894 		rec->evDigits(fxsEvent,event.getValue("pulse"),false);
895 		break;
896 	    case SignallingCircuitEvent::OnHook:
897 		terminate = true;
898 		break;
899 	    case SignallingCircuitEvent::OffHook:
900 		terminate = !rec->answered();
901 		return;
902 	    case SignallingCircuitEvent::RingBegin:
903 	    case SignallingCircuitEvent::RingerOn:
904 		terminate = !rec->ringing(fxsEvent);
905 		break;
906 	    case SignallingCircuitEvent::Polarity:
907 		terminate = !rec->evPolarity(fxsEvent);
908 		break;
909 	    case SignallingCircuitEvent::Flash:
910 		rec->evDigits(fxsEvent,"F",true);
911 		break;
912 	    case SignallingCircuitEvent::Alarm:
913 	    case SignallingCircuitEvent::NoAlarm:
914 		terminate = !rec->evAlarm(fxsEvent,event.type() == SignallingCircuitEvent::Alarm,
915 		    event.getValue("alarms"));
916 		break;
917 	    case SignallingCircuitEvent::RingEnd:
918 	    case SignallingCircuitEvent::RingerOff:
919 	    case SignallingCircuitEvent::PulseStart:
920 	    case SignallingCircuitEvent::LineStarted:
921 	    case SignallingCircuitEvent::DialComplete:
922 	    case SignallingCircuitEvent::Wink:
923 		DDebug(rec,DebugAll,"Ignoring '%s' event [%p]",event.c_str(),rec);
924 		break;
925 	    default:
926 		Debug(this,DebugStub,"handleRecEvent(%u,'%s') not implemented [%p]",
927 		    event.type(),event.c_str(),this);
928 	}
929 	if (terminate) {
930 	    rec->hangup();
931 	    plugin.terminateChan(rec);
932 	}
933 	return;
934     }
935 
936     // Check for new call
937     bool fxsCaller = (line.type() == AnalogLine::FXO && event.type() == SignallingCircuitEvent::RingBegin);
938     bool fxoCaller = (line.type() == AnalogLine::FXS && event.type() == SignallingCircuitEvent::OffHook);
939 
940     if (!(fxsCaller || fxoCaller)) {
941 	DDebug(this,DebugNote,
942 	    "Event (%p,%u,%s) from line (%p,%s) without recorder [%p]",
943 	    &event,event.type(),event.c_str(),&line,line.address(),this);
944 	return;
945     }
946 
947     String id;
948     id << plugin.recPrefix() << plugin.nextRecId();
949     ModuleLine* fxs = (line.type() == AnalogLine::FXS ? &line : static_cast<ModuleLine*>(line.getPeer()));
950     rec = new AnalogCallRec(fxs,fxsCaller,id);
951     if (!(rec->line() && rec->fxo())) {
952 	plugin.terminateChan(rec,rec->reason());
953 	return;
954     }
955     if (rec->startOnSecondRing()) {
956 	DDebug(rec,DebugAll,"Delaying start until next ring [%p]",rec);
957 	return;
958     }
959     bool ok = true;
960     if (fxsCaller || rec->fxo()->answerOnPolarity())
961 	ok = rec->startRecording();
962     else
963 	ok = rec->answered();
964     if (!ok) {
965 	rec->hangup();
966 	plugin.terminateChan(rec,rec->reason());
967     }
968 }
969 
970 // Apply debug level. Call create and create worker thread on first init
971 // Re(load) lines and calls specific group reload
initialize(const NamedList & params,const NamedList & defaults,String & error)972 bool ModuleGroup::initialize(const NamedList& params, const NamedList& defaults,
973 	String& error)
974 {
975     if (!m_init)
976 	debugChain(&plugin);
977 
978     int level = params.getIntValue("debuglevel",m_init ? DebugEnabler::debugLevel() : plugin.debugLevel());
979     if (level >= 0) {
980 	debugEnabled(0 != level);
981 	debugLevel(level);
982     }
983 
984     m_ringback = params.getBoolValue("ringback");
985 
986     Lock2 lock(this,fxoRec());
987     bool ok = true;
988     if (!m_init) {
989 	m_init = true;
990 	if (!fxoRec())
991 	    ok = create(params,defaults,error);
992 	else
993 	    ok = createRecorder(params,defaults,error);
994 	if (!ok)
995 	    return false;
996 	m_thread = new AnalogWorkerThread(this);
997 	if (!m_thread->startup()) {
998 	    error = "Failed to start worker thread";
999 	    return false;
1000 	}
1001     }
1002 
1003     // (Re)load analog lines
1004     bool all = params.getBoolValue("useallcircuits",true);
1005 
1006     unsigned int n = circuits().length();
1007     for (unsigned int i = 0; i < n; i++) {
1008 	SignallingCircuit* cic = static_cast<SignallingCircuit*>(circuits()[i]);
1009 	if (!cic)
1010 	    continue;
1011 
1012 	// Setup line parameter list
1013 	NamedList dummy("");
1014 	String sectName = s_lineSectPrefix + toString() + "/" + String(cic->code());
1015 	NamedList* lineParams = s_cfg.getSection(sectName);
1016 	if (!lineParams)
1017 	    lineParams = &dummy;
1018 	bool remove = !lineParams->getBoolValue("enable",true);
1019 
1020 	ModuleLine* line = static_cast<ModuleLine*>(findLine(cic->code()));
1021 
1022 	// Remove existing line if required
1023 	if (remove) {
1024 	    if (line) {
1025 		XDebug(this,DebugAll,"Removing line=%s [%p]",line->address(),this);
1026 		plugin.lineUnavailable(line);
1027 		TelEngine::destruct(line);
1028 	    }
1029 	    continue;
1030 	}
1031 
1032 	// Reload line if already created. Notify plugin if service state changed
1033 	completeLineParams(*lineParams,params,defaults);
1034 	if (line) {
1035 	    bool inService = (line->state() != AnalogLine::OutOfService);
1036 	    reloadLine(line,*lineParams);
1037 	    if (inService != (line->state() != AnalogLine::OutOfService))
1038 		plugin.lineUnavailable(line);
1039 	    continue;
1040 	}
1041 
1042 	// Don't create the line if useallcircuits is false and no section in config
1043 	if (!all && lineParams == &dummy)
1044 	    continue;
1045 
1046 	DDebug(this,DebugAll,"Creating line for cic=%u [%p]",cic->code(),this);
1047 	// Create a new line (create its peer if this is a monitor)
1048 	line = new ModuleLine(this,cic->code(),*lineParams,params);
1049 	while (fxoRec() && line->type() != AnalogLine::Unknown) {
1050 	    SignallingCircuit* fxoCic = static_cast<SignallingCircuit*>(fxoRec()->circuits()[i]);
1051 	    if (!fxoCic) {
1052 		Debug(this,DebugNote,"FXO circuit is missing for %s/%u [%p]",
1053 		    debugName(),cic->code(),this);
1054 		TelEngine::destruct(line);
1055 		break;
1056 	    }
1057 
1058 	    NamedList dummyFxo("");
1059 	    String fxoName = s_lineSectPrefix + fxoRec()->toString() + "/" + String(fxoCic->code());
1060 	    NamedList* fxoParams = s_cfg.getSection(fxoName);
1061 	    if (!fxoParams)
1062 		fxoParams = &dummyFxo;
1063 
1064 	    completeLineParams(*fxoParams,params,defaults);
1065 
1066 	    ModuleLine* fxoLine = new ModuleLine(fxoRec(),fxoCic->code(),*fxoParams,params);
1067 	    if (fxoLine->type() == AnalogLine::Unknown) {
1068 		TelEngine::destruct(fxoLine);
1069 		TelEngine::destruct(line);
1070 		break;
1071 	    }
1072 	    fxoRec()->appendLine(fxoLine);
1073 	    line->setPeer(fxoLine);
1074 	    break;
1075 	}
1076 
1077 	// Append line to group: constructor may fail
1078 	if (line && line->type() != AnalogLine::Unknown) {
1079 	    appendLine(line);
1080 	    // Disconnect the line if not expecting call setup
1081 	    if (line->callSetup() != AnalogLine::Before)
1082 		line->disconnect(true);
1083 	}
1084 	else {
1085 	    Debug(this,DebugNote,"Failed to create line %s/%u [%p]",
1086 		debugName(),cic->code(),this);
1087 	    TelEngine::destruct(line);
1088 	}
1089     }
1090 
1091     if (!fxoRec())
1092 	ok = reload(params,defaults,error);
1093     else
1094 	ok = reloadRecorder(params,defaults,error);
1095     return ok;
1096 }
1097 
1098 // Copy some data to a channel
copyData(AnalogChannel * chan)1099 void ModuleGroup::copyData(AnalogChannel* chan)
1100 {
1101     if (!chan || fxoRec())
1102 	return;
1103     chan->m_callEndedTarget = m_callEndedTarget;
1104     chan->m_oooTarget = m_oooTarget;
1105     if (!chan->m_lang)
1106 	chan->m_lang = m_lang;
1107     chan->m_callEndedTimer.interval(m_callEndedPlayTime);
1108 }
1109 
1110 // Append/remove endpoints from list
setEndpoint(CallEndpoint * ep,bool add)1111 void ModuleGroup::setEndpoint(CallEndpoint* ep, bool add)
1112 {
1113     if (!ep)
1114 	return;
1115     Lock lock(this);
1116     if (add)
1117 	m_endpoints.append(ep);
1118     else
1119 	m_endpoints.remove(ep,false);
1120 }
1121 
1122 // Find a recorder by its line
findRecorder(ModuleLine * line)1123 AnalogCallRec* ModuleGroup::findRecorder(ModuleLine* line)
1124 {
1125     if (!fxoRec())
1126 	return 0;
1127     Lock lock(this);
1128     for (ObjList* o = m_endpoints.skipNull(); o; o = o->skipNull()) {
1129 	AnalogCallRec* rec = static_cast<AnalogCallRec*>(o->get());
1130 	if (rec->line() == line)
1131 	    return rec;
1132     }
1133     return 0;
1134 }
1135 
1136 // Fill a string with group status parameters
statusParams(String & str)1137 void ModuleGroup::statusParams(String& str)
1138 {
1139     str.append("module=",";") << plugin.name();
1140     str << ",name=" << toString();
1141     str << ",type=" << lookup(!fxo()?type():AnalogLine::Monitor,AnalogLine::typeNames());
1142     str << ",lines=" << lines().count();
1143     str << "," << s_lineStatusDetail;
1144     for (ObjList* o = lines().skipNull(); o; o = o->skipNext())
1145 	(static_cast<ModuleLine*>(o->get()))->statusDetail(str);
1146 }
1147 
1148 // Fill a string with group status detail parameters
statusDetail(String & str)1149 void ModuleGroup::statusDetail(String& str)
1150 {
1151     // format=Type|Lines
1152     Lock lock(this);
1153     str.append(toString(),";") << "=";
1154     str << lookup(!fxo()?type():AnalogLine::Monitor,AnalogLine::typeNames());
1155     str << "|" << lines().count();
1156 }
1157 
1158 // Disconnect all group's endpoints
clearEndpoints(const char * reason)1159 void ModuleGroup::clearEndpoints(const char* reason)
1160 {
1161     if (!reason)
1162 	reason = "shutdown";
1163 
1164     DDebug(this,DebugAll,"Clearing endpoints with reason=%s [%p]",reason,this);
1165     bool chans = !fxoRec();
1166     lock();
1167     ListIterator iter(m_endpoints);
1168     for (;;) {
1169 	RefPointer<CallEndpoint> c = static_cast<CallEndpoint*>(iter.get());
1170 	unlock();
1171 	if (!c)
1172 	    break;
1173 	if (chans)
1174 	    plugin.terminateChan(static_cast<AnalogChannel*>((CallEndpoint*)c),reason);
1175 	else
1176 	    plugin.terminateChan(static_cast<AnalogCallRec*>((CallEndpoint*)c),reason);
1177 	c = 0;
1178 	lock();
1179     }
1180 }
1181 
1182 // Check timers for recorders owned by this group
checkTimers(Time & when)1183 void ModuleGroup::checkTimers(Time& when)
1184 {
1185     bool chans = !fxoRec();
1186     lock();
1187     ListIterator iter(m_endpoints);
1188     for (;;) {
1189 	RefPointer<CallEndpoint> c = static_cast<CallEndpoint*>(iter.get());
1190 	unlock();
1191 	if (!c)
1192 	    break;
1193 	if (chans) {
1194 	    AnalogChannel* ch = static_cast<AnalogChannel*>((CallEndpoint*)c);
1195 	    if (!ch->checkTimeouts(when))
1196 		plugin.terminateChan(ch,"timeout");
1197 	}
1198 	else {
1199 	    AnalogCallRec* ch = static_cast<AnalogCallRec*>((CallEndpoint*)c);
1200 	    if (!ch->checkTimeouts(when))
1201 		plugin.terminateChan(ch,"timeout");
1202 	}
1203 	c = 0;
1204 	lock();
1205     }
1206 }
1207 
1208 // Create FXS/FXO group data: called by initialize() on first init
create(const NamedList & params,const NamedList & defaults,String & error)1209 bool ModuleGroup::create(const NamedList& params, const NamedList& defaults,
1210 	String& error)
1211 {
1212     String device = params.getValue("spans");
1213     ObjList* voice = device.split(',',false);
1214     if (voice && voice->count())
1215 	buildGroup(this,*voice,error);
1216     else
1217 	error << "Missing or invalid spans=" << device;
1218     TelEngine::destruct(voice);
1219     if (error)
1220 	return false;
1221     return true;
1222 }
1223 
1224 // Reload FXS/FXO data: called by initialize() (not called on first init if create failed)
reload(const NamedList & params,const NamedList & defaults,String & error)1225 bool ModuleGroup::reload(const NamedList& params, const NamedList& defaults,
1226 	String& error)
1227 {
1228     // (Re)load tone targets
1229     if (type() == AnalogLine::FXS) {
1230 	int tmp = params.getIntValue("call-ended-playtime",
1231 	    defaults.getIntValue("call-ended-playtime",5));
1232 	if (tmp < 0)
1233 	    tmp = 5;
1234 	m_callEndedPlayTime = 1000 * (unsigned int)tmp;
1235 	m_callEndedTarget = params.getValue("call-ended-target",
1236 	    defaults.getValue("call-ended-target"));
1237 	if (!m_callEndedTarget)
1238 	    m_callEndedTarget = "tone/busy";
1239 	m_oooTarget = params.getValue("outoforder-target",
1240 	    defaults.getValue("outoforder-target"));
1241 	if (!m_oooTarget)
1242 	    m_oooTarget = "tone/outoforder";
1243 	m_lang = params.getValue("lang",defaults.getValue("lang"));
1244 	XDebug(this,DebugAll,"Targets: call-ended='%s' outoforder='%s' [%p]",
1245 	    m_callEndedTarget.c_str(),m_oooTarget.c_str(),this);
1246     }
1247     return true;
1248 }
1249 
1250 // Create recorder group data: called by initialize() on first init
createRecorder(const NamedList & params,const NamedList & defaults,String & error)1251 bool ModuleGroup::createRecorder(const NamedList& params, const NamedList& defaults,
1252 	String& error)
1253 {
1254     for (unsigned int i = 0; i < 2; i++) {
1255 	String device = params.getValue(callertype(0 != i));
1256 	ObjList* voice = device.split(',',false);
1257 	if (voice && voice->count())
1258 	    if (i)
1259 		buildGroup(this,*voice,error);
1260 	    else
1261 		buildGroup(fxoRec(),*voice,error);
1262 	else
1263 	    error << "Missing or invalid " << callertype(0 != i) << " spans=" << device;
1264 	TelEngine::destruct(voice);
1265 	if (error)
1266 	    return false;
1267     }
1268     return true;
1269 }
1270 
1271 // Reload recorder data: called by initialize() (not called on first init if create failed)
reloadRecorder(const NamedList & params,const NamedList & defaults,String & error)1272 bool ModuleGroup::reloadRecorder(const NamedList& params, const NamedList& defaults,
1273 	String& error)
1274 {
1275     return true;
1276 }
1277 
1278 // Reload existing line's parameters
reloadLine(ModuleLine * line,const NamedList & params)1279 void ModuleGroup::reloadLine(ModuleLine* line, const NamedList& params)
1280 {
1281     if (!line)
1282 	return;
1283     bool inService = !params.getBoolValue("out-of-service",false);
1284     if (inService == (line->state() != AnalogLine::OutOfService))
1285 	return;
1286     Lock lock(line);
1287     Debug(this,DebugAll,"Reloading line %s in-service=%s [%p]",line->address(),String::boolText(inService),this);
1288     line->ref();
1289     line->enable(inService,true);
1290     line->deref();
1291 }
1292 
1293 // Build the circuit list for a given group
buildGroup(ModuleGroup * group,ObjList & spanList,String & error)1294 void ModuleGroup::buildGroup(ModuleGroup* group, ObjList& spanList, String& error)
1295 {
1296     if (!group)
1297 	return;
1298     unsigned int start = 0;
1299     for (ObjList* o = spanList.skipNull(); o; o = o->skipNext()) {
1300 	String* s = static_cast<String*>(o->get());
1301 	if (s->null())
1302 	    continue;
1303 	SignallingCircuitSpan* span = buildSpan(*s,start);
1304 	if (!span) {
1305 	    error << "Failed to build span '" << *s << "'";
1306 	    break;
1307 	}
1308 	start += span->increment();
1309     }
1310 }
1311 
1312 
1313 /**
1314  * AnalogChannel
1315  */
1316 // Incoming: msg=0. Outgoing: msg is the call execute message
AnalogChannel(ModuleLine * line,Message * msg,RecordTrigger recorder)1317 AnalogChannel::AnalogChannel(ModuleLine* line, Message* msg, RecordTrigger recorder)
1318     : Channel(&plugin,0,(msg != 0)),
1319     m_line(line),
1320     m_hungup(false),
1321     m_ringback(false),
1322     m_routeOnSecondRing(false),
1323     m_recording(recorder),
1324     m_callEndedTimer(0),
1325     m_ringTimer(RING_PATTERN_TIME),
1326     m_alarmTimer(line ? line->alarmTimeout() : 0),
1327     m_dialTimer(0),
1328     m_polarityCount(0),
1329     m_polarity(false),
1330     m_privacy(false),
1331     m_callsetup(AnalogLine::NoCallSetup)
1332 {
1333     if (msg)
1334 	setChanParams(*msg);
1335     m_line->userdata(this);
1336     if (m_line->moduleGroup()) {
1337 	m_line->moduleGroup()->setEndpoint(this,true);
1338 	m_ringback = m_line->moduleGroup()->ringback();
1339     }
1340 
1341     // Set caller/called from line
1342     if (isOutgoing()) {
1343 	m_lang = msg->getValue("lang");
1344 	m_line->setCall(msg->getValue("caller"),msg->getValue("callername"),msg->getValue("called"));
1345     }
1346     else
1347 	if ((m_line->type() == AnalogLine::FXS) || (recorder == FXO))
1348 	    m_line->setCall("","","off-hook");
1349 	else
1350 	    m_line->setCall("","","ringing");
1351 
1352     const char* mode = 0;
1353     switch (recorder) {
1354 	case FXO:
1355 	    mode = "Record FXO";
1356 	    break;
1357 	case FXS:
1358 	    mode = "Record FXS";
1359 	    break;
1360 	default:
1361 	    mode = isOutgoing() ? "Outgoing" : "Incoming";
1362     }
1363     Debug(this,DebugCall,"%s call on line %s caller=%s called=%s [%p]",
1364 	mode,
1365 	m_line->address(),
1366 	m_line->caller().c_str(),m_line->called().c_str(),this);
1367 
1368     m_line->connect(false);
1369     m_line->acceptPulseDigit(isIncoming());
1370 
1371     // Incoming on FXO:
1372     // Caller id after first ring: delay router until the second ring and
1373     //  set/remove call setup detector
1374     if (isIncoming() && m_line->type() == AnalogLine::FXO && recorder != FXO) {
1375 	m_routeOnSecondRing = (m_line->callSetup() == AnalogLine::After);
1376 	if (m_routeOnSecondRing)
1377 	    m_line->setCallSetupDetector();
1378 	else
1379 	    m_line->removeCallSetupDetector();
1380     }
1381 
1382     m_address = m_line->address();
1383     if (m_line->type() == AnalogLine::FXS && m_line->moduleGroup())
1384 	m_line->moduleGroup()->copyData(this);
1385 
1386     setMaxcall(msg);
1387     if (msg)
1388 	setMaxPDD(*msg);
1389     // Startup
1390     Message* m = message("chan.startup");
1391     if (msg)
1392 	m->copyParams(*msg,"caller,callername,called,billid,callto,username");
1393     m_line->copyCall(*m);
1394     if (isOutgoing())
1395 	m_targetid = msg->getValue("id");
1396     Engine::enqueue(m);
1397 
1398     // Init call
1399     setAudio(isIncoming());
1400     if (isOutgoing()) {
1401 	// Check for parameters override
1402 	m_dialTimer.interval(msg->getIntValue("delaydial",0));
1403 	// FXO: send start line event
1404 	// FXS: start ring and send call setup (caller id)
1405 	// Return if failed to send events
1406 	switch (line->type()) {
1407 	    case AnalogLine::FXO:
1408 		m_line->sendEvent(SignallingCircuitEvent::StartLine,AnalogLine::Dialing);
1409 		break;
1410 	    case AnalogLine::FXS:
1411 		m_callsetup = m_line->callSetup();
1412 		// Check call setup override
1413 		{
1414 		    NamedString* ns = msg->getParam("callsetup");
1415 		    if (ns)
1416 			m_callsetup = lookup(*ns,AnalogLine::csNames(),AnalogLine::NoCallSetup);
1417 		}
1418 		m_privacy = getPrivacy(*msg);
1419 		if (m_callsetup == AnalogLine::Before)
1420 		    m_line->sendCallSetup(m_privacy);
1421 		{
1422 		    NamedList* params = 0;
1423 		    NamedList callerId("");
1424 		    if (m_callsetup != AnalogLine::NoCallSetup) {
1425 			params = &callerId;
1426 			m_line->copyCall(callerId,m_privacy);
1427 		    }
1428 		    m_line->sendEvent(SignallingCircuitEvent::RingBegin,AnalogLine::Dialing,params);
1429 		}
1430 		if (m_callsetup == AnalogLine::After)
1431 		    m_dialTimer.interval(500);
1432 		break;
1433 	    default: ;
1434 	}
1435 	if (line->state() == AnalogLine::Idle) {
1436 	    setReason("failure");
1437 	    msg->setParam("error",m_reason);
1438 	    return;
1439 	}
1440     }
1441     else {
1442 	m_line->changeState(AnalogLine::Dialing);
1443 
1444 	// FXO: start ring timer (check if the caller hangs up before answer)
1445 	// FXS: do nothing
1446 	switch (line->type()) {
1447 	    case AnalogLine::FXO:
1448 		if (recorder == FXO) {
1449 		    m_line->noRingTimer().stop();
1450 		    break;
1451 		}
1452 		m_line->noRingTimer().interval(m_line->noRingTimeout());
1453 		DDebug(this,DebugAll,"Starting ring timer for " FMT64 "ms [%p]",
1454 		    m_line->noRingTimer().interval(),this);
1455 		m_line->noRingTimer().start();
1456 		if (recorder == FXS) {
1457 		    // The FXS recorder will route only on off-hook
1458 		    m_routeOnSecondRing = false;
1459 		    return;
1460 		}
1461 		break;
1462 	    case AnalogLine::FXS:
1463 		break;
1464 	    default: ;
1465 	}
1466 	if (!m_routeOnSecondRing)
1467 	    startRouter(true);
1468 	else
1469 	    DDebug(this,DebugInfo,"Delaying route until next ring [%p]",this);
1470     }
1471 }
1472 
~AnalogChannel()1473 AnalogChannel::~AnalogChannel()
1474 {
1475     XDebug(this,DebugCall,"AnalogChannel::~AnalogChannel() [%p]",this);
1476 }
1477 
1478 // Start outgoing media and echo train if earlymedia or got peer with data source
msgProgress(Message & msg)1479 bool AnalogChannel::msgProgress(Message& msg)
1480 {
1481     Lock lock(m_mutex);
1482     if (isAnswered())
1483 	return true;
1484 
1485     Channel::msgProgress(msg);
1486     setStatus();
1487     if (m_line && m_line->type() != AnalogLine::FXS)
1488 	m_line->acceptPulseDigit(false);
1489     if (msg.getBoolValue("earlymedia",getPeer() && getPeer()->getSource())) {
1490 	setAudio(false);
1491 	if (m_line)
1492 	    m_line->setCircuitParam("echotrain",msg.getValue("echotrain"));
1493     }
1494     return true;
1495 }
1496 
1497 // Start outgoing media and echo train if earlymedia or got peer with data source
msgRinging(Message & msg)1498 bool AnalogChannel::msgRinging(Message& msg)
1499 {
1500     Lock lock(m_mutex);
1501     if (isAnswered())
1502 	return true;
1503 
1504     Channel::msgRinging(msg);
1505     setStatus();
1506     if (m_line) {
1507 	if (m_line->type() != AnalogLine::FXS)
1508 	    m_line->acceptPulseDigit(false);
1509 	m_line->changeState(AnalogLine::Ringing);
1510     }
1511     bool media = msg.getBoolValue("earlymedia",getPeer() && getPeer()->getSource());
1512     if (media) {
1513 	setAudio(false);
1514 	if (m_line)
1515 	    m_line->setCircuitParam("echotrain",msg.getValue("echotrain"));
1516     }
1517     else if (m_ringback && m_line) {
1518 	// Provide ringback from circuit features if supported
1519 	NamedList params("ringback");
1520 	params.addParam("tone","ringback");
1521 	media = m_line->sendEvent(SignallingCircuitEvent::GenericTone,&params);
1522     }
1523     if (media)
1524 	m_ringback = false;
1525     return true;
1526 }
1527 
1528 // Terminate ringing on line. Start echo train. Open audio streams
msgAnswered(Message & msg)1529 bool AnalogChannel::msgAnswered(Message& msg)
1530 {
1531     Lock lock(m_mutex);
1532     if (m_line) {
1533 	m_line->noRingTimer().stop();
1534 	m_line->removeCallSetupDetector();
1535 	m_line->sendEvent(SignallingCircuitEvent::RingEnd);
1536 	if (m_line->type() == AnalogLine::FXS)
1537 	    polarityControl(true);
1538 	else {
1539 	    m_line->acceptPulseDigit(false);
1540 	    m_line->sendEvent(SignallingCircuitEvent::OffHook);
1541 	}
1542 	m_line->changeState(AnalogLine::Answered);
1543 	m_line->setCircuitParam("echotrain",msg.getValue("echotrain"));
1544     }
1545     setAudio(true);
1546     setAudio(false);
1547     Channel::msgAnswered(msg);
1548     setStatus();
1549     return true;
1550 }
1551 
1552 // Send tones or flash
msgTone(Message & msg,const char * tone)1553 bool AnalogChannel::msgTone(Message& msg, const char* tone)
1554 {
1555     Lock lock(m_mutex);
1556     if (!(tone && *tone && m_line))
1557 	return false;
1558     if (*tone != 'F') {
1559 	if (m_dialTimer.started()) {
1560 	    Debug(this,DebugAll,"msgTone(%s). Adding to called number [%p]",tone,this);
1561 	    m_line->called().append(tone);
1562 	    return true;
1563 	}
1564 	return sendTones(tone,false);
1565     }
1566     // Flash event: don't send if not FXO
1567     if (m_line->type() != AnalogLine::FXO) {
1568 	Debug(this,DebugInfo,"Can't send line flash on non-FXO line (tones='%s') [%p]",tone,this);
1569 	return false;
1570     }
1571     Debug(this,DebugAll,"Sending line flash (tones='%s') [%p]",tone,this);
1572     return m_line->sendEvent(SignallingCircuitEvent::Flash);
1573 }
1574 
1575 // Hangup
msgDrop(Message & msg,const char * reason)1576 bool AnalogChannel::msgDrop(Message& msg, const char* reason)
1577 {
1578     Lock lock(m_mutex);
1579     setReason(reason ? reason : "dropped");
1580     if (Engine::exiting() || !m_line || m_line->type() != AnalogLine::FXS)
1581 	Channel::msgDrop(msg,m_reason);
1582     hangup(true);
1583     return true;
1584 }
1585 
1586 // Update echo canceller and/or start echo training
msgUpdate(Message & msg)1587 bool AnalogChannel::msgUpdate(Message& msg)
1588 {
1589     String tmp = msg.getValue("echocancel");
1590     Lock lock(m_mutex);
1591     if (!(tmp.isBoolean() && m_line))
1592 	return false;
1593     bool ok = m_line->setCircuitParam("echocancel",tmp);
1594     if (tmp.toBoolean())
1595 	m_line->setCircuitParam("echotrain",msg.getValue("echotrain"));
1596     return ok;
1597 }
1598 
1599 // Call routed: set tone detector
callRouted(Message & msg)1600 bool AnalogChannel::callRouted(Message& msg)
1601 {
1602     Channel::callRouted(msg);
1603     setStatus();
1604     Lock lock(m_mutex);
1605     // Update tones language
1606     m_lang = msg.getValue("lang",m_lang);
1607     // Check if the circuit supports tone detection
1608     if (!m_line->circuit())
1609 	return true;
1610     String value;
1611     if (m_line->circuit()->getParam("tonedetect",value) && value.toBoolean())
1612 	return true;
1613     // Set tone detector
1614     setAudio(false);
1615     if (toneDetect())
1616 	DDebug(this,DebugAll,"Loaded tone detector [%p]",this);
1617     else {
1618 	setConsumer();
1619 	DDebug(this,DebugNote,"Failed to set tone detector [%p]",this);
1620     }
1621     return true;
1622 }
1623 
1624 // Call accepted: set line and open audio
callAccept(Message & msg)1625 void AnalogChannel::callAccept(Message& msg)
1626 {
1627     Lock lock(m_mutex);
1628     // Update tones language
1629     m_lang = msg.getValue("lang",m_lang);
1630     if (isAnswered())
1631 	return;
1632     if (m_line) {
1633 	if (m_line->type() != AnalogLine::FXS)
1634 	    m_line->acceptPulseDigit(false);
1635 	m_line->changeState(AnalogLine::DialComplete);
1636     }
1637     m_ringback = msg.getBoolValue("ringback",m_ringback);
1638     setAudio(false);
1639     setAudio(true);
1640     Channel::callAccept(msg);
1641 }
1642 
1643 // Call rejected: hangup
callRejected(const char * error,const char * reason,const Message * msg)1644 void AnalogChannel::callRejected(const char* error, const char* reason,
1645 	const Message* msg)
1646 {
1647     if (msg) {
1648 	Lock lock(m_mutex);
1649 	m_lang = msg->getValue("lang",m_lang);
1650     }
1651     setReason(error ? error : reason);
1652     Channel::callRejected(error,m_reason,msg);
1653     setStatus();
1654     hangup(true);
1655 }
1656 
disconnected(bool final,const char * reason)1657 void AnalogChannel::disconnected(bool final, const char* reason)
1658 {
1659     Lock lock(m_mutex);
1660     Channel::disconnected(final,m_reason);
1661     hangup(!final,"disconnected",reason);
1662 }
1663 
1664 // Disconnect the channel
disconnect(const char * reason)1665 bool AnalogChannel::disconnect(const char* reason)
1666 {
1667     Lock lock(m_mutex);
1668     if (!m_hungup) {
1669 	setReason(reason);
1670 	setStatus("disconnecting");
1671     }
1672     return Channel::disconnect(m_reason,parameters());
1673 }
1674 
1675 // Hangup call
1676 // Keep call alive to play announcements on FXS line not set on hook by the remote FXO
hangup(bool local,const char * status,const char * reason)1677 void AnalogChannel::hangup(bool local, const char* status, const char* reason)
1678 {
1679     // Sanity: reset dial timer and call setup flag if FXS
1680     m_dialTimer.stop();
1681     m_callsetup = AnalogLine::NoCallSetup;
1682 
1683     Lock lock(m_mutex);
1684 
1685     if (m_hungup)
1686 	return;
1687     m_hungup = true;
1688     setReason(reason ? reason : (Engine::exiting() ? "shutdown" : "normal"));
1689     if (status)
1690 	setStatus(status);
1691     setSource();
1692     setConsumer();
1693 
1694     Message* m = message("chan.hangup",true);
1695     putStatus(*m);
1696     m->setParam("reason",m_reason);
1697     Engine::enqueue(m);
1698 
1699     setStatus("hangup");
1700     if (m_line && m_line->state() != AnalogLine::Idle)
1701 	m_line->sendEvent(SignallingCircuitEvent::RingEnd);
1702     polarityControl(false);
1703 
1704     // Check some conditions to keep the channel
1705     if (!m_line || m_line->type() != AnalogLine::FXS ||
1706 	!local || Engine::exiting() ||
1707 	(isOutgoing() && m_line->state() < AnalogLine::Answered) ||
1708 	(isIncoming() && m_line->state() == AnalogLine::Idle))
1709 	return;
1710 
1711     Debug(this,DebugAll,"Call ended. Keep channel alive [%p]",this);
1712     if (m_callEndedTimer.interval()) {
1713 	m_callEndedTimer.start();
1714 	m_line->changeState(AnalogLine::CallEnded);
1715 	if (!setAnnouncement("call-ended",m_callEndedTarget))
1716 	    ref();
1717     }
1718     else {
1719 	m_line->changeState(AnalogLine::OutOfOrder);
1720 	if (!setAnnouncement("out-of-order",m_oooTarget))
1721 	    ref();
1722     }
1723 }
1724 
1725 // Process incoming or outgoing digits
evDigits(const char * text,bool tone)1726 void AnalogChannel::evDigits(const char* text, bool tone)
1727 {
1728     if (!(text && *text))
1729 	return;
1730     Debug(this,DebugAll,"Got %s digits=%s [%p]",tone?"tone":"pulse",text,this);
1731     Message* m = message("chan.dtmf",false,true);
1732     m->addParam("text",text);
1733     if (!tone)
1734 	m->addParam("pulse",String::boolText(true));
1735     m->addParam("detected","analog");
1736     dtmfEnqueue(m);
1737 }
1738 
1739 // Line got off hook. Terminate ringing
1740 // Outgoing: answer it (call outCallAnswered())
1741 // Incoming: start echo train
evOffHook()1742 void AnalogChannel::evOffHook()
1743 {
1744     Lock lock(m_mutex);
1745     if (isOutgoing()) {
1746 	outCallAnswered();
1747 	if (m_line)
1748 	    m_line->sendEvent(SignallingCircuitEvent::RingEnd,AnalogLine::Answered);
1749     }
1750     else if (m_line) {
1751 	m_line->sendEvent(SignallingCircuitEvent::RingEnd,m_line->state());
1752 	m_line->setCircuitParam("echotrain");
1753 	if (m_recording == FXS)
1754 	    startRouter(true);
1755     }
1756 }
1757 
1758 // Line ring on/off notification. Ring off is ignored
1759 // Outgoing: enqueue call.ringing
1760 // Incoming: FXO: Route the call if delayed. Remove line's detector and start ring timer
evRing(bool on)1761 void AnalogChannel::evRing(bool on)
1762 {
1763     Lock lock(m_mutex);
1764 
1765     // Re(start) ring timer. Ignore ring events if timer was already started
1766     if (on) {
1767 	bool ignore = m_ringTimer.started();
1768 	m_ringTimer.start();
1769 	if (ignore)
1770 	    return;
1771     }
1772 
1773     // Check call setup
1774     if (m_callsetup == AnalogLine::After) {
1775 	if (on)
1776 	    m_dialTimer.stop();
1777 	else
1778 	    m_dialTimer.start();
1779     }
1780 
1781     // Done if ringer is off
1782     if (!on)
1783 	return;
1784 
1785     // Outgoing: remote party is ringing
1786     if (isOutgoing()) {
1787 	Engine::enqueue(message("call.ringing",false,true));
1788 	if (m_line)
1789 	    m_line->changeState(AnalogLine::Ringing);
1790 	return;
1791     }
1792     // Incoming: start ringing (restart FXO timer to check remote hangup)
1793     // Start router if delayed
1794     if (!m_line)
1795 	return;
1796     if (m_line->type() == AnalogLine::FXO) {
1797 	if (m_routeOnSecondRing) {
1798 	    m_routeOnSecondRing = false;
1799 	    startRouter(false);
1800 	}
1801 	m_line->removeCallSetupDetector();
1802 	if (m_line->noRingTimer().interval()) {
1803 	    DDebug(this,DebugAll,"Restarting ring timer for " FMT64 "ms [%p]",
1804 		m_line->noRingTimer().interval(),this);
1805 	    m_line->noRingTimer().start();
1806 	}
1807     }
1808 }
1809 
1810 // Line started (initialized) notification
1811 // Answer outgoing FXO calls on lines not expecting polarity changes to answer
1812 // Send called number if any
evLineStarted()1813 void AnalogChannel::evLineStarted()
1814 {
1815     Lock lock(m_mutex);
1816     if (!m_line)
1817 	return;
1818     // Send number: delay it if interval is not 0
1819     bool stopDial = true;
1820     if (m_line->called()) {
1821 	if (m_line->delayDial() || m_dialTimer.interval()) {
1822 	    if (!m_dialTimer.started()) {
1823 		if (!m_dialTimer.interval())
1824 		    m_dialTimer.interval(m_line->delayDial());
1825 		DDebug(this,DebugAll,"Delaying dial for " FMT64 "ms [%p]",
1826 		    m_dialTimer.interval(),this);
1827 		m_dialTimer.start();
1828 	    }
1829 	    stopDial = false;
1830 	}
1831 	else
1832 	    sendTones(m_line->called());
1833     }
1834 
1835     // Answer now outgoing FXO calls on lines not expecting polarity changes to answer
1836     if (isOutgoing() && m_line && m_line->type() == AnalogLine::FXO &&
1837 	!m_line->answerOnPolarity())
1838 	outCallAnswered(stopDial);
1839 }
1840 
1841 // Dial complete notification. Enqueue call.progress
1842 // Answer outgoing FXO calls on lines not expecting polarity changes to answer
evDialComplete()1843 void AnalogChannel::evDialComplete()
1844 {
1845     DDebug(this,DebugAll,"Dial completed [%p]",this);
1846     Lock lock(m_mutex);
1847     if (m_line)
1848 	m_line->changeState(AnalogLine::DialComplete);
1849     Engine::enqueue(message("call.progress",true,true));
1850     // Answer now outgoing FXO calls on lines not expecting polarity changes to answer
1851     if (isOutgoing() && m_line && m_line->type() == AnalogLine::FXO &&
1852 	!m_line->answerOnPolarity())
1853 	outCallAnswered();
1854 }
1855 
1856 // Line polarity change notification
1857 // Terminate call if:
1858 //   - no line or line is not FXO,
1859 //   - Outgoing: don't answer on polarity or already answered and should hangup on polarity change
1860 //   - Incoming: don't answer on polarity or polarity already changed and should hangup on polarity change
evPolarity()1861 void AnalogChannel::evPolarity()
1862 {
1863     Lock lock(m_mutex);
1864     m_polarityCount++;
1865     DDebug(this,DebugAll,"Line polarity changed %u time(s) [%p]",m_polarityCount,this);
1866     bool terminate = (!m_line || m_line->type() != AnalogLine::FXO);
1867     if (!terminate) {
1868 	if (isOutgoing())
1869 	    if (!m_line->answerOnPolarity() || isAnswered())
1870 		terminate = m_line->hangupOnPolarity();
1871 	    else
1872 		outCallAnswered();
1873 	else if (!m_line->answerOnPolarity() || m_polarityCount > 1)
1874 	    terminate = m_line->hangupOnPolarity();
1875     }
1876 
1877     if (terminate) {
1878 	DDebug(this,DebugAll,"Terminating on polarity change [%p]",this);
1879 	hangup(false);
1880 	plugin.terminateChan(this);
1881     }
1882 }
1883 
1884 // Line ok: stop alarm timer
1885 // Terminate channel if not answered; otherwise: start timer if not already started
evAlarm(bool alarm,const char * alarms)1886 void AnalogChannel::evAlarm(bool alarm, const char* alarms)
1887 {
1888     Lock lock(m_mutex);
1889     if (!alarm) {
1890 	Debug(this,DebugInfo,"No more alarms on line [%p]",this);
1891 	if (m_line)
1892 	    m_line->setCircuitParam("echotrain");
1893 	m_alarmTimer.stop();
1894 	return;
1895     }
1896     // Terminate now if not answered
1897     if (!isAnswered()) {
1898 	Debug(this,DebugNote,"Line is out of order alarms=%s. Terminating now [%p]",
1899 	    alarms,this);
1900 	hangup(false,0,"net-out-of-order");
1901 	plugin.terminateChan(this);
1902 	return;
1903     }
1904     // Wait if answered
1905     if (!m_alarmTimer.started()) {
1906 	Debug(this,DebugNote,
1907 	    "Line is out of order alarms=%s. Starting timer for " FMT64U " ms [%p]",
1908 	    alarms,m_alarmTimer.interval(),this);
1909 	m_alarmTimer.start();
1910     }
1911 }
1912 
1913 // Check timers. Return false to terminate
checkTimeouts(const Time & when)1914 bool AnalogChannel::checkTimeouts(const Time& when)
1915 {
1916     Lock lock(m_mutex);
1917     // Stop ring timer: we didn't received a ring event in the last interval
1918     if (m_ringTimer.timeout(when.msecNow()))
1919 	m_ringTimer.stop();
1920     if (m_alarmTimer.timeout(when.msecNow())) {
1921 	m_alarmTimer.stop();
1922 	DDebug(this,DebugInfo,"Line was in alarm for " FMT64 " ms [%p]",
1923 	    m_alarmTimer.interval(),this);
1924 	setReason("net-out-of-order");
1925 	hangup(false);
1926 	return false;
1927     }
1928     if (m_callEndedTimer.timeout(when.msecNow())) {
1929 	m_callEndedTimer.stop();
1930 	m_line->changeState(AnalogLine::OutOfOrder);
1931 	disconnect();
1932 	if (!setAnnouncement("out-of-order",m_oooTarget))
1933 	    ref();
1934 	return true;
1935     }
1936     if (m_line->noRingTimer().timeout(when.msecNow())) {
1937 	DDebug(this,DebugInfo,"No ring for " FMT64 " ms. Terminating [%p]",
1938 	    m_line->noRingTimer().interval(),this);
1939 	m_line->noRingTimer().stop();
1940 	setReason("cancelled");
1941 	hangup(false);
1942 	return false;
1943     }
1944     if (m_dialTimer.timeout(when.msecNow())) {
1945 	m_dialTimer.stop();
1946 	m_callsetup = AnalogLine::NoCallSetup;
1947 	DDebug(this,DebugInfo,"Dial timer expired. %s [%p]",
1948 	    m_line?"Sending number/callsetup":"Line is missing",this);
1949 	if (!m_line)
1950 	    return true;
1951 	if (m_line->type() == AnalogLine::FXO)
1952 	    sendTones(m_line->called());
1953 	else if (m_line->type() == AnalogLine::FXS)
1954 	    m_line->sendCallSetup(m_privacy);
1955 	return true;
1956     }
1957     return true;
1958 }
1959 
1960 // Route incoming
startRouter(bool first)1961 void AnalogChannel::startRouter(bool first)
1962 {
1963     m_routeOnSecondRing = false;
1964     Message* m = message("call.preroute",false,true);
1965     if (m_line) {
1966 	m_line->copyCall(*m);
1967 	const char* caller = m->getValue("caller");
1968 	if (!(caller && *caller))
1969 	    m->setParam("caller",s_unk);
1970 	switch (m_line->type()) {
1971 	    case AnalogLine::FXO:
1972 		if (getSource())
1973 		    m->addParam("format",getSource()->getFormat());
1974 		break;
1975 	    case AnalogLine::FXS:
1976 		m->addParam("overlapped","true");
1977 		m->addParam("lang",m_lang,false);
1978 		break;
1979 	    default: ;
1980 	}
1981     }
1982     switch (m_recording) {
1983 	case FXO:
1984 	    m->addParam("callsource","fxo");
1985 	    break;
1986 	case FXS:
1987 	    m->addParam("callsource","fxs");
1988 	    break;
1989 	default: ;
1990     }
1991     DDebug(this,DebugInfo,"Starting router %scaller=%s callername=%s [%p]",
1992 	first?"":"(delayed) ",
1993 	m->getValue("caller"),m->getValue("callername"),this);
1994     Channel::startRouter(m);
1995 }
1996 
1997 // Set data source and consumer
setAudio(bool in)1998 bool AnalogChannel::setAudio(bool in)
1999 {
2000     if ((in && getSource()) || (!in && getConsumer()))
2001 	return true;
2002     if ((m_recording != None) && !in)
2003 	return true;
2004 
2005     SignallingCircuit* cic = m_line ? m_line->circuit() : 0;
2006     if (cic) {
2007 	if (in)
2008 	    setSource(static_cast<DataSource*>(cic->getObject(YATOM("DataSource"))));
2009 	else
2010 	    setConsumer(static_cast<DataConsumer*>(cic->getObject(YATOM("DataConsumer"))));
2011     }
2012 
2013     DataNode* res = in ? (DataNode*)getSource() : (DataNode*)getConsumer();
2014     if (res)
2015 	DDebug(this,DebugAll,"Data %s set to (%p): '%s' [%p]",
2016 	    in?"source":"consumer",res,res->getFormat().c_str(),this);
2017     else
2018 	Debug(this,DebugNote,"Failed to set data %s%s [%p]",
2019 	    in?"source":"consumer",cic?"":". Circuit is missing",this);
2020     return res != 0;
2021 }
2022 
2023 // Set call status
setStatus(const char * newStat)2024 bool AnalogChannel::setStatus(const char* newStat)
2025 {
2026     if (newStat)
2027 	status(newStat);
2028     if (debugAt(DebugCall)) {
2029 	String tmp;
2030 	getStatus(tmp);
2031 	if (m_reason)
2032 	    Debug(this,DebugCall,"status=%s reason=%s [%p]",
2033 		tmp.c_str(),m_reason.c_str(),this);
2034 	else
2035 	    Debug(this,DebugCall,"status=%s [%p]",tmp.c_str(),this);
2036     }
2037     return true;
2038 }
2039 
2040 // Set tones to the remote end of the line
setAnnouncement(const char * status,const char * callto)2041 bool AnalogChannel::setAnnouncement(const char* status, const char* callto)
2042 {
2043     setStatus(status);
2044     // Don't set announcements for FXO
2045     if (!m_line || m_line->type() == AnalogLine::FXO)
2046 	return false;
2047     Message* m = message("call.execute",false,true);
2048     m->addParam("callto",callto);
2049     m->addParam("lang",m_lang,false);
2050     bool ok = Engine::dispatch(*m);
2051     TelEngine::destruct(m);
2052     if (ok) {
2053 	setAudio(false);
2054 	Debug(this,DebugAll,"Announcement set to %s",callto);
2055     }
2056     else
2057 	Debug(this,DebugMild,"Set announcement=%s failed",callto);
2058     return ok;
2059 }
2060 
2061 // Outgoing call answered: set call state, start echo train, open data source/consumer
outCallAnswered(bool stopDial)2062 void AnalogChannel::outCallAnswered(bool stopDial)
2063 {
2064     // Sanity: reset dial timer and call setup flag if FXS
2065     if (m_line && m_line->type() == AnalogLine::FXS) {
2066 	m_dialTimer.stop();
2067 	m_callsetup = AnalogLine::NoCallSetup;
2068     }
2069 
2070     if (isAnswered())
2071 	return;
2072 
2073     if (stopDial)
2074 	m_dialTimer.stop();
2075     m_answered = true;
2076     m_ringback = false;
2077     setStatus("answered");
2078     if (m_line) {
2079 	m_line->changeState(AnalogLine::Answered);
2080 	polarityControl(true);
2081 	m_line->setCircuitParam("echotrain");
2082     }
2083     setAudio(true);
2084     setAudio(false);
2085     Engine::enqueue(message("call.answered",false,true));
2086 }
2087 
2088 // Hangup. Release memory
destroyed()2089 void AnalogChannel::destroyed()
2090 {
2091     detachLine();
2092     if (!m_hungup)
2093 	hangup(true);
2094     else {
2095 	setConsumer();
2096 	setSource();
2097     }
2098     setStatus("destroyed");
2099     Channel::destroyed();
2100 }
2101 
2102 // Detach the line from this channel
detachLine()2103 void AnalogChannel::detachLine()
2104 {
2105     Lock lock(m_mutex);
2106     if (!m_line)
2107 	return;
2108 
2109     if (m_line->moduleGroup())
2110 	m_line->moduleGroup()->setEndpoint(this,false);
2111     m_line->userdata(0);
2112     m_line->acceptPulseDigit(true);
2113     if (m_line->state() != AnalogLine::Idle) {
2114 	m_line->sendEvent(SignallingCircuitEvent::RingEnd);
2115 	m_line->sendEvent(SignallingCircuitEvent::OnHook);
2116 	m_line->changeState(AnalogLine::Idle);
2117     }
2118     m_line->removeCallSetupDetector();
2119     m_line->setCall();
2120     polarityControl(false);
2121 
2122     // Don't disconnect the line if waiting for call setup (need audio)
2123     if (m_line->type() == AnalogLine::FXO && m_line->callSetup() == AnalogLine::Before)
2124 	m_line->setCallSetupDetector();
2125     else
2126 	m_line->disconnect(false);
2127     TelEngine::destruct(m_line);
2128 }
2129 
2130 // Send tones (DTMF or dial number)
sendTones(const char * tone,bool dial)2131 bool AnalogChannel::sendTones(const char* tone, bool dial)
2132 {
2133     if (!(m_line && tone && *tone))
2134 	return false;
2135     DDebug(this,DebugInfo,"Sending %sband tones='%s' dial=%u [%p]",
2136 	m_line->outbandDtmf()?"out":"in",tone,dial,this);
2137     bool ok = false;
2138     if (m_line->outbandDtmf()) {
2139 	NamedList p("");
2140 	p.addParam("tone",tone);
2141 	p.addParam("dial",String::boolText(dial));
2142 	ok = m_line->sendEvent(SignallingCircuitEvent::Dtmf,&p);
2143     }
2144     if (!ok)
2145 	ok = dtmfInband(tone);
2146     return ok;
2147 }
2148 
2149 
2150 /**
2151  * AnalogCallRec
2152  */
2153 // Append to driver's list
AnalogCallRec(ModuleLine * line,bool fxsCaller,const char * id)2154 AnalogCallRec::AnalogCallRec(ModuleLine* line, bool fxsCaller, const char* id)
2155     : CallEndpoint(id),
2156     m_line(line),
2157     m_fxsCaller(fxsCaller),
2158     m_answered(false),
2159     m_hungup(false),
2160     m_polarityCount(0),
2161     m_startOnSecondRing(false),
2162     m_ringTimer(RING_PATTERN_TIME),
2163     m_status("startup")
2164 {
2165     debugName(CallEndpoint::id());
2166     debugChain(&plugin);
2167 
2168     ModuleLine* fxo = this->fxo();
2169     if (!(fxo && m_line->ref())) {
2170 	m_line = 0;
2171 	m_reason = "invalid-line";
2172 	return;
2173     }
2174 
2175     plugin.setRecorder(this,true);
2176     if (m_line->moduleGroup())
2177 	m_line->moduleGroup()->setEndpoint(this,true);
2178     m_line->userdata(this);
2179 
2180     m_line->connect(true);
2181     m_line->changeState(AnalogLine::Dialing,true);
2182     m_line->acceptPulseDigit(fxsCaller);
2183     fxo->acceptPulseDigit(!fxsCaller);
2184 
2185     // FXS caller:
2186     // Caller id after first ring: delay router until the second ring and
2187     //  set/remove call setup detector
2188     if (fxsCaller) {
2189 	m_startOnSecondRing = (fxo->callSetup() == AnalogLine::After);
2190 	if (m_startOnSecondRing)
2191 	    fxo->setCallSetupDetector();
2192 	else
2193 	    fxo->removeCallSetupDetector();
2194     }
2195 
2196     if (fxsCaller && m_line->getPeer())
2197 	m_address = m_line->getPeer()->address();
2198     else
2199 	m_address = m_line->address();
2200 
2201     // Set caller/called
2202     if (fxsCaller) {
2203 	if (m_startOnSecondRing && fxo->callSetup() == AnalogLine::Before)
2204 	    fxo->setCall(fxo->caller(),"",m_line->called());
2205 	else
2206 	    fxo->setCall(s_unk,"",m_line->called());
2207     }
2208     else
2209 	m_line->setCall(s_unk,"",fxo->called());
2210 
2211     Debug(this,DebugCall,"Created addr=%s initiator=%s [%p]",
2212 	m_address.c_str(),callertype(fxsCaller),this);
2213 
2214     Engine::enqueue(message("chan.startup"));
2215 
2216     if (fxsCaller) {
2217 	fxo->noRingTimer().interval(fxo->noRingTimeout());
2218 	DDebug(this,DebugAll,"Starting ring timer for " FMT64 "ms [%p]",
2219 	    fxo->noRingTimer().interval(),this);
2220 	fxo->noRingTimer().start();
2221     }
2222 }
2223 
2224 // Close recorder. Disconnect the line
hangup(const char * reason)2225 void AnalogCallRec::hangup(const char* reason)
2226 {
2227     Lock lock(m_mutex);
2228     if (m_hungup)
2229 	return;
2230 
2231     m_hungup = true;
2232     m_status = "hangup";
2233     if (!m_reason)
2234 	m_reason = reason;
2235     if (!m_reason)
2236 	m_reason = Engine::exiting() ? "shutdown" : "unknown";
2237 
2238     Debug(this,DebugCall,"Hangup reason='%s' [%p]",m_reason.c_str(),this);
2239     setSource();
2240     Engine::enqueue(message("chan.hangup",false));
2241 
2242     // Disconnect lines
2243     if (!m_line)
2244 	return;
2245 
2246     ModuleLine* peer = fxo();
2247     bool sync = !(peer && peer->callSetup() == AnalogLine::Before);
2248 
2249     m_line->changeState(AnalogLine::Idle,true);
2250     m_line->disconnect(sync);
2251     m_line->acceptPulseDigit(true);
2252     m_line->setCall();
2253 
2254     if (peer) {
2255 	if (!sync)
2256 	    peer->setCallSetupDetector();
2257 	peer->acceptPulseDigit(true);
2258 	peer->setCall();
2259     }
2260 }
2261 
disconnect(const char * reason)2262 bool AnalogCallRec::disconnect(const char* reason)
2263 {
2264     Debug(this,DebugCall,"Disconnecting reason='%s' [%p]",reason,this);
2265     hangup(reason);
2266     return CallEndpoint::disconnect(m_reason);
2267 }
2268 
2269 // Get source(s) and other objects
2270 // DataSource0: caller's source
2271 // DataSource1: called's source
getObject(const String & name) const2272 void* AnalogCallRec::getObject(const String& name) const
2273 {
2274     int who = (name == YATOM("DataSource0")) ? 0 : (name == YATOM("DataSource1") ? 1 : -1);
2275     if (who == -1)
2276 	return CallEndpoint::getObject(name);
2277 
2278     ModuleLine* target = 0;
2279     if (who)
2280 	 target = m_fxsCaller ? m_line : fxo();
2281     else
2282 	 target = m_fxsCaller ? fxo() : m_line;
2283     return (target && target->circuit()) ? target->circuit()->getObject(YATOM("DataSource")) : 0;
2284 }
2285 
2286 // Create data source. Route and execute
startRecording()2287 bool AnalogCallRec::startRecording()
2288 {
2289     m_line->setCircuitParam("echotrain");
2290     if (getSource())
2291 	return true;
2292 
2293     Debug(this,DebugCall,"Start recording [%p]",this);
2294 
2295     Lock lock (m_mutex);
2296     String format = "2*";
2297     DataSource* src = 0;
2298     String buflen;
2299     if (m_line && m_line->circuit()) {
2300 	src = static_cast<DataSource*>(m_line->circuit()->getObject(YATOM("DataSource")));
2301 	m_line->circuit()->getParam("buflen",buflen);
2302     }
2303     if (src)
2304 	format << src->getFormat();
2305 
2306     // Create source
2307     Message* m = message("chan.attach",false,true);
2308     m->addParam("source","mux/");
2309     m->addParam("single",String::boolText(true));
2310     m->addParam("notify",id());
2311     if (buflen)
2312 	m->addParam("chanbuffer",buflen);
2313     m->addParam("format",format);
2314     m->addParam("fail","true");
2315     m->addParam("failempty","true");
2316     if (!Engine::dispatch(m))
2317 	Debug(this,DebugNote,"Error attaching data mux '%s' [%p]",m->getValue("error"),this);
2318     else if (m->userData())
2319 	setSource(static_cast<DataSource*>(m->userData()->getObject(YATOM("DataSource"))));
2320     TelEngine::destruct(m);
2321     if (!getSource()) {
2322 	m_reason = "nodata";
2323 	return false;
2324     }
2325 
2326     // Route and execute
2327     m = message("call.preroute");
2328     m->addParam("callsource",callertype(m_fxsCaller));
2329     const char* caller = m->getValue("caller");
2330     if (!(caller && *caller))
2331 	m->setParam("caller",s_unk);
2332     bool ok = false;
2333     while (true) {
2334 	if (Engine::dispatch(m) && (m->retValue() == "-" || m->retValue() == "error")) {
2335 	    m_reason = m->getValue("reason",m->getValue("error","failure"));
2336 	    break;
2337 	}
2338 	*m = "call.route";
2339 	m->addParam("type","record");
2340 	m->addParam("format",format);
2341 	m->setParam("callsource",callertype(m_fxsCaller));
2342 	if (!(Engine::dispatch(m) && m->retValue())) {
2343 	    m_reason = "noroute";
2344 	    break;
2345 	}
2346 	*m = "call.execute";
2347 	m->userData(this);
2348 	m->setParam("callto",m->retValue());
2349 	m->retValue().clear();
2350 	if (!Engine::dispatch(m)) {
2351 	    m_reason = "noconn";
2352 	    break;
2353 	}
2354 	ok = true;
2355 	break;
2356     }
2357     TelEngine::destruct(m);
2358     if (getPeer()) {
2359 	XDebug(this,DebugInfo,"Got connected: deref() [%p]",this);
2360 	deref();
2361     }
2362     else
2363 	setSource();
2364     return ok;
2365 }
2366 
2367 // Call answered: start recording
answered()2368 bool AnalogCallRec::answered()
2369 {
2370     Lock lock(m_mutex);
2371     if (m_line)
2372 	m_line->noRingTimer().stop();
2373     if (fxo())
2374 	fxo()->noRingTimer().stop();
2375     m_startOnSecondRing = false;
2376     if (!(m_line && startRecording()))
2377 	return false;
2378     if (m_answered)
2379 	return true;
2380     Debug(this,DebugCall,"Answered [%p]",this);
2381     m_answered = true;
2382     m_status = "answered";
2383     m_line->changeState(AnalogLine::Answered,true);
2384     Engine::enqueue(message("call.answered"));
2385     return true;
2386 }
2387 
2388 // Process rings: start recording if delayed
ringing(bool fxsEvent)2389 bool AnalogCallRec::ringing(bool fxsEvent)
2390 {
2391     Lock lock(m_mutex);
2392 
2393     // Re(start) ring timer. Ignore ring events if timer was already started
2394     bool ignore = m_ringTimer.started();
2395     m_ringTimer.start();
2396     if (ignore)
2397 	return true;
2398 
2399     if (m_line)
2400 	m_line->changeState(AnalogLine::Ringing,true);
2401 
2402     // Ignore rings from caller party
2403     if (m_fxsCaller != fxsEvent) {
2404 	DDebug(this,DebugAll,"Ignoring ring from caller [%p]",this);
2405 	return true;
2406     }
2407 
2408     if (!m_answered) {
2409 	m_status = "ringing";
2410 	Engine::enqueue(message("call.ringing",false,true));
2411     }
2412 
2413     bool ok = true;
2414     if (m_fxsCaller) {
2415 	if (m_startOnSecondRing) {
2416 	    m_startOnSecondRing = false;
2417 	    ok = startRecording();
2418 	}
2419 	if (m_line->getPeer())
2420 	    fxo()->removeCallSetupDetector();
2421 	if (ok && !m_answered) {
2422 	    DDebug(this,DebugAll,"Restarting ring timer for " FMT64 "ms [%p]",
2423 		fxo()->noRingTimer().interval(),this);
2424 	    fxo()->noRingTimer().start();
2425 	}
2426     }
2427     return ok;
2428 }
2429 
2430 // Enqueue chan.dtmf
evDigits(bool fxsEvent,const char * text,bool tone)2431 void AnalogCallRec::evDigits(bool fxsEvent, const char* text, bool tone)
2432 {
2433     if (!(text && *text))
2434 	return;
2435     DDebug(this,DebugAll,"Got %s digits=%s from %s [%p]",
2436 	tone?"tone":"pulse",text,callertype(fxsEvent),this);
2437     Message* m = message("chan.dtmf",false,true);
2438     m->addParam("text",text);
2439     if (!tone)
2440 	m->addParam("pulse",String::boolText(true));
2441     m->addParam("sender",callertype(fxsEvent));
2442     m->addParam("detected","analog");
2443     Engine::enqueue(m);
2444 }
2445 
2446 // Process line polarity changes
evPolarity(bool fxsEvent)2447 bool AnalogCallRec::evPolarity(bool fxsEvent)
2448 {
2449     if (fxsEvent)
2450 	return true;
2451 
2452     Lock lock(m_mutex);
2453     m_polarityCount++;
2454     DDebug(this,DebugAll,"Line polarity changed %u time(s) [%p]",m_polarityCount,this);
2455 
2456     ModuleLine* fxo = this->fxo();
2457     if (!fxo)
2458 	return false;
2459 
2460     if (m_fxsCaller) {
2461 	if (!fxo->answerOnPolarity() || m_polarityCount > 1)
2462 	    return !fxo->hangupOnPolarity();
2463 	return true;
2464     }
2465     if (!fxo->answerOnPolarity() || m_answered)
2466 	return !fxo->hangupOnPolarity();
2467     return answered();
2468 }
2469 
2470 // Line alarms changed
evAlarm(bool fxsEvent,bool alarm,const char * alarms)2471 bool AnalogCallRec::evAlarm(bool fxsEvent, bool alarm, const char* alarms)
2472 {
2473     Lock lock(m_mutex);
2474     if (alarm) {
2475 	Debug(this,DebugNote,"%s line is out of order alarms=%s. Terminating now [%p]",
2476 	    callertype(!fxsEvent),alarms,this);
2477 	if (!m_reason) {
2478 	    m_reason = callertype(!fxsEvent);
2479 	    m_reason << "-out-of-order";
2480 	}
2481 	return false;
2482     }
2483     else {
2484 	if (m_line)
2485 	    m_line->setCircuitParam("echotrain");
2486 	Debug(this,DebugInfo,"No more alarms on %s line [%p]",callertype(!fxsEvent),this);
2487     }
2488     return true;
2489 }
2490 
2491 // Check timers. Return false to terminate
checkTimeouts(const Time & when)2492 bool AnalogCallRec::checkTimeouts(const Time& when)
2493 {
2494     Lock lock(m_mutex);
2495 
2496     if (m_ringTimer.timeout(when.msecNow()))
2497 	m_ringTimer.stop();
2498 
2499     if (!fxo()->noRingTimer().timeout(when.msecNow()))
2500 	return true;
2501     DDebug(this,DebugInfo,"Ring timer expired [%p]",this);
2502     fxo()->noRingTimer().stop();
2503     hangup("cancelled");
2504     return false;
2505 }
2506 
2507 // Fill a string with recorder status parameters
statusParams(String & str)2508 void AnalogCallRec::statusParams(String& str)
2509 {
2510     str.append("module=",",") << plugin.name();
2511     str << ",peerid=";
2512     if (getPeer())
2513 	 str << getPeer()->id();
2514     str << ",status=" << m_status;
2515     str << ",initiator=" << callertype(m_fxsCaller);
2516     str << ",answered=" << m_answered;
2517     str << ",address=" << m_address;
2518 }
2519 
2520 // Fill a string with recorder status detail parameters
statusDetail(String & str)2521 void AnalogCallRec::statusDetail(String& str)
2522 {
2523     // format=Status|Address|Peer
2524     Lock lock(m_mutex);
2525     str.append(id(),";") << "=" << m_status;
2526     str << "|" << m_address << "|";
2527     if (getPeer())
2528 	 str << getPeer()->id();
2529 }
2530 
2531 // Remove from driver's list
destroyed()2532 void AnalogCallRec::destroyed()
2533 {
2534     plugin.setRecorder(this,false);
2535     hangup();
2536     // Reset line
2537     if (m_line) {
2538 	m_line->userdata(0,true);
2539 	if (m_line->moduleGroup())
2540 	    m_line->moduleGroup()->setEndpoint(this,false);
2541 	TelEngine::destruct(m_line);
2542     }
2543     Debug(this,DebugCall,"Destroyed reason='%s' [%p]",m_reason.c_str(),this);
2544     CallEndpoint::destroyed();
2545 }
2546 
disconnected(bool final,const char * reason)2547 void AnalogCallRec::disconnected(bool final, const char *reason)
2548 {
2549     DDebug(this,DebugCall,"Disconnected final=%s reason='%s' [%p]",
2550 	String::boolText(final),reason,this);
2551     hangup(reason);
2552     CallEndpoint::disconnected(final,m_reason);
2553 }
2554 
message(const char * name,bool peers,bool userdata)2555 Message* AnalogCallRec::message(const char* name, bool peers, bool userdata)
2556 {
2557     Message* m = new Message(name);
2558     m->addParam("id",id());
2559     m->addParam("status",m_status);
2560     if (m_address)
2561 	m->addParam("address",m_address);
2562     ModuleLine* fxo = peers ? this->fxo() : 0;
2563     if (fxo) {
2564 	if (m_fxsCaller) {
2565 	    m->addParam("caller",fxo->caller());
2566 	    m->addParam("called",fxo->called());
2567 	}
2568 	else {
2569 	    m->addParam("caller",m_line->caller());
2570 	    m->addParam("called",m_line->called());
2571 	}
2572     }
2573     if (m_reason)
2574 	m->addParam("reason",m_reason);
2575     if (userdata)
2576 	m->userData(this);
2577     return m;
2578 }
2579 
2580 
2581 /**
2582  * AnalogDriver
2583  */
2584 String AnalogDriver::s_statusCmd[StatusCmdCount] = {"groups","lines","recorders"};
2585 
AnalogDriver()2586 AnalogDriver::AnalogDriver()
2587     : Driver("analog","varchans"),
2588     m_init(false),
2589     m_recId(0)
2590 {
2591     Output("Loaded module Analog Channel");
2592     m_statusCmd << "status " << name();
2593     m_recPrefix << prefix() << "rec/";
2594 }
2595 
~AnalogDriver()2596 AnalogDriver::~AnalogDriver()
2597 {
2598     Output("Unloading module Analog Channel");
2599     m_groups.clear();
2600 }
2601 
initialize()2602 void AnalogDriver::initialize()
2603 {
2604     Output("Initializing module Analog Channel");
2605     s_cfg = Engine::configFile("analog");
2606     s_cfg.load();
2607 
2608     NamedList dummy("");
2609     NamedList* general = s_cfg.getSection("general");
2610     if (!general)
2611 	general = &dummy;
2612 
2613     // Startup
2614     setup();
2615     if (!m_init) {
2616 	m_init = true;
2617 	installRelay(Masquerade);
2618 	installRelay(Halt);
2619 	installRelay(Progress);
2620 	installRelay(Update);
2621 	installRelay(Route);
2622 	Engine::install(new EngineStartHandler);
2623 	Engine::install(new ChanNotifyHandler);
2624     }
2625 
2626     // Build/initialize groups
2627     String tmpRec = m_recPrefix.substr(0,m_recPrefix.length()-1);
2628     unsigned int n = s_cfg.sections();
2629     for (unsigned int i = 0; i < n; i++) {
2630 	NamedList* sect = s_cfg.getSection(i);
2631 	if (!sect || sect->null() || *sect == "general" ||
2632 	    sect->startsWith(s_lineSectPrefix))
2633 	    continue;
2634 
2635 	// Check section name
2636 	bool valid = true;
2637 	if (*sect == name() || *sect == tmpRec)
2638 	    valid = false;
2639 	else
2640 	    for (unsigned int i = 0; i < StatusCmdCount; i++)
2641 		if (*sect == s_statusCmd[i]) {
2642 		    valid = false;
2643 		    break;
2644 		}
2645 	if (!valid) {
2646 	    Debug(this,DebugWarn,"Invalid use of reserved word in section name '%s'",sect->c_str());
2647 	    continue;
2648 	}
2649 
2650 	ModuleGroup* group = findGroup(*sect);
2651 	if (!sect->getBoolValue("enable",true)) {
2652 	    if (group)
2653 		removeGroup(group);
2654 	    continue;
2655 	}
2656 
2657 	// Create and/or initialize. Check for valid type if creating
2658 	const char* stype = sect->getValue("type");
2659 	int type = lookup(stype,AnalogLine::typeNames(),AnalogLine::Unknown);
2660 	switch (type) {
2661 	    case AnalogLine::FXO:
2662 	    case AnalogLine::FXS:
2663 	    case AnalogLine::Recorder:
2664 	    case AnalogLine::Monitor:
2665 		break;
2666 	    default:
2667 		Debug(this,DebugWarn,"Unknown type '%s' for group '%s'",stype,sect->c_str());
2668 		continue;
2669 	}
2670 
2671 	bool create = (group == 0);
2672 	Debug(this,DebugAll,"%sing group '%s' of type '%s'",create?"Creat":"Reload",sect->c_str(),stype);
2673 
2674 	if (create) {
2675 	    if (type != AnalogLine::Monitor)
2676 		group = new ModuleGroup((AnalogLine::Type)type,*sect);
2677 	    else {
2678 		String tmp = *sect;
2679 		tmp << "/fxo";
2680 		ModuleGroup* fxo = new ModuleGroup(tmp);
2681 		group = new ModuleGroup(*sect,fxo);
2682 	    }
2683 	    lock();
2684 	    m_groups.append(group);
2685 	    unlock();
2686 	    XDebug(this,DebugAll,"Added group (%p,'%s')",group,group->debugName());
2687 	}
2688 
2689 	String error;
2690 	if (!group->initialize(*sect,*general,error)) {
2691 	    Debug(this,DebugWarn,"Failed to %s group '%s'. Error: '%s'",
2692 		create?"create":"reload",sect->c_str(),error.safe());
2693 	    if (create)
2694 		removeGroup(group);
2695 	}
2696     }
2697 }
2698 
msgExecute(Message & msg,String & dest)2699 bool AnalogDriver::msgExecute(Message& msg, String& dest)
2700 {
2701     CallEndpoint* peer = YOBJECT(CallEndpoint,msg.userData());
2702     ModuleLine* line = 0;
2703     String cause;
2704     const char* error = "failure";
2705 
2706     // Check message parameters: peer channel, group, circuit, line
2707     while (true) {
2708 	if (!peer) {
2709 	    cause = "No data channel";
2710 	    break;
2711 	}
2712 	String tmp;
2713 	int cic = decodeAddr(dest,tmp,true);
2714 	ModuleGroup* group = findGroup(tmp);
2715 	if (group && !group->fxoRec()) {
2716 	    if (cic >= 0)
2717 		line = static_cast<ModuleLine*>(group->findLine(cic));
2718 	    else if (cic == -1) {
2719 		Lock lock(group);
2720 		// Destination is a group: find the first free idle line
2721 		for (ObjList* o = group->lines().skipNull(); o; o = o->skipNext()) {
2722 		    line = static_cast<ModuleLine*>(o->get());
2723 		    Lock lockLine(line);
2724 		    if (!line->userdata() && line->state() == AnalogLine::Idle)
2725 			break;
2726 		    line = 0;
2727 		}
2728 		lock.drop();
2729 		if (!line) {
2730 		    cause << "All lines in group '" << dest << "' are busy";
2731 		    error = "busy";
2732 		    break;
2733 		}
2734 	    }
2735 	}
2736 
2737 	if (!line) {
2738 	    cause << "No line with address '" << dest << "'";
2739 	    error = "noroute";
2740 	    break;
2741 	}
2742 	if (line->type() == AnalogLine::Unknown) {
2743 	    cause << "Line '" << line->address() << "' has unknown type";
2744 	    break;
2745 	}
2746 	if (line->userdata()) {
2747 	    cause << "Line '" << line->address() << "' is busy";
2748 	    error = "busy";
2749 	    break;
2750 	}
2751 	if (line->state() == AnalogLine::OutOfService) {
2752 	    cause << "Line '" << line->address() << "' is out of service";
2753 	    error = "noroute";
2754 	    break;
2755 	}
2756 	if (!line->ref())
2757 	    cause = "ref() failed";
2758 	break;
2759     }
2760 
2761     if (!line || cause) {
2762 	Debug(this,DebugNote,"Analog call failed. %s",cause.c_str());
2763 	msg.setParam("error",error);
2764 	return false;
2765     }
2766 
2767     Debug(this,DebugAll,"Executing call. caller=%s called=%s line=%s",
2768 	msg.getValue("caller"),msg.getValue("called"),line->address());
2769 
2770     msg.clearParam("error");
2771     // Create channel
2772     AnalogChannel* analogCh = new AnalogChannel(line,&msg);
2773     analogCh->initChan();
2774     error = msg.getValue("error");
2775     if (!error) {
2776 	if (analogCh->connect(peer,msg.getValue("reason"))) {
2777 	    analogCh->callConnect(msg);
2778 	    msg.setParam("peerid",analogCh->id());
2779 	    msg.setParam("targetid",analogCh->id());
2780 	    if (analogCh->line() && (analogCh->line()->type() == AnalogLine::FXS))
2781 		Engine::enqueue(analogCh->message("call.ringing",false,true));
2782         }
2783     }
2784     else
2785 	Debug(this,DebugNote,"Analog call failed with reason '%s'",error);
2786     analogCh->deref();
2787     return !error;
2788 }
2789 
dropAll(Message & msg)2790 void AnalogDriver::dropAll(Message& msg)
2791 {
2792     const char* reason = msg.getValue("reason");
2793     if (!(reason && *reason))
2794 	reason = "dropped";
2795     DDebug(this,DebugInfo,"dropAll('%s')",reason);
2796     Driver::dropAll(msg);
2797     // Drop recorders
2798     lock();
2799     ListIterator iter(m_recorders);
2800     for (;;) {
2801 	RefPointer<AnalogCallRec> c = static_cast<AnalogCallRec*>(iter.get());
2802 	unlock();
2803 	if (!c)
2804 	    break;
2805 	terminateChan(c,reason);
2806 	c = 0;
2807 	lock();
2808     }
2809 }
2810 
received(Message & msg,int id)2811 bool AnalogDriver::received(Message& msg, int id)
2812 {
2813     String target;
2814 
2815     switch (id) {
2816 	case Masquerade:
2817 	    // Masquerade a recorder message
2818 	    target = msg.getValue("id");
2819 	    if (target.startsWith(recPrefix())) {
2820 		Lock lock(this);
2821 		AnalogCallRec* rec = findRecorder(target);
2822 		if (rec) {
2823 		    msg = msg.getValue("message");
2824 		    msg.clearParam("message");
2825 		    msg.userData(rec);
2826 		    return false;
2827 		}
2828 	    }
2829 	    return Driver::received(msg,id);
2830 	case Status:
2831 	case Drop:
2832 	    target = msg.getValue("module");
2833 	    // Target is the driver or channel
2834 	    if (!target || target == name() || target.startsWith(prefix()))
2835 		return Driver::received(msg,id);
2836 	    // Check if requested a recorder
2837 	    if (target.startsWith(recPrefix())) {
2838 		Lock lock(this);
2839 		AnalogCallRec* rec = findRecorder(target);
2840 		if (!rec)
2841 		    return false;
2842 		if (id == Status) {
2843 		    msg.retValue().clear();
2844 		    rec->statusParams(msg.retValue());
2845 		    msg.retValue() << "\r\n";
2846 		}
2847 		else
2848 		    terminateChan(rec,"dropped");
2849 		return true;
2850 	    }
2851 	    // Done if the command is drop
2852 	    if (id == Drop)
2853 		return Driver::received(msg,id);
2854 	    break;
2855 	case Halt:
2856 	    lock();
2857 	    m_groups.clear();
2858 	    unlock();
2859 	    return Driver::received(msg,id);
2860 	default:
2861 	    return Driver::received(msg,id);
2862     }
2863 
2864     // Check for additional status commands or a specific group or line
2865     if (!target.startSkip(name(),false))
2866 	return false;
2867     target.trimBlanks();
2868     int cmd = 0;
2869     for (; cmd < StatusCmdCount; cmd++)
2870 	if (s_statusCmd[cmd] == target)
2871 	    break;
2872 
2873     Lock lock(this);
2874     DDebug(this,DebugInfo,"Processing '%s' target=%s",msg.c_str(),target.c_str());
2875     // Specific group or line
2876     if (cmd == StatusCmdCount) {
2877 	String group;
2878 	int cic = decodeAddr(target,group,false);
2879 	ModuleGroup* grp = findGroup(group);
2880 	bool ok = true;
2881 	while (grp) {
2882 	    Lock lock(grp);
2883 	    if (target == grp->toString()) {
2884 		msg.retValue().clear();
2885 		grp->statusParams(msg.retValue());
2886 		break;
2887 	    }
2888 	    ModuleLine* line = static_cast<ModuleLine*>(grp->findLine(cic));
2889 	    if (!line) {
2890 		ok = false;
2891 		break;
2892 	    }
2893 	    msg.retValue().clear();
2894 	    Lock lockLine(line);
2895 	    line->statusParams(msg.retValue());
2896 	    break;
2897 	}
2898 	if (ok)
2899 	    msg.retValue() << "\r\n";
2900 	return ok;
2901     }
2902 
2903     // Additional command
2904     String detail;
2905     const char* format = 0;
2906     int count = 0;
2907     switch (cmd) {
2908 	case Groups:
2909 	    format = s_groupStatusDetail;
2910 	    for (ObjList* o = m_groups.skipNull(); o; o = o->skipNext()) {
2911 		count++;
2912 		(static_cast<ModuleGroup*>(o->get()))->statusDetail(detail);
2913 	    }
2914 	    break;
2915 	case Lines:
2916 	    format = s_lineStatusDetail;
2917 	    for (ObjList* o = m_groups.skipNull(); o; o = o->skipNext()) {
2918 		ModuleGroup* grp = static_cast<ModuleGroup*>(o->get());
2919 		Lock lockGrp(grp);
2920 		for (ObjList* ol = grp->lines().skipNull(); ol; ol = ol->skipNext()) {
2921 		    count++;
2922 		    (static_cast<ModuleLine*>(ol->get()))->statusDetail(detail);
2923 		}
2924 	    }
2925 	    break;
2926 	case Recorders:
2927 	    format = s_recStatusDetail;
2928 	    for (ObjList* o = m_recorders.skipNull(); o; o = o->skipNext()) {
2929 		count++;
2930 		(static_cast<AnalogCallRec*>(o->get()))->statusDetail(detail);
2931 	    }
2932 	    break;
2933 	default:
2934 	    count = -1;
2935     }
2936     // Just in case we've missed something
2937     if (count == -1)
2938 	return false;
2939 
2940     msg.retValue().clear();
2941     msg.retValue() << "module=" << name();
2942     msg.retValue() << "," << s_statusCmd[cmd] << "=" << count;
2943     msg.retValue() << "," << format;
2944     if (detail)
2945 	msg.retValue() << ";" << detail;
2946     msg.retValue() << "\r\n";
2947     return true;
2948 }
2949 
2950 // Handle command complete requests
commandComplete(Message & msg,const String & partLine,const String & partWord)2951 bool AnalogDriver::commandComplete(Message& msg, const String& partLine,
2952 	const String& partWord)
2953 {
2954     bool status = partLine.startsWith("status");
2955     bool drop = !status && partLine.startsWith("drop");
2956     if (!(status || drop))
2957 	return Driver::commandComplete(msg,partLine,partWord);
2958 
2959     // 'status' command
2960     Lock lock(this);
2961     // line='status analog': add additional commands, groups and lines
2962     if (partLine == m_statusCmd) {
2963 	DDebug(this,DebugInfo,"Processing '%s' partWord=%s",partLine.c_str(),partWord.c_str());
2964 	for (unsigned int i = 0; i < StatusCmdCount; i++)
2965 	    itemComplete(msg.retValue(),s_statusCmd[i],partWord);
2966 	completeGroups(msg.retValue(),partWord);
2967 	completeLines(msg.retValue(),partWord);
2968 	return true;
2969     }
2970 
2971     if (partLine != "status" && partLine != "drop")
2972 	return false;
2973 
2974     // Empty partial word or name start with it: add name, prefix and recorder prefix
2975     if (itemComplete(msg.retValue(),name(),partWord)) {
2976 	if (channels().skipNull())
2977 	    msg.retValue().append(prefix(),"\t");
2978 	return false;
2979     }
2980     // Non empty partial word greater then module name: check if we have a prefix
2981     if (!partWord.startsWith(prefix()))
2982 	return false;
2983     // Partial word is not empty and starts with module's prefix
2984     // Recorder prefix (greater then any channel ID): complete recorders
2985     // Between module and recorder prefix: complete recorder prefix and channels
2986     if (partWord.startsWith(recPrefix())) {
2987 	bool all = (partWord == recPrefix());
2988 	completeChanRec(msg.retValue(),partWord,false,all);
2989     }
2990     else {
2991 	bool all = (partWord == prefix());
2992 	completeChanRec(msg.retValue(),partWord,true,all);
2993 	completeChanRec(msg.retValue(),partWord,false,all);
2994     }
2995     return true;
2996 }
2997 
2998 // Execute commands
commandExecute(String & retVal,const String & line)2999 bool AnalogDriver::commandExecute(String& retVal, const String& line)
3000 {
3001     DDebug(this,DebugInfo,"commandExecute(%s)",line.c_str());
3002     return false;
3003 }
3004 
3005 // Complete group names from partial command word
completeGroups(String & dest,const String & partWord)3006 void AnalogDriver::completeGroups(String& dest, const String& partWord)
3007 {
3008     for (ObjList* o = m_groups.skipNull(); o; o = o->skipNext())
3009 	itemComplete(dest,static_cast<ModuleGroup*>(o->get())->toString(),partWord);
3010 }
3011 
3012 // Complete line names from partial command word
completeLines(String & dest,const String & partWord)3013 void AnalogDriver::completeLines(String& dest, const String& partWord)
3014 {
3015     for (ObjList* o = m_groups.skipNull(); o; o = o->skipNext()) {
3016 	ModuleGroup* grp = static_cast<ModuleGroup*>(o->get());
3017 	Lock lock(grp);
3018 	for (ObjList* ol = grp->lines().skipNull(); ol; ol = ol->skipNext())
3019 	    itemComplete(dest,static_cast<ModuleLine*>(ol->get())->toString(),partWord);
3020     }
3021 }
3022 
3023 // Notification of line service state change or removal
3024 // Return true if a channel or recorder was found
lineUnavailable(ModuleLine * line)3025 bool AnalogDriver::lineUnavailable(ModuleLine* line)
3026 {
3027     if (!line)
3028 	return false;
3029 
3030     const char* reason = (line->state() == AnalogLine::OutOfService) ? "line-out-of-service" : "line-shutdown";
3031     Lock lock(this);
3032     for (ObjList* o = channels().skipNull(); o; o = o->skipNext()) {
3033 	AnalogChannel* ch = static_cast<AnalogChannel*>(o->get());
3034 	if (ch->line() != line)
3035 	    continue;
3036 	terminateChan(ch,reason);
3037 	return true;
3038     }
3039 
3040     // Check for recorders
3041     if (!line->getPeer())
3042 	return false;
3043     ModuleGroup* grp = line->moduleGroup();
3044     AnalogCallRec* rec = 0;
3045     if (grp && 0 != (rec = grp->findRecorder(line))) {
3046 	terminateChan(rec,reason);
3047 	return true;
3048     }
3049     return false;
3050 }
3051 
3052 // Destroy a channel
terminateChan(AnalogChannel * ch,const char * reason)3053 void AnalogDriver::terminateChan(AnalogChannel* ch, const char* reason)
3054 {
3055     if (!ch)
3056 	return;
3057     DDebug(this,DebugAll,"Terminating channel %s peer=%p reason=%s",
3058 	ch->id().c_str(),ch->getPeer(),reason);
3059     if (ch->getPeer())
3060 	ch->disconnect(reason);
3061     else
3062 	ch->deref();
3063 }
3064 
3065 // Destroy a monitor endpoint
terminateChan(AnalogCallRec * ch,const char * reason)3066 void AnalogDriver::terminateChan(AnalogCallRec* ch, const char* reason)
3067 {
3068     if (!ch)
3069 	return;
3070     DDebug(this,DebugAll,"Terminating recorder %s peer=%p reason=%s",
3071 	ch->id().c_str(),ch->getPeer(),reason);
3072     if (ch->getPeer())
3073 	ch->disconnect(reason);
3074     else
3075 	ch->deref();
3076 }
3077 
3078 // Attach detectors after engine started
engineStart(Message & msg)3079 void AnalogDriver::engineStart(Message& msg)
3080 {
3081     s_engineStarted = true;
3082     Lock lock(this);
3083     for (ObjList* o = m_groups.skipNull(); o; o = o->skipNext()) {
3084 	ModuleGroup* grp = static_cast<ModuleGroup*>(o->get());
3085 	if (grp->type() != AnalogLine::FXO) {
3086 	    grp = grp->fxoRec();
3087 	    if (!grp || grp->type() != AnalogLine::FXO)
3088 		grp = 0;
3089 	}
3090 	if (!grp)
3091 	    continue;
3092 	Lock lock(grp);
3093 	for (ObjList* ol = grp->lines().skipNull(); ol; ol = ol->skipNext()) {
3094 	    ModuleLine* line = static_cast<ModuleLine*>(ol->get());
3095 	    if (line->callSetup() == AnalogLine::Before)
3096 	        line->setCallSetupDetector();
3097 	}
3098     }
3099 }
3100 
3101 // Notify lines on detector events or channels
chanNotify(Message & msg)3102 bool AnalogDriver::chanNotify(Message& msg)
3103 {
3104     String target = msg.getValue("targetid");
3105     if (!target.startSkip(plugin.prefix(),false))
3106 	return false;
3107 
3108     // Check if the notification is for a channel
3109     if (-1 != target.toInteger(-1)) {
3110 	Debug(this,DebugStub,"Ignoring chan.notify with target=%s",msg.getValue("targetid"));
3111 	return true;
3112     }
3113 
3114     // Notify lines
3115     String name;
3116     int cic = decodeAddr(target,name,false);
3117     ModuleLine* line = 0;
3118     Lock lockDrv(this);
3119     ModuleGroup* grp = findGroup(name);
3120     if (grp)
3121 	line = static_cast<ModuleLine*>(grp->findLine(cic));
3122     else {
3123 	// Find by recorder's fxo
3124 	grp = findGroup(name,true);
3125 	if (grp && grp->fxoRec())
3126 	    line = static_cast<ModuleLine*>(grp->fxoRec()->findLine(cic));
3127     }
3128 
3129     Lock lockLine(line);
3130     if (!(line && line->ref())) {
3131 	Debug(this,DebugNote,"Received chan.notify for unknown target=%s",target.c_str());
3132 	return true;
3133     }
3134     lockDrv.drop();
3135     line->processNotify(msg);
3136     line->deref();
3137     return true;
3138 }
3139 
3140 // Append/remove recorders from list
setRecorder(AnalogCallRec * rec,bool add)3141 void AnalogDriver::setRecorder(AnalogCallRec* rec, bool add)
3142 {
3143     if (!rec)
3144 	return;
3145     Lock lock(this);
3146     if (add)
3147 	m_recorders.append(rec);
3148     else
3149 	m_recorders.remove(rec,false);
3150 }
3151 
3152 // Remove a group from list
removeGroup(ModuleGroup * group)3153 void AnalogDriver::removeGroup(ModuleGroup* group)
3154 {
3155     if (!group)
3156 	return;
3157     Lock lock(this);
3158     Debug(this,DebugAll,"Removing group (%p,'%s')",group,group->debugName());
3159     m_groups.remove(group);
3160 }
3161 
3162 // Find a group or recorder by its name
3163 // Set useFxo to true to find a recorder by its fxo's name
findGroup(const char * name,bool useFxo)3164 ModuleGroup* AnalogDriver::findGroup(const char* name, bool useFxo)
3165 {
3166     if (!useFxo)
3167 	return findGroup(name);
3168     if (!(name && *name))
3169 	return 0;
3170     Lock lock(this);
3171     String tmp = name;
3172     for (ObjList* o = m_groups.skipNull(); o; o = o->skipNext()) {
3173 	ModuleGroup* grp = static_cast<ModuleGroup*>(o->get());
3174 	if (grp->fxoRec() && grp->fxoRec()->toString() == tmp)
3175 	    return grp;
3176     }
3177     return 0;
3178 }
3179 
3180 
3181 /**
3182  * AnalogWorkerThread
3183  */
AnalogWorkerThread(ModuleGroup * group)3184 AnalogWorkerThread::AnalogWorkerThread(ModuleGroup* group)
3185     : Thread("Analog Worker"),
3186     m_client(group),
3187     m_groupName(group ? group->debugName() : "")
3188 {
3189 }
3190 
~AnalogWorkerThread()3191 AnalogWorkerThread::~AnalogWorkerThread()
3192 {
3193     DDebug(&plugin,DebugAll,"AnalogWorkerThread(%p,'%s') terminated [%p]",
3194 	m_client,m_groupName.c_str(),this);
3195     if (m_client)
3196 	m_client->m_thread = 0;
3197 }
3198 
run()3199 void AnalogWorkerThread::run()
3200 {
3201     Debug(&plugin,DebugAll,"AnalogWorkerThread(%p,'%s') start running [%p]",
3202 	m_client,m_groupName.c_str(),this);
3203     if (!m_client)
3204 	return;
3205     while (true) {
3206 	Time t = Time();
3207 	AnalogLineEvent* event = m_client->getEvent(t);
3208 	if (!event) {
3209 	    m_client->checkTimers(t);
3210 	    Thread::idle(true);
3211 	    continue;
3212 	}
3213 	ModuleLine* line = static_cast<ModuleLine*>(event->line());
3214 	SignallingCircuitEvent* cicEv = event->event();
3215 	if (line && cicEv)
3216 	    if (!m_client->fxoRec())
3217 		m_client->handleEvent(*line,*cicEv);
3218 	    else
3219 		m_client->handleRecEvent(*line,*cicEv);
3220 	else
3221 	    Debug(m_client,DebugInfo,"Invalid event (%p) line=%p cic event=%p",
3222 		event,line,event->event());
3223 	TelEngine::destruct(event);
3224 	if (Thread::check(true))
3225 	    break;
3226     }
3227 }
3228 
3229 
3230 /**
3231  * EngineStartHandler
3232  */
received(Message & msg)3233 bool EngineStartHandler::received(Message& msg)
3234 {
3235     plugin.engineStart(msg);
3236     return false;
3237 }
3238 
3239 
3240 /**
3241  * ChanNotifyHandler
3242  */
received(Message & msg)3243 bool ChanNotifyHandler::received(Message& msg)
3244 {
3245     return plugin.chanNotify(msg);
3246 }
3247 
3248 }; // anonymous namespace
3249 
3250 /* vi: set ts=8 sw=4 sts=4 noet: */
3251