1 /**
2  * yatesig.h
3  * This file is part of the YATE Project http://YATE.null.ro
4  *
5  * Yet Another Signalling Stack - implements the support for SS7, ISDN and PSTN
6  *
7  * Yet Another Telephony Engine - a fully featured software PBX and IVR
8  * Copyright (C) 2004-2014 Null Team
9  *
10  * This software is distributed under multiple licenses;
11  * see the COPYING file in the main directory for licensing
12  * information for this specific distribution.
13  *
14  * This use of this software may be subject to additional restrictions.
15  * See the LEGAL file in the main directory for details.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  */
21 
22 #ifndef __YATESIG_H
23 #define __YATESIG_H
24 
25 #include <yateclass.h>
26 
27 #ifdef _WINDOWS
28 
29 #ifdef LIBYSIG_EXPORTS
30 #define YSIG_API __declspec(dllexport)
31 #else
32 #ifndef LIBYSIG_STATIC
33 #define YSIG_API __declspec(dllimport)
34 #endif
35 #endif
36 
37 #endif /* _WINDOWS */
38 
39 #ifndef YSIG_API
40 #define YSIG_API
41 #endif
42 
43 /**
44  * Holds all Telephony Engine related classes.
45  */
46 namespace TelEngine {
47 
48 // Signalling classes
49 class SignallingDumper;                  // A generic data dumper
50 class SignallingDumpable;                // A component that can dump data
51 class SignallingNotifier;                // A signalling notifier
52 class SignallingTimer;                   // A signalling timer
53 class SignallingCounter;                 // A signalling counter
54 class SignallingFactory;                 // A signalling component factory
55 class SignallingComponent;               // Abstract signalling component that can be managed by the engine
56 class SignallingEngine;                  // Main signalling component holder
57 class SignallingThreadPrivate;           // Engine private thread
58 class SignallingMessage;                 // Abstract signalling message
59 class SignallingCallControl;             // Abstract phone call signalling
60 class SignallingCall;                    // Abstract single phone call
61 class SignallingEvent;                   // A single signalling related event
62 class SignallingCircuitEvent;            // A single signalling circuit related event
63 class SignallingCircuit;                 // Abstract data circuit used by signalling
64 class SignallingCircuitRange;            // A circuit range (set of circuits)
65 class SignallingCircuitGroup;            // Group of data circuits used by signalling
66 class SignallingCircuitSpan;             // A span in a circuit group
67 class SignallingInterface;               // Abstract digital signalling interface (hardware access)
68 class SignallingReceiver;                // Abstract Layer 2 packet data receiver
69 struct SignallingFlags;                  // Description of parameter flags
70 class SignallingUtils;                   // Library wide services and data provider
71 class SignallingMessageTimer;            // A pending signalling message
72 class SignallingMessageTimerList;        // A pending signalling message list
73 // Analog lines
74 class AnalogLine;                        // An analog line
75 class AnalogLineEvent;                   // A single analog line related event
76 class AnalogLineGroup;                   // A group of analog lines
77 // SS7
78 class SS7PointCode;                      // SS7 Code Point
79 class SS7Label;                          // SS7 Routing Label
80 class SS7MSU;                            // A block of data that holds a Message Signal Unit
81 class SIGTRAN;                           // Abstract SIGTRAN component
82 class SIGTransport;                      // Abstract transport for SIGTRAN
83 class SIGAdaptation;                     // Abstract Adaptation style SIGTRAN
84 class SIGAdaptClient;                    // Client side of adaptation (ASP)
85 class SIGAdaptServer;                    // Server side of adaptation (SG)
86 class SIGAdaptUser;                      // Abstract Adaptation User SIGTRAN
87 class ASPUser;                           // Abstract SS7 ASP user interface
88 class SCCP;                              // Abstract SS7 SCCP interface
89 class GTT;                               // Abstract SCCP Global Title Translation interface
90 class SCCPManagement;                    // Abstract SCCP Management interface
91 class SCCPUser;                          // Abstract SS7 SCCP user interface
92 class TCAPUser;                          // Abstract SS7 TCAP user interface
93 class SS7L2User;                         // Abstract user of SS7 layer 2 (data link) message transfer part
94 class SS7Layer2;                         // Abstract SS7 layer 2 (data link) message transfer part
95 class SS7L3User;                         // Abstract user of SS7 layer 3 (network) message transfer part
96 class SS7Layer3;                         // Abstract SS7 layer 3 (network) message transfer part
97 class SS7Layer4;                         // Abstract SS7 layer 4 (application) protocol
98 class SS7Route;                          // A SS7 MSU route
99 class SS7Router;                         // Main router for SS7 message transfer and applications
100 class SS7M2PA;                           // SIGTRAN MTP2 User Peer-to-Peer Adaptation Layer
101 class SS7M2UA;                           // SIGTRAN MTP2 User Adaptation Layer
102 class SS7M3UA;                           // SIGTRAN MTP3 User Adaptation Layer
103 class SS7MTP2;                           // SS7 Layer 2 implementation on top of a hardware interface
104 class SS7MTP3;                           // SS7 Layer 3 implementation on top of Layer 2
105 class SS7MsgSNM;                         // SNM signalling message
106 class SS7MsgMTN;                         // MTN signalling message
107 class SS7MsgISUP;                        // ISUP signalling message
108 class SS7MsgSCCP;                        // SCCP signalling message
109 class SS7Management;                     // SS7 SNM implementation
110 class SS7ISUPCall;                       // A SS7 ISUP call
111 class SS7ISUP;                           // SS7 ISUP implementation
112 class SS7BICC;                           // SS7 BICC implementation
113 class SS7TUP;                            // SS7 TUP implementation
114 class SS7SCCP;                           // SS7 SCCP implementation
115 class SccpSubsystem;                     // Helper class to keep a SCCP subsystem
116 class SccpLocalSubsystem;                // Helper class to keep s sccp local subsystem informations
117 class SccpRemote;                        // Helper class to keep a remote sccp
118 class SS7AnsiSccpManagement;             // SS7 SCCP management implementation for ANSI
119 class SS7ItuSccpManagement;              // SS7 SCCP management implementation for ITU
120 class SS7SUA;                            // SIGTRAN SCCP User Adaptation Layer
121 class SS7ASP;                            // SS7 ASP implementation
122 class SS7TCAPMessage;                    // SS7 TCAP message wrapper
123 class SS7TCAPError;                      // SS7 TCAP errors
124 class SS7TCAP;                           // SS7 TCAP implementation
125 class SS7TCAPTransaction;                // SS7 TCAP transaction base class
126 class SS7TCAPComponent;                  // SS7 TCAP component
127 class SS7TCAPANSI;                       // SS7 ANSI TCAP implementation
128 class SS7TCAPTransactionANSI;            // SS7 TCAP ANSI Transaction
129 class SS7TCAPITU;                        // SS7 ITU TCAP implementation
130 class SS7TCAPTransactionITU;             // SS7 TCAP ITU Transaction
131 // ISDN
132 class ISDNLayer2;                        // Abstract ISDN layer 2 (Q.921) message transport
133 class ISDNLayer3;                        // Abstract ISDN layer 3 (Q.931) message transport
134 class ISDNFrame;                         // An ISDN Q.921 frame
135 class ISDNQ921;                          // ISDN Q.921 implementation on top of a hardware interface
136 class ISDNQ921Passive;                   // Stateless ISDN Q.921 implementation on top of a hardware interface
137 class ISDNQ921Management;                // ISDN Layer 2 BRI TEI management or PRI with D-channel(s) backup
138 class ISDNIUA;                           // SIGTRAN ISDN Q.921 User Adaptation Layer
139 class ISDNQ931IE;                        // A Q.931 ISDN Layer 3 message Information Element
140 class ISDNQ931Message;                   // A Q.931 ISDN Layer 3 message
141 class ISDNQ931IEData;                    // A Q.931 message IE data processor
142 class ISDNQ931State;                     // Q.931 ISDN call and call controller state
143 class ISDNQ931Call;                      // A Q.931 ISDN call
144 class ISDNQ931CallMonitor;               // A Q.931 ISDN call monitor
145 class ISDNQ931ParserData;                // Q.931 message parser data
146 class ISDNQ931;                          // ISDN Q.931 implementation on top of Q.921
147 class ISDNQ931Monitor;                   // ISDN Q.931 implementation on top of Q.921 of call controller monitor
148 
149 // Macro to create a factory that builds a component by class name
150 #define YSIGFACTORY(clas) \
151 class clas ## Factory : public SignallingFactory \
152 { \
153 protected: \
154 virtual SignallingComponent* create(const String& type, NamedList& name) \
155     { return (type == #clas) ? new clas : 0; } \
156 }; \
157 static clas ## Factory s_ ## clas ## Factory
158 
159 // Macro to create a factory that calls a component's static create method
160 #define YSIGFACTORY2(clas) \
161 class clas ## Factory : public SignallingFactory \
162 { \
163 protected: \
164 virtual SignallingComponent* create(const String& type, NamedList& name) \
165     { return clas::create(type,name); } \
166 }; \
167 static clas ## Factory s_ ## clas ## Factory
168 
169 // Macro to call the factory creation method and return the created component
170 #define YSIGCREATE(type,name) (static_cast<type*>(SignallingFactory::buildInternal(#type,name)))
171 
172 /**
173  * This class is a generic data dumper with libpcap compatibility
174  * @short A generic data dumper
175  */
176 class YSIG_API SignallingDumper
177 {
178 public:
179     /**
180      * Type of dumper output
181      */
182     enum Type {
183 	Raw,
184 	Hexa,
185 	Hdlc,
186 	Q921,
187 	Q931,
188 	Mtp2,
189 	Mtp3,
190 	Sccp,
191     };
192 
193     /**
194      * Constructor
195      * @param type Type of the output desired
196      * @param network True if we are the network side of the link
197      */
198     SignallingDumper(Type type = Hexa, bool network = false);
199 
200     /**
201      * Destructor, closes the output
202      */
203     ~SignallingDumper();
204 
205     /**
206      * Get the type of the dumper
207      * @return Type of the dumper object
208      */
type()209     inline Type type() const
210 	{ return m_type; }
211 
212     /**
213      * Get the network side flag
214      * @return True if we are the network side
215      */
network()216     inline bool network() const
217 	{ return m_network; }
218 
219     /**
220      * Check if the dumper is active
221      * @return True if the object will actually send data to something
222      */
223     bool active() const;
224 
225     /**
226      * Terminate the dump session, close the output
227      */
228     void terminate();
229 
230     /**
231      * Set a new output stream
232      * @param stream New stream for output, NULL to terminate
233      * @param writeHeader True to write the header (if any) at start of stream
234      */
235     void setStream(Stream* stream = 0, bool writeHeader = true);
236 
237     /**
238      * Dump the provided data
239      * @param buf Pointer to buffer to dump
240      * @param len Length of the data
241      * @param sent True if data is being sent, false if is being received
242      * @param link Link number (relevant to MTP2 only)
243      * @return True if the data was dumped successfully
244      */
245     bool dump(void* buf, unsigned int len, bool sent = false, int link = 0);
246 
247     /**
248      * Dump the provided data
249      * @param data Buffer to dump
250      * @param sent True if data is being sent, false if is being received
251      * @param link Link number (relevant to MTP2 only)
252      * @return True if the data was dumped successfully
253      */
254     inline bool dump(const DataBlock& data, bool sent = false, int link = 0)
255 	{ return dump(data.data(),data.length(),sent,link); }
256 
257     /**
258      * Create a file to dump data in it. The file is opened/created in write only, binary mode
259      * @param dbg DebugEnabler requesting the operation (used for debug message on failure)
260      * @param filename The file name to use
261      * @param type The dumper type
262      * @param network True to create a network side dumper
263      * @param create True to create the file if doesn't exist
264      * @param append Append to an existing file. If false and the file already exists, it will be truncated
265      * @return SignallingDumper pointer on success, 0 on failure
266      */
267     static SignallingDumper* create(DebugEnabler* dbg, const char* filename, Type type,
268 	bool network = false, bool create = true, bool append = false);
269 
270     /**
271      * Create a dumper from an already existing stream
272      * @param stream Stream to use for output, will be owned by dumper
273      * @param type The dumper type
274      * @param network True to create a network side dumper
275      * @param writeHeader True to write the header (if any) at start of stream
276      * @return SignallingDumper pointer on success, 0 on failure
277      */
278     static SignallingDumper* create(Stream* stream, Type type, bool network = false, bool writeHeader = true);
279 
280 private:
281     void head();
282     Type m_type;
283     bool m_network;
284     Stream* m_output;
285 };
286 
287 /**
288  * A generic base class for components capable of creating data dumps
289  * @short A data dumping capable component
290  */
291 class YSIG_API SignallingDumpable
292 {
293 public:
294     /**
295      * Destructor - destroys the data dumper
296      */
~SignallingDumpable()297     inline ~SignallingDumpable()
298 	{ setDumper(); }
299 
300 protected:
301     /**
302      * Constructor
303      * @param type Default type of the data dumper
304      * @param network True if we are the network side of the link
305      */
306     inline SignallingDumpable(SignallingDumper::Type type, bool network = false)
m_type(type)307 	: m_type(type), m_dumpNet(network), m_dumper(0)
308 	{ }
309 
310     /**
311      * Dump the provided data if the dumper is valid
312      * @param buf Pointer to buffer to dump
313      * @param len Length of the data
314      * @param sent True if data is being sent, false if is being received
315      * @param link Link number (relevant to MTP2 only)
316      * @return True if the data was dumped successfully
317      */
318     inline bool dump(void* buf, unsigned int len, bool sent = false, int link = 0)
319 	{ return (m_dumper && m_dumper->dump(buf,len,sent,link)); }
320 
321     /**
322      * Dump data if the dumper is valid
323      * @param data Buffer to dump
324      * @param sent True if data is being sent, false if is being received
325      * @param link Link number (relevant to MTP2 only)
326      * @return True if the data was dumped successfully
327      */
328     inline bool dump(const DataBlock& data, bool sent = false, int link = 0)
329 	{ return dump(data.data(),data.length(),sent,link); }
330 
331     /**
332      * Set the dump network side flag
333      * @param network True to dump as network side, false othervise
334      */
setDumpNetwork(bool network)335     inline void setDumpNetwork(bool network)
336 	{ m_dumpNet = network; }
337 
338     /**
339      * Set or remove the data dumper
340      * @param dumper Pointer to the data dumper object, 0 to remove
341      */
342     void setDumper(SignallingDumper* dumper = 0);
343 
344     /**
345      * Set or remove a file data dumper
346      * @param name Name of the file to dump to, empty to remove dumper
347      * @param create True to create the file if doesn't exist
348      * @param append Append to an existing file. If false and the file already exists, it will be truncated
349      * @return True if the file dumper was created or removed
350      */
351     bool setDumper(const String& name, bool create = true, bool append = false);
352 
353     /**
354      * Handle dumper related control on behalf of the owning component
355      * @param params Control parameters to handle
356      * @param owner Optional owning component
357      * @return True if control operation was applied
358      */
359     bool control(NamedList& params, SignallingComponent* owner = 0);
360 
361 private:
362     SignallingDumper::Type m_type;
363     bool m_dumpNet;
364     SignallingDumper* m_dumper;
365 };
366 
367 /**
368  * Notifying class. Used to handle notifications.
369  * @short Notifier class
370  */
371 
372 class YSIG_API SignallingNotifier
373 {
374 public:
375     /**
376      * Destructor.
377      */
~SignallingNotifier()378     virtual inline ~SignallingNotifier()
379 	{ cleanup(); }
380     /**
381      * Handle the received notifications
382      * @param notifs Received notifications
383      */
384     virtual void notify(NamedList& notifs);
385     /**
386      * Handle necessary clean up
387      */
388     virtual void cleanup();
389 };
390 
391 /**
392  * Timer management class. Used to manage timeouts. The time is kept in miliseconds
393  * @short A signalling timer
394  */
395 class YSIG_API SignallingTimer
396 {
397 public:
398     /**
399      * Constructor
400      * @param interval The timeout interval. Set to 0 to disable
401      * @param time Optional timeout value. If non 0, the timer is started
402      */
403     inline SignallingTimer(u_int64_t interval, u_int64_t time = 0)
m_interval(interval)404 	: m_interval(interval), m_timeout(0)
405 	{ if (time) start(time); }
406 
407     /**
408      * Set the timeout interval
409      * @param value The new timeout value
410      */
interval(u_int64_t value)411     inline void interval(u_int64_t value)
412 	{ m_interval = value; }
413 
414     /**
415      * Set the timeout interval from a list of parameters. The interval value is
416      *  checked to be at least minVal or 0 if allowDisable is true
417      * @param params The list of parameters
418      * @param param The name of the parameter containing the timer interval value
419      * @param minVal Minimum value allowed for the timer interval
420      * @param defVal Default value if it fails to get one from the given parameter
421      * @param allowDisable True to allow 0 for the timer interval
422      * @param sec True if the interval value if given in seconds
423      */
424     inline void interval(const NamedList& params, const char* param,
425 	unsigned int minVal, unsigned int defVal, bool allowDisable, bool sec = false) {
426 	    m_interval = getInterval(params,param,minVal,defVal,0,allowDisable);
427 	    if (sec)
428 		m_interval *= 1000;
429 	}
430 
431     /**
432      * Get the timeout interval
433      * @return The timeout interval
434      */
interval()435     inline u_int64_t interval() const
436 	{ return m_interval; }
437 
438     /**
439      * Get the time this timer will fire (timeout)
440      * @return The timeout (fire) time
441      */
fireTime()442     inline u_int64_t fireTime() const
443 	{ return m_timeout; }
444 
445     /**
446      * Start the timer if enabled (interval is positive)
447      * @param time Time to be added to the interval to set the timeout point
448      */
449     inline void start(u_int64_t time = Time::msecNow())
450 	{ if (m_interval) m_timeout = time + m_interval; }
451 
452     /**
453      * Fire the timer at a specific absolute time
454      * @param time Absolute time (in msec) when the timer will fire
455      */
456     inline void fire(u_int64_t time = Time::msecNow())
457 	{ m_timeout = time; }
458 
459     /**
460      * Stop the timer
461      */
stop()462     inline void stop()
463 	{ m_timeout = 0; }
464 
465     /**
466      * Check if the timer is started
467      * @return True if the timer is started
468      */
started()469     inline bool started() const
470 	{ return m_timeout > 0; }
471 
472     /**
473      * Check if the timer is started and timed out
474      * @param time The time to compare with
475      * @return True if the timer timed out
476      */
477     inline bool timeout(u_int64_t time = Time::msecNow()) const
478 	{ return started() && (m_timeout < time); }
479 
480     /**
481      * Retrieve a timer interval from a list of parameters.
482      * @param params The list of parameters
483      * @param param The name of the parameter containing the timer interval value
484      * @param minVal Minimum value allowed for the timer interval
485      * @param defVal Default value if it fails to get one from the given parameter
486      * @param maxVal Optional interval maximum value
487      * @param allowDisable True to allow 0 for the timer interval
488      * @return The interval value
489      */
490     static unsigned int getInterval(const NamedList& params, const char* param,
491 	unsigned int minVal, unsigned int defVal, unsigned int maxVal = 0,
492 	bool allowDisable = false);
493 
494 private:
495     u_int64_t m_interval;                // Timer interval
496     u_int64_t m_timeout;                 // Timeout value
497 };
498 
499 /**
500  * Counter management class. Keep a value between 0 and a given maximum one
501  * @short A counter class
502  */
503 class YSIG_API SignallingCounter
504 {
505 public:
506     /**
507      * Constructor
508      * @param maxVal The maximum value for the counter
509      */
SignallingCounter(u_int32_t maxVal)510     inline SignallingCounter(u_int32_t maxVal)
511 	: m_max(maxVal), m_count(0)
512 	{ }
513 
514     /**
515      * Set the maximum value for the counter
516      * @param value The new maximum value for the counter
517      */
maxVal(u_int32_t value)518     inline void maxVal(u_int32_t value)
519 	{ m_max = value; }
520 
521     /**
522      * Get the maximum value for the counter
523      * @return The maximum value for the counter
524      */
maxVal()525     inline u_int32_t maxVal() const
526 	{ return m_max; }
527 
528     /**
529      * Get the current value of the counter
530      * @return The current value of the counter
531      */
count()532     inline u_int32_t count() const
533 	{ return m_count; }
534 
535     /**
536      * Reset the counter's value
537      * @param down True to reset to 0, false to reset to maxVal()
538      */
539     inline void reset(bool down = true)
540 	{ m_count = down ? 0 : m_max; }
541 
542     /**
543      * Increment the counter's value if it can
544      * @return False if the counter is full (reached the maximum value)
545      */
inc()546     inline bool inc()
547     {
548 	if (full())
549 	    return false;
550 	m_count++;
551 	return true;
552     }
553 
554     /**
555      * Decrement the counter's value if it can
556      * @return False if the counter is empty (reached 0)
557      */
dec()558     inline bool dec()
559     {
560 	if (empty())
561 	    return false;
562 	m_count--;
563 	return true;
564     }
565 
566     /**
567      * Check if the counter is empty (the value is 0)
568      * @return True if the counter is empty
569      */
empty()570     inline bool empty() const
571 	{ return m_count == 0; }
572 
573     /**
574      * Check if the counter is full (the value reached the maximum)
575      * @return True if the counter is full
576      */
full()577     inline bool full() const
578 	{ return m_count == maxVal(); }
579 
580 private:
581     u_int32_t m_max;                     // Maximum counter value
582     u_int32_t m_count;                   // Current counter value
583 };
584 
585 /**
586  * A factory that constructs various elements by name
587  * @short A signalling component factory
588  */
589 class YSIG_API SignallingFactory : public GenObject
590 {
591 public:
592     /**
593      * Constructor, adds the factory to the global list
594      * @param fallback True to add this factory at the end of the priority list
595      */
596     SignallingFactory(bool fallback = false);
597 
598     /**
599      * Destructor, removes the factory from list
600      */
601     virtual ~SignallingFactory();
602 
603     /**
604      * Builds a component given its name and arbitrary parameters
605      * @param type The type of the component that should be returned
606      * @param name Name of the requested component and additional parameters
607      * @return Pointer to the created component, NULL on failure
608      */
609     static SignallingComponent* build(const String& type, NamedList* name = 0);
610 
611     /**
612      * This method is for internal use only and must not be called directly
613      * @param type The name of the interface that should be returned
614      * @param name Name of the requested component and additional parameters
615      * @return Raw pointer to the requested interface of the component, NULL on failure
616      */
617     static void* buildInternal(const String& type, NamedList* name);
618 
619 protected:
620     /**
621      * Creates a component given its name and arbitrary parameters
622      * @param type The name of the interface that should be returned
623      * @param name Name of the requested component and additional parameters
624      * @return Pointer to the created component
625      */
626     virtual SignallingComponent* create(const String& type, NamedList& name) = 0;
627 };
628 
629 /**
630  * Interface to an abstract signalling component that is managed by an engine.
631  * The engine will periodically poll each component to keep them alive.
632  * @short Abstract signalling component that can be managed by the engine
633  */
634 class YSIG_API SignallingComponent : public RefObject, public DebugEnabler
635 {
636     YCLASS(SignallingComponent,RefObject)
637     friend class SignallingEngine;
638 public:
639     /**
640      * Destructor, detaches the engine and other components
641      */
642     virtual ~SignallingComponent();
643 
644     /**
645      * Get the component's name so it can be used for list searches
646      * @return A reference to the name by which the component is known to engine
647      */
648     virtual const String& toString() const;
649 
650     /**
651      * Configure and initialize the component and any subcomponents it may have
652      * @param config Optional configuration parameters override
653      * @return True if the component was initialized properly
654      */
655     virtual bool initialize(const NamedList* config);
656 
657     /**
658      * Choose parameters that should be used for object initialization
659      * @param cmpName The name of the parameter holding the component name
660      * @param params The list of parameters used to initialize the component
661      * @param config The received list of parameters
662      * @return True if the config was resolved
663      */
664     static bool resolveConfig(const String& cmpName, NamedList& params, const NamedList* config);
665 
666     /**
667      * Query or modify component's settings or operational parameters
668      * @param params The list of parameters to query or change
669      * @return True if the control operation was executed
670      */
671     virtual bool control(NamedList& params);
672 
673     /**
674      * Create a parameter list adequate to control this component
675      * @param oper Optional name of the operation to execute
676      * @return A new parameter list or descendant object, NULL if not supported
677      */
678     virtual NamedList* controlCreate(const char* oper = 0);
679 
680     /**
681      * Execute or postpone a control command
682      * @param params Parameter list describing the command, will be destroyed
683      * @return True if the command was accepted (but not necessarily executed)
684      */
685     virtual bool controlExecute(NamedList* params);
686 
687     /**
688      * Set the @ref TelEngine::SignallingEngine that manages this component
689      *  and any subcomponent of it
690      * @param eng Pointer to the engine that will manage this component
691      */
692     virtual void engine(SignallingEngine* eng);
693 
694     /**
695      * Get the @ref TelEngine::SignallingEngine that manages this component
696      * @return Pointer to engine or NULL if not managed by an engine
697      */
engine()698     inline SignallingEngine* engine() const
699 	{ return m_engine; }
700 
701     /**
702      * Conditionally set the debug level of the component
703      * @param level Desired debug level, negative for no change
704      * @return Current debug level
705      */
debugLevel(int level)706     inline int debugLevel(int level)
707 	{ return (level >= 0) ? DebugEnabler::debugLevel(level) : DebugEnabler::debugLevel(); }
708 
709     /**
710      * Return the type of this component
711      * @return A string version of the component type
712      */
componentType()713     inline const String& componentType() const
714 	{ return m_compType; }
715 
716 protected:
717     /**
718      * Constructor with a default empty component name
719      * @param name Name of this component
720      * @param params Optional pointer to creation parameters
721      * @param type Default component type string
722      */
723     SignallingComponent(const char* name = 0, const NamedList* params = 0, const char* type = "unknown");
724 
725     /**
726      * This method is called to clean up and destroy the object after the
727      *  reference counter becomes zero
728      */
729     virtual void destroyed();
730 
731     /**
732      * Insert another component in the same engine as this one.
733      * This method should be called for every component we attach.
734      * @param component Pointer to component to insert in engine
735      */
736     void insert(SignallingComponent* component);
737 
738     /**
739      * Detach this component from all its links - components and engine.
740      * Reimplement this method in all components that keep pointers to
741      *  other components.
742      * The default implementation detaches from the engine.
743      */
744     virtual void detach();
745 
746     /**
747      * Method called periodically by the engine to keep everything alive
748      * @param when Time to use as computing base for events and timeouts
749      */
750     virtual void timerTick(const Time& when);
751 
752     /**
753      * Change the name of the component after it was constructed
754      * @param name Name of this component
755      */
756     void setName(const char* name);
757 
758     /**
759      * Change the type of the component after it was constructed
760      * @param type Type of this component
761      */
setCompType(const char * type)762     inline void setCompType(const char* type)
763 	{ m_compType = type; }
764 
765     /**
766      * Adjust (decrease only) the desired maximum time until next tick.
767      * Can be called only from within timerTick()
768      * @param usec Desired time until next engine's timerTick() call in usec
769      * @return Timer sleep in usec after applying the current change
770      */
771     unsigned long tickSleep(unsigned long usec = 1000000) const;
772 
773 private:
774     SignallingEngine* m_engine;
775     String m_name;
776     String m_compType;
777 };
778 
779 /**
780  * The engine is the center of all SS7 or ISDN applications.
781  * It is used as a base to build the protocol stack from components.
782  * @short Main signalling component holder
783  */
784 class YSIG_API SignallingEngine : public DebugEnabler, public Mutex
785 {
786     friend class SignallingComponent;
787     friend class SignallingThreadPrivate;
788 public:
789     /**
790      * Constructor of an empty engine
791      * @param name The debug name of this engine
792      */
793     SignallingEngine(const char* name = "signalling");
794 
795     /**
796      * Destructor, removes all components
797      */
798     virtual ~SignallingEngine();
799 
800     /**
801      * Get a pointer to the first (and usually only) instance created
802      * @param create Create the instance if it doesn't exist
803      * @return Pointer to first engine, NULL if not created
804      */
805     static SignallingEngine* self(bool create = false);
806 
807     /**
808      * Insert a component in the engine, lock the list while doing so
809      * @param component Pointer to component to insert in engine
810      */
811     void insert(SignallingComponent* component);
812 
813     /**
814      * Remove a component from the engine, lock the list while doing so
815      * @param component Pointer to component to remove from engine
816      */
817     void remove(SignallingComponent* component);
818 
819     /**
820      * Remove and destroy a component from the engine by name
821      * @param name Name of component to remove from engine
822      * @return True if a component was found and destroyed
823      */
824     bool remove(const String& name);
825 
826     /**
827      * Retrieve a component by name, lock the list while searching for it
828      * @param name Name of the component to find
829      * @return Pointer to component found or NULL
830      */
831     SignallingComponent* find(const String& name);
832 
833     /**
834      * Retrieve a component by name and class, lock the list while searching for it
835      * @param name Name of the component to find, empty to find any of the type
836      * @param type Class or base class of the component to find, empty to match any
837      * @param start Component to start searching from, search all list if NULL
838      * @return Pointer to component found or NULL
839      */
840     SignallingComponent* find(const String& name, const String& type, const SignallingComponent* start = 0);
841 
842     /**
843      * Retrieve and reference an existing component, create by factory if not present
844      * @param type Class or base class of the component to find or create
845      * @param params Name of component to find or create and creation parameters
846      * @param init Set to true to initialize a newly created component
847      * @param ref True to add a reference when returning existing component
848      * @return Pointer to component found or created, NULL on failure
849      */
850     SignallingComponent* build(const String& type, NamedList& params, bool init = false, bool ref = true);
851 
852     /**
853      * Apply a control operation to all components in the engine
854      * @param params The list of parameters to query or change
855      * @return True if the control operation was executed by at least one component
856      */
857     bool control(NamedList& params);
858 
859     /**
860      * Check if a component is in the engine's list
861      * @param component Pointer to component to check
862      * @return True if the component is in the engine's list
863      */
864     bool find(const SignallingComponent* component);
865 
866     /**
867      * Handle notifications from a SignallingComponent
868      * @param component The SignallingComponent from which the notifications were received
869      * @param notifs The notifications sent by this SignallingComponent
870      */
871     void notify(SignallingComponent* component, NamedList notifs);
872 
873     /**
874      * Starts the worker thread that keeps components alive
875      * @param name Static name of the thread
876      * @param prio Thread's priority
877      * @param usec How long to sleep between iterations in usec, 0 to use library default
878      * @return True if (already) started, false if an error occured
879      */
880     bool start(const char* name = "Sig Engine", Thread::Priority prio = Thread::Normal, unsigned long usec = 0);
881 
882     /**
883      * Stops and destroys the worker thread if running
884      */
885     void stop();
886 
887     /**
888      * Add to this engine a notifier object
889      * @param notifier The SignallingNotifier object to be added to the engine
890      */
setNotifier(SignallingNotifier * notifier)891     inline void setNotifier(SignallingNotifier* notifier)
892 	{ m_notifier = notifier; }
893 
894     /**
895      * Remove from this engine a notifier object
896      * @param notifier The SignallingNotifier object to be removed from the engine
897      */
removeNotifier(SignallingNotifier * notifier)898     inline void removeNotifier(SignallingNotifier* notifier)
899     {
900 	if (m_notifier == notifier)
901 	    m_notifier = 0;
902     }
903 
904     /**
905      * Return a pointer to the worker thread
906      * @return Pointer to running worker thread or NULL
907      */
908     Thread* thread() const;
909 
910     /**
911      * Adjust (decrease only) the desired maximum time until next tick.
912      * Can be called only from within timerTick()
913      * @param usec Desired time until next timerTick() call in usec
914      * @return Timer sleep in usec after applying the current change
915      */
916     unsigned long tickSleep(unsigned long usec = 1000000);
917 
918     /**
919      * Get the default engine tick sleep time in microseconds
920      * @return Default timer sleep in usec
921      */
tickDefault()922     inline unsigned long tickDefault() const
923 	{ return m_usecSleep; }
924 
925     /**
926      * Get the maximum time we should spend acquiring a non-critical Mutex
927      * @return Maximum non-critical lock wait in usec, -1 to wait forever
928      */
maxLockWait()929     inline static long maxLockWait()
930 	{ return s_maxLockWait; }
931 
932     /**
933      * Set the maximum time we should spend acquiring a non-critical Mutex
934      * @param maxWait New maximum non-critical lock wait in usec, negative to wait forever
935      */
936     static void maxLockWait(long maxWait);
937 
938     /**
939      * Helper template used to remove a component descendant from its engine,
940      *  destroy it and set the received pointer to 0
941      * @param obj Reference to pointer (lvalue) to the object to remove and destroy
942      */
destruct(Obj * & obj)943     template <class Obj> static inline void destruct(Obj*& obj)
944     {
945 	if (!obj)
946 	    return;
947 	if (obj->engine())
948 	    obj->engine()->remove(obj);
949 	TelEngine::destruct(obj);
950     }
951 
952 protected:
953     /**
954      * Method called periodically by the worker thread to keep everything alive
955      * @param when Time to use as computing base for events and timeouts
956      * @return Desired sleep (in usec) until thread's next tick interval
957      */
958     virtual unsigned long timerTick(const Time& when);
959 
960     /**
961      * The list of components managed by this engine
962      */
963     ObjList m_components;
964 
965 private:
966     SignallingThreadPrivate* m_thread;
967     SignallingNotifier* m_notifier;
968     unsigned long m_usecSleep;
969     unsigned long m_tickSleep;
970     static long s_maxLockWait;
971 };
972 
973 /**
974  * Interface of protocol independent signalling message
975  * @short Abstract signalling message
976  */
977 class YSIG_API SignallingMessage : public RefObject
978 {
YCLASS(SignallingMessage,RefObject)979     YCLASS(SignallingMessage,RefObject)
980 public:
981     /**
982      * Constructor
983      * @param name Named list's name
984      */
985     inline SignallingMessage(const char* name = 0)
986 	: m_params(name)
987 	{ }
988 
989     /**
990      * Get the name of the message
991      * @return The name of the message
992      */
name()993     inline const char* name() const
994 	{ return m_params.c_str(); }
995 
996     /**
997      * Get this message's parameter list
998      * @return This message's parameter list
999      */
params()1000     inline NamedList& params()
1001 	{ return m_params; }
1002 
1003     /**
1004      * Get this message's parameter list - const version
1005      * @return This message's parameter list
1006      */
params()1007     inline const NamedList& params() const
1008 	{ return m_params; }
1009 
1010 protected:
1011     /**
1012      * Message parameter list
1013      */
1014     NamedList m_params;
1015 };
1016 
1017 /**
1018  * Interface of protocol independent signalling for phone calls
1019  * @short Abstract phone call signalling
1020  */
1021 class YSIG_API SignallingCallControl : public Mutex
1022 {
1023     friend class SignallingCall;
1024     friend class SS7ISUPCall;
1025     friend class ISDNQ931Call;
1026     friend class ISDNQ931CallMonitor;
1027 public:
1028 
1029     /**
1030      * When is media absolutely required during the call
1031      */
1032     enum MediaRequired {
1033 	MediaNever,
1034 	MediaAnswered,
1035 	MediaRinging,
1036 	MediaAlways
1037     };
1038 
1039     /**
1040      * Constructor
1041      * @param params Call controller's parameters
1042      * @param msgPrefix Optional prefix to be added before a decoded message's
1043      *  parameters or retrieve message parameters from a list
1044      */
1045     SignallingCallControl(const NamedList& params, const char* msgPrefix = 0);
1046 
1047     /**
1048      * Destructor
1049      */
1050     virtual ~SignallingCallControl();
1051 
1052     /**
1053      * Retrieve Q.850 cause location
1054      * @return Controller location
1055      */
location()1056     inline const String& location() const
1057 	{ return m_location; }
1058 
1059     /**
1060      * Set exiting flag
1061      */
setExiting()1062     inline void setExiting()
1063 	{ m_exiting = true; }
1064 
1065     /**
1066      * Get exiting flag
1067      * @return The exiting flag
1068      */
exiting()1069     inline bool exiting() const
1070 	{ return m_exiting; }
1071 
1072     /**
1073      * Check the verify event flag. Reset it if true is returned
1074      * @return True if the verify event flag is set
1075      */
verify()1076     inline bool verify()
1077     {
1078 	Lock lock(this);
1079 	if (!m_verifyEvent)
1080 	    return false;
1081 	m_verifyEvent = false;
1082 	return true;
1083     }
1084 
1085     /**
1086      * Get the Media Required flag
1087      * @return Configured media requirement
1088      */
mediaRequired()1089     inline MediaRequired mediaRequired() const
1090 	{ return m_mediaRequired; }
1091 
1092     /**
1093      * Get the prefix used by this call controller when decoding message parameters or
1094      *  retrieve message parameters from a list
1095      * @return Message parameters prefix used by this call controller
1096      */
msgPrefix()1097     inline const String& msgPrefix() const
1098 	{ return m_msgPrefix; }
1099 
1100     /**
1101      * Get the circuit group attached to this call controller
1102      * @return The circuit group attached to this call controller
1103      */
circuits()1104     inline SignallingCircuitGroup* circuits() const
1105 	{ return m_circuits; }
1106 
1107     /**
1108      * Get the list of calls currently known by this call controller
1109      * @return Reference to the list of calls
1110      */
calls()1111     inline const ObjList& calls() const
1112 	{ return m_calls; }
1113 
1114     /**
1115      * Get the controller's status as text
1116      * @return Controller status name
1117      */
1118     virtual const char* statusName() const = 0;
1119 
1120     /**
1121      * Attach/detach a circuit group to this call controller. Set group's allocation strategy.
1122      * Set locked flags for all circuits belonging to the attached circuit group.
1123      * Cleanup controller before detaching the group or attaching a new one
1124      * This method is thread safe
1125      * @param circuits Pointer to the SignallingCircuitGroup to attach. 0 to detach and force a cleanup
1126      * @return Pointer to the old group that was detached, NULL if none or no change
1127      */
1128     SignallingCircuitGroup* attach(SignallingCircuitGroup* circuits);
1129 
1130     /**
1131      * Reserve a circuit for later use. If the circuit list is 0, try to reserve a circuit from
1132      *  the group using its strategy. Release the given circuit before trying to reserve it.
1133      *  Set cic to 0 on failure.
1134      * This method is thread safe
1135      * @param cic Destination circuit
1136      * @param checkLock Lock flags to check. If the given lock flags are set, reservation will fail
1137      * @param range Optional range name to restrict circuit reservation within attached circuit group
1138      * @param list Comma separated list of circuits
1139      * @param mandatory The list is mandatory. If false and none of the circuits in
1140      *  the list are available, try to reserve a free one. Ignored if list is 0
1141      * @param reverseRestrict Used when failed to reserve circuit from list. If true and the circuit allocation
1142      *  strategy includes any restriction (odd or even) use the opposite restriction to reserve a circuit.
1143      *  Ignored if mandatory is true
1144      * @return False if the operation failed
1145      */
1146     bool reserveCircuit(SignallingCircuit*& cic, const char* range = 0, int checkLock = -1,
1147 	const String* list = 0,	bool mandatory = true, bool reverseRestrict = false);
1148 
1149     /**
1150      * Initiate a release of a circuit. Set cic to 0.
1151      * This method is thread safe
1152      * @param cic The circuit to release
1153      * @param sync Synchronous release requested
1154      * @return True if the circuit release was initiated
1155      */
1156     bool releaseCircuit(SignallingCircuit*& cic, bool sync = false);
1157 
1158     /**
1159      * Initiate a release of a circuit from the attached group
1160      * This method is thread safe
1161      * @param code The circuit's code
1162      * @param sync Synchronous release requested
1163      * @return True if the circuit release was initiated
1164      */
1165     bool releaseCircuit(unsigned int code, bool sync = false);
1166 
1167     /**
1168      * Cleanup
1169      * @param reason Cleanup reason
1170      */
1171     virtual void cleanup(const char* reason = "net-out-of-order")
1172 	{ }
1173 
1174     /**
1175      * Iterate through the call list to get an event
1176      * @param when The current time
1177      * @return SignallingEvent pointer or 0 if no events
1178      */
1179     virtual SignallingEvent* getEvent(const Time& when);
1180 
1181     /**
1182      * Create an outgoing call. Send a NewCall event with the given msg parameter
1183      * @param msg Call parameters
1184      * @param reason Failure reason if any
1185      * @return Referenced SignallingCall pointer on success or 0 on failure
1186      */
call(SignallingMessage * msg,String & reason)1187     virtual SignallingCall* call(SignallingMessage* msg, String& reason)
1188 	{ reason = "not-implemented"; return 0; }
1189 
1190     /**
1191      * Build the parameters of a Verify event
1192      * @param params The list of parameters to fill
1193      */
buildVerifyEvent(NamedList & params)1194     virtual void buildVerifyEvent(NamedList& params)
1195 	{ }
1196 
1197 protected:
1198     /**
1199      * Get the strategy used by the attached circuit group to allocate circuits
1200      * @return The strategy used by the attached circuit group to allocate circuits
1201      */
strategy()1202     inline int strategy() const
1203 	{ return m_strategy; }
1204 
1205     /**
1206      * Process an event received from a call. This will give to derived classes an opportunity
1207      *  to intercept events generated by their calls
1208      * @param event The event
1209      * @return True if the event was processed by the controller.
1210      *  False to deliver the event to the requestor
1211      */
processEvent(SignallingEvent * event)1212     virtual bool processEvent(SignallingEvent* event)
1213 	{ return false; }
1214 
1215     /**
1216      * Process an event received from a non-reserved circuit
1217      * @param event The event, will be consumed and zeroed
1218      * @param call Optional signalling call whose circuit generated the event
1219      * @return Signalling event pointer or 0
1220      */
1221     virtual SignallingEvent* processCircuitEvent(SignallingCircuitEvent*& event,
1222 	SignallingCall* call = 0)
1223 	{ TelEngine::destruct(event); return 0; }
1224 
1225     /**
1226      * Clear call list
1227      */
1228     void clearCalls();
1229 
1230     /**
1231      * Remove a call from list
1232      * @param call The call to remove
1233      * @param del True to delete it. False to remove without destruct
1234      */
1235     void removeCall(SignallingCall* call, bool del = false);
1236 
1237     /**
1238      * Set the verify event flag. Restart/fire verify timer
1239      * @param restartTimer True to restart/fire the timer
1240      * @param fireNow True to fire the verify timer. Ignored if restartTimer is false
1241      * @param time Optional time to use for timer restart
1242      */
1243     void setVerify(bool restartTimer = false, bool fireNow = false, const Time* time = 0);
1244 
1245     /**
1246      * List of active calls
1247      */
1248     ObjList m_calls;
1249 
1250     /**
1251      * Prefix to be added to decoded message parameters or
1252      *  retrieve message parameters from a list
1253      */
1254     String m_msgPrefix;
1255 
1256     /**
1257      * Media required flag, call should drop if requirement not satisfied
1258      */
1259     MediaRequired m_mediaRequired;
1260 
1261     /**
1262      * Draw attention to call controller's user that something changed by
1263      *  raising a Verify event
1264      */
1265     bool m_verifyEvent;
1266 
1267     /**
1268      * Timer used to raise verify events
1269      */
1270     SignallingTimer m_verifyTimer;
1271 
1272     /**
1273      * Controller location used when encoding Q.850 cause
1274      */
1275     String m_location;
1276 
1277     /**
1278      * Media required keywords
1279      */
1280     static const TokenDict s_mediaRequired[];
1281 
1282 private:
1283     SignallingCircuitGroup* m_circuits;  // Circuit group
1284     int m_strategy;                      // Strategy to allocate circuits for outgoing calls
1285     bool m_exiting;                      // Call control is terminating. Generate a Disable event when no more calls
1286 };
1287 
1288 /**
1289  * Interface of protocol independent phone call
1290  * @short Abstract single phone call
1291  */
1292 class YSIG_API SignallingCall : public RefObject, public Mutex
1293 {
1294 public:
1295     /**
1296      * Constructor
1297      * @param controller The call controller owning this call
1298      * @param outgoing Call direction (true for outgoing)
1299      * @param signalOnly Just signalling (no voice) flag
1300      */
1301     SignallingCall(SignallingCallControl* controller, bool outgoing, bool signalOnly = false);
1302 
1303     /**
1304      * Destructor, notifies the controller
1305      */
1306     virtual ~SignallingCall();
1307 
1308     /**
1309      * Check if this is an outgoing call
1310      * @return True if it's an outgoing call
1311      */
outgoing()1312     inline bool outgoing() const
1313 	{ return m_outgoing; }
1314 
1315     /**
1316      * Retreive the controller of this call
1317      */
controller()1318     inline SignallingCallControl* controller() const
1319 	{ return m_controller; }
1320 
1321     /**
1322      * Set this call's private user data
1323      * @param data New user data
1324      */
userdata(void * data)1325     inline void userdata(void* data)
1326 	{ m_private = data; }
1327 
1328     /**
1329      * Retreive the private user data of this call
1330      * @return User data
1331      */
userdata()1332     inline void* userdata() const
1333 	{ return m_private; }
1334 
1335     /**
1336      * Check if this call is just a signalling (no voice) one
1337      * @return True if no audio data can be negotiated for this call
1338      */
signalOnly()1339     inline bool signalOnly() const
1340 	{ return m_signalOnly; }
1341 
1342     /**
1343      * Check if this call is in overlapped send/recv state
1344      * @return True if this call is expecting more digits to be sent/received
1345      */
overlapDialing()1346     inline bool overlapDialing() const
1347 	{ return m_overlap; }
1348 
1349     /**
1350      * Send an event to this call
1351      * @param event The event to send
1352      * @return True if the operation succedded
1353      */
sendEvent(SignallingEvent * event)1354     virtual bool sendEvent(SignallingEvent* event)
1355 	{ return false; }
1356 
1357     /**
1358      * Get an event from this call if not already got one
1359      * This method is thread safe
1360      * @param when The current time
1361      * @return SignallingEvent pointer or 0 if no events or this call has a not terminated event
1362      */
1363     virtual SignallingEvent* getEvent(const Time& when) = 0;
1364 
1365     /**
1366      * Event terminated notification. No event will be generated until
1367      *  the current event is terminated
1368      * This method is thread safe
1369      * @param event The terminated event
1370      */
1371     virtual void eventTerminated(SignallingEvent* event);
1372 
1373 protected:
1374     /**
1375      * Enqueue a received message.
1376      * This method is thread safe
1377      * @param msg The received message
1378      */
1379     void enqueue(SignallingMessage* msg);
1380 
1381     /**
1382      * Dequeue a received message. Just return it if remove is false
1383      * This method is thread safe
1384      * @param remove True to remove the message from queue
1385      * @return SignallingMessage pointer or 0 if no more messages
1386      */
1387     SignallingMessage* dequeue(bool remove = true);
1388 
1389     /**
1390      * Clear incoming messages queue
1391      */
clearQueue()1392     void clearQueue()
1393     {
1394 	Lock lock(m_inMsgMutex);
1395 	m_inMsg.clear();
1396     }
1397 
1398     /**
1399      * Last event generated by this call. Used to serialize events
1400      */
1401     SignallingEvent* m_lastEvent;
1402 
1403     /**
1404      * Call is in overlapped send/recv state
1405      */
1406     bool m_overlap;
1407 
1408 private:
1409     SignallingCallControl* m_controller; // Call controller this call belongs to
1410     bool m_outgoing;                     // Call direction
1411     bool m_signalOnly;                   // Just signalling flag
1412     ObjList m_inMsg;                     // Incoming messages queue
1413     Mutex m_inMsgMutex;                  // Lock incoming messages queue
1414     void* m_private;                     // Private user data
1415 };
1416 
1417 /**
1418  * An object holding a signalling event and related references
1419  * @short A single signalling related event
1420  */
1421 class YSIG_API SignallingEvent
1422 {
1423 public:
1424     /**
1425      * Type of the event
1426      */
1427     enum Type {
1428 	Unknown = 0,
1429 	Generic,
1430 	// Call related
1431 	NewCall,
1432 	Accept,
1433 	Connect,
1434 	Complete,
1435 	Progress,
1436 	Ringing,
1437 	Answer,
1438 	Transfer,
1439 	Suspend,
1440 	Resume,
1441 	Release,
1442 	Info,
1443 	Charge,
1444 	// Non-call related
1445 	Message,
1446 	Facility,
1447 	Circuit,
1448 	// Controller related
1449 	Enable,
1450 	Disable,
1451 	Reset,
1452 	Verify,
1453     };
1454 
1455     /**
1456      * Constructor for a call related event
1457      * @param type Type of the event
1458      * @param message Message carried by the event
1459      * @param call Call this event refers to
1460      */
1461     SignallingEvent(Type type, SignallingMessage* message, SignallingCall* call);
1462 
1463     /**
1464      * Constructor for a controller related event
1465      * @param type Type of the event
1466      * @param message Message carried by the event
1467      * @param controller Controller this event refers to
1468      */
1469     SignallingEvent(Type type, SignallingMessage* message, SignallingCallControl* controller = 0);
1470 
1471     /**
1472      * Constructor for a signalling circuit related event
1473      * @param event The event signaled by the circuit, will be consumed and zeroed
1474      * @param call Call this event refers to
1475      */
1476     SignallingEvent(SignallingCircuitEvent*& event, SignallingCall* call);
1477 
1478     /**
1479      * Destructor, dereferences any resources, notify the signalling call of termination
1480      */
1481     virtual ~SignallingEvent();
1482 
1483     /**
1484      * Get the string associated with this event's type
1485      * @return The string associated with this event's type, if any
1486      */
name()1487     inline const char* name() const
1488 	{ return typeName(type()); }
1489 
1490     /**
1491      * Get the type of the event
1492      * @return Type of event, may be unknown
1493      */
type()1494     inline Type type() const
1495 	{ return m_type; }
1496 
1497     /**
1498      * Get the call that generated this event, may be NULL
1499      */
call()1500     inline SignallingCall* call() const
1501 	{ return m_call; }
1502 
1503     /**
1504      * Get the message that generated this event, may be NULL
1505      */
message()1506     inline SignallingMessage* message() const
1507 	{ return m_message; }
1508 
1509     /**
1510      * Retrieve the controller of the call
1511      */
controller()1512     inline SignallingCallControl* controller() const
1513 	{ return m_controller; }
1514 
1515     /**
1516      * Retrieve the circuit event
1517      */
cicEvent()1518     inline SignallingCircuitEvent* cicEvent() const
1519 	{ return m_cicEvent; }
1520 
1521     /**
1522      * Get the text associated with a given event type for debug purposes
1523      * @param t The requested type
1524      * @return The text associated with the given type
1525      */
typeName(Type t)1526     static inline const char* typeName(Type t)
1527 	{ return lookup(t,s_types,0); }
1528 
1529     /**
1530      * Send this event through the call that generated it
1531      * @return True if there was a call and the operation succedded
1532      */
1533     bool sendEvent();
1534 
1535 private:
1536     Type m_type;
1537     SignallingMessage* m_message;
1538     SignallingCall* m_call;
1539     SignallingCallControl* m_controller;
1540     SignallingCircuitEvent* m_cicEvent;
1541     static const TokenDict s_types[];
1542 };
1543 
1544 /**
1545  * An object holding a signalling circuit event and related references
1546  * @short A single signalling circuit related event
1547  */
1548 class YSIG_API SignallingCircuitEvent : public NamedList
1549 {
1550 public:
1551     /**
1552      * Type of the event
1553      */
1554     enum Type {
1555 	Unknown      = 0,
1556 	Dtmf         = 1,                // Transfer tones: param: tone
1557 	GenericTone  = 2,                // Play or detect tones: param: tone
1558 	// Analog line events
1559 	Timeout      = 10,               //
1560 	Polarity     = 11,               // Line's polarity changed
1561 	StartLine    = 15,               // Initialize FXO line
1562 	LineStarted  = 16,               // FXO line initialized: send number
1563 	DialComplete = 17,               // FXO line completed dialing the number
1564 	OnHook       = 20,               // The hook is down
1565 	OffHook      = 21,               // The hook is up
1566 	RingBegin    = 22,               // Start ringing
1567 	RingEnd      = 23,               // Stop ringing
1568 	RingerOn     = 30,               // An FXS started the FXO's ringer
1569 	RingerOff    = 31,               // An FXS stopped the FXO's ringer
1570 	Wink         = 32,               // On hook momentarily
1571 	Flash        = 33,               // Off hook momentarily
1572 	PulseStart   = 40,               // Pulse dialing start
1573 	PulseDigit   = 41,               // Transfer pulse digits: param: pulse
1574 	// Remote circuit events
1575 	Connect      = 50,               // Request connect
1576 	Disconnect   = 51,               // Request disconnect
1577 	Connected    = 52,               // Connected notification
1578 	Disconnected = 53,               // Disconnected notification
1579 	// Errors
1580 	Alarm        = 100,              // Param: alarms (comma separated list of strings)
1581 	NoAlarm      = 101,              // No more alarms
1582     };
1583 
1584     /**
1585      * Constructor for a circuit related event
1586      * @param cic The circuit that generated this event
1587      * @param type Event type as enumeration
1588      * @param name Optional name for the named list
1589      */
1590     SignallingCircuitEvent(SignallingCircuit* cic, Type type, const char* name = 0);
1591 
1592     /**
1593      * Destructor, dereferences any resources
1594      */
1595     virtual ~SignallingCircuitEvent();
1596 
1597     /**
1598      * Get the type of this event
1599      * @return The type of this event
1600      */
type()1601     inline Type type() const
1602 	{ return m_type; }
1603 
1604     /**
1605      * Get the circuit that generated this event
1606      * @return The circuit that generated this event
1607      */
circuit()1608     inline SignallingCircuit* circuit()
1609 	{ return m_circuit; }
1610 
1611     /**
1612      * Send this event through the circuit. Release (delete) the event
1613      * @return True if the operation succeded
1614      */
1615     bool sendEvent();
1616 
1617 private:
1618     SignallingCircuit* m_circuit;
1619     Type m_type;
1620 };
1621 
1622 /**
1623  * Interface to an abstract voice/data circuit referenced by signalling
1624  * @short Abstract data circuit used by signalling
1625  */
1626 class YSIG_API SignallingCircuit : public RefObject
1627 {
YCLASS(SignallingCircuit,RefObject)1628     YCLASS(SignallingCircuit,RefObject)
1629     friend class SignallingCircuitGroup;
1630     friend class SignallingCircuitEvent;
1631 public:
1632     /**
1633      * Type of the circuit hardware or transport
1634      */
1635     enum Type {
1636 	Unknown = 0,
1637 	Local, // not really a circuit
1638 	TDM,
1639 	RTP,
1640 	IAX,
1641     };
1642 
1643     /**
1644      * Status of the circuit
1645      */
1646     enum Status {
1647 	Missing = 0,
1648 	Disabled,
1649 	Idle,
1650 	Reserved,
1651 	Starting,
1652 	Stopping,
1653 	Special,
1654 	Connected,
1655     };
1656 
1657     /**
1658      * Lock circuit flags
1659      */
1660     enum LockFlags {
1661 	LockLocalHWFail       = 0x0001,  // Local side of the circuit is locked due to HW failure
1662 	LockLocalMaint        = 0x0002,  // Local side of the circuit is locked for maintenance
1663 	LockingHWFail         = 0x0004,  // Circuit (un)lock due to HW failure in progress
1664 	LockingMaint          = 0x0008,  // Circuit (un)lock due to maintenance in progress
1665 	LockLocalHWFailChg    = 0x0010,  // Local HW failure flag changed
1666 	LockLocalMaintChg     = 0x0020,  // Local maintenance flag changed
1667 	Resetting             = 0x0040,  // Circuit is beeing reset
1668 	LockRemoteHWFail      = 0x0100,  // Remote side of the circuit is locked due to HW failure
1669 	LockRemoteMaint       = 0x0200,  // Remote side of the circuit is locked for maintenance
1670 	LockRemoteHWFailChg   = 0x1000,  // Remote HW failure flag changed
1671 	LockRemoteMaintChg    = 0x2000,  // Remote maintenance flag changed
1672 	// Masks used to test lock conditions
1673 	LockLocal             = LockLocalHWFail | LockLocalMaint,
1674 	LockRemote            = LockRemoteHWFail | LockRemoteMaint,
1675 	LockLocked            = LockLocal | LockRemote,
1676 	LockBusy              = LockingHWFail | LockingMaint | Resetting,
1677 	LockLockedBusy        = LockLocked | LockBusy,
1678 	LockLocalChg          = LockLocalHWFailChg | LockLocalMaintChg,
1679 	LockRemoteChg         = LockRemoteHWFailChg | LockRemoteMaintChg,
1680 	LockChanged           = LockLocalChg | LockRemoteChg,
1681     };
1682 
1683     /**
1684      * Destructor. Clear event list
1685      */
1686     virtual ~SignallingCircuit();
1687 
1688     /**
1689      * Initiate a status transition
1690      * @param newStat Desired new status
1691      * @param sync Synchronous status change requested
1692      * @return True if status change has been initiated
1693      */
1694     virtual bool status(Status newStat, bool sync = false)
1695 	{ m_status = newStat; return true; }
1696 
1697     /**
1698      * Get the type of this circuit
1699      * @return Enumerated type of circuit
1700      */
type()1701     inline Type type() const
1702 	{ return m_type; }
1703 
1704     /**
1705      * Get the status of this circuit
1706      * @return Enumerated status of circuit
1707      */
status()1708     inline Status status() const
1709 	{ return m_status; }
1710 
1711     /**
1712      * Check if the given lock flags are set
1713      * @param flags The lock flags to check. -1 to check all flags
1714      * @return The lock flags of this circuit masked by the given flags
1715      */
1716     inline int locked(int flags = -1) const
1717 	{ return (m_lock & flags); }
1718 
1719     /**
1720      * Set the given lock flags of this circuit
1721      * @param flags The lock flags to set
1722      */
setLock(int flags)1723     inline void setLock(int flags)
1724 	{ m_lock |= flags; }
1725 
1726     /**
1727      * Reset the given lock flags of this circuit
1728      * @param flags The lock flags to reset
1729      */
resetLock(int flags)1730     inline void resetLock(int flags)
1731 	{ m_lock &= ~flags; }
1732 
1733     /**
1734      * Set the format of the data transported through this circuit
1735      * @param format The new data format
1736      * @param direction The direction to be updated. -1 means to the lower layer, 1 from the lower layer, 0 both directions
1737      * @return True if the operation succeedded (format changed)
1738      */
updateFormat(const char * format,int direction)1739     virtual bool updateFormat(const char* format, int direction)
1740 	{ return false; }
1741 
1742     /**
1743      * Set circuit data or trigger some action
1744      * @param param The data to update or the action to trigger
1745      * @param value The data value or action parameter
1746      * @return True on success
1747      */
setParam(const String & param,const String & value)1748     virtual bool setParam(const String& param, const String& value)
1749 	{ return false; }
1750 
1751     /**
1752      * Set circuit data from a list of parameters
1753      * @param params Parameter list to set in the circuit
1754      * @return True if all parameters were successfully set
1755      */
1756     virtual bool setParams(const NamedList& params);
1757 
1758     /**
1759      * Get circuit parameter
1760      * @param param The parameter to get
1761      * @param value The value of the parameter
1762      * @return True on success. False if the parameter doesn't exist
1763      */
getParam(const String & param,String & value)1764     virtual bool getParam(const String& param, String& value) const
1765 	{ return false; }
1766 
1767     /**
1768      * Get boolean circuit parameter
1769      * @param param The parameter to get
1770      * @param defValue The default returned value
1771      * @return Value from circuit, devValue if the parameter doesn't exist
1772      */
1773     virtual bool getBoolParam(const String& param, bool defValue = false) const
1774 	{ return defValue; }
1775 
1776     /**
1777      * Get integer circuit parameter
1778      * @param param The parameter to get
1779      * @param defValue The default returned value
1780      * @return Value from circuit, devValue if the parameter doesn't exist
1781      */
1782     virtual int getIntParam(const String& param, int defValue = 0) const
1783 	{ return defValue; }
1784 
1785     /**
1786      * Get circuit parameters
1787      * @param params Parameter list to fill from the circuit
1788      * @param category Optional category used to select desired parameters
1789      * @return True if handled
1790      */
1791     virtual bool getParams(NamedList& params, const String& category = String::empty())
1792 	{ return false; }
1793 
1794     /**
1795      * Get the group of circuits this one belongs to
1796      * @return Pointer to circuit group
1797      */
group()1798     inline SignallingCircuitGroup* group()
1799 	{ return m_group; }
1800 
1801     /**
1802      * Get the circuit span this one belongs to
1803      * @return Pointer to circuit span
1804      */
span()1805     inline SignallingCircuitSpan* span()
1806 	{ return m_span; }
1807 
1808     /**
1809      * Get the group of circuits this one belongs to - const version
1810      * @return Pointer to const circuit group
1811      */
group()1812     inline const SignallingCircuitGroup* group() const
1813 	{ return m_group; }
1814 
1815     /**
1816      * Get the circuit span this one belongs to - const version
1817      * @return Pointer to const circuit span
1818      */
span()1819     inline const SignallingCircuitSpan* span() const
1820 	{ return m_span; }
1821 
1822     /**
1823      * Get the group-local code of this circuit
1824      * @return Identification code within group
1825      */
code()1826     inline unsigned int code() const
1827 	{ return m_code; }
1828 
1829     /**
1830      * Get the available status of the circuit
1831      * @return True if the circuit is available for use
1832      */
available()1833     inline bool available() const
1834 	{ return m_status == Idle; }
1835 
1836     /**
1837      * Get the connected status of the circuit
1838      * @return True if the circuit is connected (in use)
1839      */
connected()1840     inline bool connected() const
1841 	{ return m_status == Connected; }
1842 
1843     /**
1844      * Reserve this circuit for later use
1845      * @return True if the circuit was changed from Idle to Reserved
1846      */
reserve()1847     inline bool reserve()
1848 	{ return available() && status(Reserved,true); }
1849 
1850     /**
1851      * Connect this circuit
1852      * @param format Optional data format to update for both directions
1853      * @return True if the circuit state was changed to Connected
1854      */
1855     inline bool connect(const char* format = 0)
1856 	{ updateFormat(format,0); return status(Connected,true); }
1857 
1858     /**
1859      * Disconnect (set state to Reserved) this circuit if connected
1860      * @return True if the circuit was changed from Connected to Reserved
1861      */
disconnect()1862     inline bool disconnect()
1863 	{ return status() == Connected && status(Reserved,true); }
1864 
1865     /**
1866      * Disable this circuit for maintenance
1867      * @return True if the circuit was changed from Idle to Reserved
1868      */
disable()1869     inline bool disable()
1870 	{ return status(Disabled,true); }
1871 
1872     /**
1873      * Set/reset HW failure lock flag
1874      * @param set True to set, false to reset the flag
1875      * @param remote True to use remote side of the circuit, false to use the local one
1876      * @param changed Set/reset changed flag. If false the changed flag won't be affected
1877      * @param setChanged The value of the changed flag. gnored if changed is false
1878      * @return True if the flag's state changed
1879      */
1880     bool hwLock(bool set, bool remote, bool changed = false, bool setChanged = false);
1881 
1882     /**
1883      * Set/reset maintenance lock flag
1884      * @param set True to set, false to reset the flag
1885      * @param remote True to use remote side of the circuit, false to use the local one
1886      * @param changed Set/reset changed flag. If false the changed flag won't be affected
1887      * @param setChanged The value of the changed flag. gnored if changed is false
1888      * @return True if the flag's state changed
1889      */
1890     bool maintLock(bool set, bool remote, bool changed = false, bool setChanged = false);
1891 
1892     /**
1893      * Add an event to the queue
1894      * This method is thread safe
1895      * @param event The event to enqueue
1896      */
1897     void addEvent(SignallingCircuitEvent* event);
1898 
1899     /**
1900      * Get an event from queue
1901      * This method is thread safe
1902      * @param when The current time
1903      * @return SignallingCircuitEvent pointer or 0 if no events
1904      */
1905     SignallingCircuitEvent* getEvent(const Time& when);
1906 
1907     /**
1908      * Send an event through this circuit
1909      * @param type The type of the event to send
1910      * @param params Optional event parameters
1911      * @return True on success
1912      */
1913     virtual bool sendEvent(SignallingCircuitEvent::Type type, NamedList* params = 0);
1914 
1915     /**
1916      * Get the text associated with a circuit type
1917      * @param type Circuit type used to retrieve the text
1918      * @return Pointer to the string associated with the given circuit type
1919      */
1920     static const char* lookupType(int type);
1921 
1922     /**
1923      * Get the text associated with a circuit status
1924      * @param status Circuit status used to retrieve the text
1925      * @return Pointer to the string associated with the given circuit status
1926      */
1927     static const char* lookupStatus(int status);
1928 
1929     /**
1930      * Keep the lock flags names
1931      */
1932     static const TokenDict s_lockNames[];
1933 
1934 protected:
1935     /**
1936      * Constructor
1937      */
1938     SignallingCircuit(Type type, unsigned int code, SignallingCircuitGroup* group = 0,
1939 	SignallingCircuitSpan* span = 0);
1940 
1941     /**
1942      * Constructor
1943      */
1944     SignallingCircuit(Type type, unsigned int code, Status status,
1945 	SignallingCircuitGroup* group = 0, SignallingCircuitSpan* span = 0);
1946 
1947     /**
1948      * Clear event queue
1949      * This method is thread safe
1950      */
1951     virtual void clearEvents();
1952 
1953     /**
1954      * Event termination notification
1955      * @param event The terminated event
1956      */
1957     void eventTerminated(SignallingCircuitEvent* event);
1958 
1959     /**
1960      * Circuit operations mutex
1961      */
1962     Mutex m_mutex;
1963 
1964 private:
1965     SignallingCircuitGroup* m_group;     // The group owning this circuit
1966     SignallingCircuitSpan* m_span;       // The span this circuit belongs to
1967     unsigned int m_code;                 // Circuit id
1968     Type m_type;                         // Circuit type (see enumeration)
1969     Status m_status;                     // Circuit local status
1970     int m_lock;                          // Circuit lock flags
1971     ObjList m_events;                    // In-band events
1972     SignallingCircuitEvent* m_lastEvent; // The last generated event
1973     bool m_noEvents;                     // No events pending, exit quickly
1974 };
1975 
1976 /**
1977  * Keeps a range (set) of circuits. The circuit codes contained within a range may
1978  *  not be contiguous.
1979  * See @ref SignallingUtils::parseUIntArray() for the format of the string ranges
1980  *  this object can be built from
1981  * @short A circuit range (set of circuits)
1982  */
1983 class YSIG_API SignallingCircuitRange : public String
1984 {
YCLASS(SignallingCircuitRange,String)1985     YCLASS(SignallingCircuitRange,String)
1986     friend class SignallingCircuitGroup;
1987 public:
1988     /**
1989      * Constructor
1990      * @param rangeStr String used to build this range
1991      * @param name Range name
1992      * @param strategy Strategy used to allocate circuits from this range
1993      */
1994     SignallingCircuitRange(const String& rangeStr, const char* name = 0,
1995 	int strategy = -1);
1996 
1997     /**
1998      * Destructor
1999      */
2000     virtual ~SignallingCircuitRange()
2001 	{ clear(); }
2002 
2003     /**
2004      * Get the number of circuits contained by this range
2005      * @return The number of circuits contained by this range
2006      */
count()2007     inline unsigned int count() const
2008 	{ return m_count; }
2009 
2010     /**
2011      * Get the pointer to the circuit codes array
2012      * @return Pointer to the circuit codes array or 0
2013      */
range()2014     inline const unsigned int* range() const
2015 	{ return (const unsigned int*)m_range.data(); }
2016 
2017     /**
2018      * Allocate and return an array containing range circuits
2019      * @param count Address of variable to be filled with circuit count
2020      * @return Pointer to allocated buffer, 0 if there is no circuit.
2021      *  The caller will own the returned buffer
2022      */
2023     unsigned int* copyRange(unsigned int& count) const;
2024 
2025     /**
2026      * Get the pointer to the circuit codes array
2027      * @return Pointer to the circuit codes array or 0
2028      */
clear()2029     inline void clear()
2030 	{ m_range.clear(); m_count = 0; }
2031 
2032     /**
2033      * Indexing operator
2034      * @param index The index in the array to retreive
2035      * @return The code at the given index
2036      */
2037     inline unsigned int operator[](unsigned int index)
2038 	{ return range()[index]; }
2039 
2040     /**
2041      * Set this range from a string
2042      * @param rangeStr String used to (re)build this range
2043      * @return False if the string has invalid format
2044      */
set(const String & rangeStr)2045     inline bool set(const String& rangeStr)
2046     {
2047 	clear();
2048 	return add(rangeStr);
2049     }
2050 
2051     /**
2052      * Add codes to this range from a string
2053      * @param rangeStr String containing the codes to be added to this range
2054      * @return False if the string has invalid format
2055      */
2056     bool add(const String& rangeStr);
2057 
2058     /**
2059      * Add an array of circuit codes to this range
2060      * @param codes The array to add
2061      * @param len The array's length
2062      */
2063     void add(unsigned int* codes, unsigned int len);
2064 
2065     /**
2066      * Add a circuit code to this range
2067      * @param code The circuit code to add
2068      */
add(unsigned int code)2069     inline void add(unsigned int code)
2070 	{ add(&code,1); }
2071 
2072     /**
2073      * Add a compact range of circuit codes to this range
2074      * @param first The first circuit code to add
2075      * @param last Number of last circuit code
2076      */
2077     void add(unsigned int first, unsigned int last);
2078 
2079     /**
2080      * Remove a circuit code from this range
2081      * @param code The circuit code to remove
2082      */
2083     void remove(unsigned int code);
2084 
2085     /**
2086      * Check if a circuit code is within this range
2087      * @param code The circuit code to find
2088      * @return True if found
2089      */
2090     bool find(unsigned int code);
2091 
2092     /**
2093      * Release memory
2094      */
destruct()2095     virtual void destruct()
2096     {
2097 	clear();
2098 	String::destruct();
2099     }
2100 
2101 protected:
2102     void updateLast();                   // Update last circuit code
2103 
2104     DataBlock m_range;                   // Array containing the circuit codes
2105     unsigned int m_count;                // The number of elements in the array
2106     unsigned int m_last;                 // Last (the greater) not used circuit code within this range
2107     int m_strategy;                      // Keep the strategy used to allocate circuits from this range
2108     unsigned int m_used;                 // Last used circuit code
2109 };
2110 
2111 /**
2112  * Interface to a stateful group of voice/data circuits
2113  * @short Group of data circuits used by signalling
2114  */
2115 class YSIG_API SignallingCircuitGroup : public SignallingComponent, public Mutex
2116 {
2117     YCLASS(SignallingCircuitGroup,SignallingComponent)
2118     friend class SignallingCircuit;
2119     friend class SignallingCallControl;
2120     friend class SS7ISUP;
2121     friend class ISDNQ931;
2122 public:
2123     /**
2124      * Circuit allocation strategy
2125      */
2126     enum Strategy {
2127 	Other     = 0,
2128 	// basic strategies
2129 	Increment = 0x0001, // round-robin, up
2130 	Decrement = 0x0002, // round-robin, down
2131 	Lowest    = 0x0003, // pick first available
2132 	Highest   = 0x0004, // pick last available
2133 	Random    = 0x0005, // pick random circuit
2134 	// even/odd strict select (glare avoidance)
2135 	OnlyEven  = 0x1000,
2136 	OnlyOdd   = 0x2000,
2137 	// glare avoidance with fallback (to be able to use all circuits)
2138 	Fallback  = 0x4000,
2139     };
2140 
2141     /**
2142      * Constructor, creates a group with a specific base code
2143      * @param base Base of identification codes for this group
2144      * @param strategy Default strategy used for circuit allocation
2145      * @param name Name of this component
2146      */
2147     SignallingCircuitGroup(unsigned int base = 0, int strategy = Increment,
2148 	const char* name = "circgroup");
2149 
2150     /**
2151      * Destructor
2152      */
2153     virtual ~SignallingCircuitGroup();
2154 
2155     /**
2156      * Get the number of circuits in this group
2157      * @return The number of circuits owned by this group
2158      */
count()2159     inline unsigned int count() const
2160 	{ return m_circuits.count(); }
2161 
2162     /**
2163      * Get the base of identification codes for this group
2164      * @return Base of identification codes for this group
2165      */
base()2166     inline unsigned int base() const
2167 	{ return m_base; }
2168 
2169     /**
2170      * Get the maximum of identification codes for this group
2171      * @return The maximum of identification codes for this group
2172      */
last()2173     inline unsigned int last() const
2174 	{ return m_range.m_last; }
2175 
2176     /**
2177      * Get the circuit allocation strategy
2178      * @return Strategy flags ORed together
2179      */
strategy()2180     inline int strategy() const
2181 	{ return m_range.m_strategy; }
2182 
2183     /**
2184      * Set the circuit allocation strategy
2185      * @param strategy The new circuit allocation strategy
2186      */
setStrategy(int strategy)2187     inline void setStrategy(int strategy)
2188 	{ Lock lock(this); m_range.m_strategy = strategy; }
2189 
2190     /**
2191      * Get the circuit list
2192      */
circuits()2193     inline ObjList& circuits()
2194 	{ return m_circuits; }
2195 
2196     /**
2197      * Create a comma separated list with this group's circuits
2198      * @param dest The destination string
2199      */
2200     void getCicList(String& dest);
2201 
2202     /**
2203      * Insert a circuit in the group
2204      * @param circuit Pointer to the circuit to insert
2205      * @return False if a circuit with the same code already exists
2206      */
2207     bool insert(SignallingCircuit* circuit);
2208 
2209     /**
2210      * Remove a circuit from the group
2211      * @param circuit Pointer to the circuit to remove
2212      */
2213     void remove(SignallingCircuit* circuit);
2214 
2215     /**
2216      * Create a circuit span using the factory
2217      * @param name Name of the span to create
2218      * @param start Desired start of circuit codes in span
2219      * @param params Optional parameters for creation of span and circuits
2220      * @return Pointer to new circuit span or NULL on failure
2221      */
2222     SignallingCircuitSpan* buildSpan(const String& name, unsigned int start = 0, NamedList* params = 0);
2223 
2224     /**
2225      * Insert a circuit span in the group
2226      * @param span Pointer to the circuit span to insert
2227      * @return False on failure
2228      */
2229     bool insertSpan(SignallingCircuitSpan* span);
2230 
2231     /**
2232      * Build and insert a range from circuits belonging to a given span
2233      * @param span Span to find
2234      * @param name Range name or 0 to use span's id
2235      * @param strategy Strategy used to allocate circuits from the new range,
2236      *  -1 to use group's strategy
2237      */
2238     void insertRange(SignallingCircuitSpan* span, const char* name,
2239 	int strategy = -1);
2240 
2241     /**
2242      * Build and insert a range contained in a string.
2243      * See @ref SignallingUtils::parseUIntArray() for the format of the string range
2244      * @param range String used to build the range
2245      * @param name Range name
2246      * @param strategy Strategy used to allocate circuits from the new range,
2247      *  -1 to use group's strategy
2248      */
2249     void insertRange(const String& range, const char* name,
2250 	int strategy = -1);
2251 
2252     /**
2253      * Remove a circuit span from the group
2254      * @param span Pointer to the circuit span to remove
2255      * @param delCics True to delete signalling circuits associated to the span
2256      * @param delSpan True to delete the span
2257      */
2258     void removeSpan(SignallingCircuitSpan* span, bool delCics = true, bool delSpan = false);
2259 
2260     /**
2261      * Remove signalling circuits associated to the given span
2262      * @param span Pointer to the circuit span whose circuits will be removed
2263      */
2264     void removeSpanCircuits(SignallingCircuitSpan* span);
2265 
2266     /**
2267      * Find a specific circuit by its identification code
2268      * @param cic Circuit Identification Code
2269      * @param local Interpret the cic parameter as group-local code
2270      * @return Pointer to circuit or NULL if not found
2271      */
2272     SignallingCircuit* find(unsigned int cic, bool local = false);
2273 
2274     /**
2275      * Find a range of circuits owned by this group
2276      * @param name The range name to find
2277      * @return Pointer to circuit range or 0 if not found
2278      */
2279     SignallingCircuitRange* findRange(const char* name);
2280 
2281     /**
2282      * Get the status of a circuit
2283      * @param cic Circuit Identification Code
2284      * @return Enumerated status of circuit
2285      */
2286     SignallingCircuit::Status status(unsigned int cic);
2287 
2288     /**
2289      * Initiate a circuit status transition
2290      * @param cic Circuit Identification Code
2291      * @param newStat Desired new status
2292      * @param sync Synchronous status change requested
2293      * @return True if status change has been initiated
2294      */
2295     bool status(unsigned int cic, SignallingCircuit::Status newStat, bool sync = false);
2296 
2297     /**
2298      * Reserve a circuit for later use
2299      * @param checkLock Lock flags to check. If the given lock flags are set, reservation will fail
2300      * @param strategy Strategy used for allocation, use group default if negative
2301      * @param range Range of circuits to allocate from. 0 to use group default
2302      * @return Referenced pointer to a reserved circuit or 0 on failure
2303      */
2304     SignallingCircuit* reserve(int checkLock = -1, int strategy = -1,
2305 	SignallingCircuitRange* range = 0);
2306 
2307     /**
2308      * Reserve a circuit for later use
2309      * @param list Comma separated list of circuits
2310      * @param mandatory The list is mandatory. If false and none of the circuits in
2311      *  the list are available, try to reserve a free one
2312      * @param checkLock Lock flags to check. If the given lock flags are set, reservation will fail
2313      * @param strategy Strategy used for allocation if failed to allocate one from
2314      *  the list, use group default if negative
2315      * @param range Range of circuits to allocate from. 0 to use group default
2316      * @return Referenced pointer to a reserved circuit or 0 on failure
2317      */
2318     SignallingCircuit* reserve(const String& list, bool mandatory,
2319 	int checkLock = -1, int strategy = -1, SignallingCircuitRange* range = 0);
2320 
2321     /**
2322      * Initiate a release of a circuit
2323      * @param cic Circuit to release
2324      * @param sync Synchronous release requested
2325      * @return True if the circuit release was initiated
2326      */
2327     inline bool release(SignallingCircuit* cic, bool sync = false)
2328 	{ return cic && cic->status(SignallingCircuit::Idle,sync); }
2329 
2330     /**
2331      * Get the strategy value associated with a given name
2332      * @param name Strategy name whose value we want to obtain
2333      * @param def Value to return if not found
2334      * @return The requested strategy value or the default one
2335      */
2336     static int str2strategy(const char* name, int def = Increment)
2337 	{ return lookup(name,s_strategy,def); }
2338 
2339     /**
2340      * Keep the strategy names
2341      */
2342     static const TokenDict s_strategy[];
2343 
2344 protected:
2345     /**
2346      * Remove all spans and circuits. Release object
2347      */
destroyed()2348     virtual void destroyed()
2349     {
2350 	clearAll();
2351 	SignallingComponent::destroyed();
2352     }
2353 
2354 private:
2355     unsigned int advance(unsigned int n, int strategy, SignallingCircuitRange& range);
2356     void clearAll();
2357 
2358     ObjList m_circuits;                  // The circuits belonging to this group
2359     ObjList m_spans;                     // The spans belonging to this group
2360     ObjList m_ranges;                    // Additional circuit ranges
2361     SignallingCircuitRange m_range;      // Range containing all circuits belonging to this group
2362     unsigned int m_base;
2363 };
2364 
2365 /**
2366  * An interface to a span belonging to a circuit group
2367  * @short A span in a circuit group
2368  */
2369 class YSIG_API SignallingCircuitSpan : public SignallingComponent
2370 {
2371     YCLASS(SignallingCircuitSpan,SignallingComponent)
2372 public:
2373     /**
2374      * Destructor. Remove from group's queue
2375      */
2376     virtual ~SignallingCircuitSpan();
2377 
2378     /**
2379      * Get the owner of this span
2380      * @return SignallingCircuitGroup pointer or 0
2381      */
group()2382     inline SignallingCircuitGroup* group() const
2383 	{ return m_group; }
2384 
2385     /**
2386       * Get this span's id
2387       * @return The id of this span
2388       */
id()2389     inline const String& id() const
2390 	{ return m_id; }
2391 
2392     /**
2393      * Get the increment in circuit numbers caused by this span
2394      * @return Circuit number increment for this span
2395      */
increment()2396     inline unsigned int increment() const
2397 	{ return m_increment; }
2398 
2399 protected:
2400     /**
2401      * Constructor
2402      * @param id Optional span id
2403      * @param group Optional circuit group owning the span's circuits
2404      */
2405     SignallingCircuitSpan(const char* id = 0, SignallingCircuitGroup* group = 0);
2406 
2407     /**
2408      * The owner of this span
2409      */
2410     SignallingCircuitGroup* m_group;
2411 
2412     /**
2413      * The increment in channel code caused by this span
2414      */
2415     unsigned int m_increment;
2416 
2417 private:
2418     String m_id;                         // Span's id
2419 };
2420 
2421 /**
2422  * An interface to an abstraction of a Layer 1 (hardware HDLC) interface
2423  * @short Abstract digital signalling interface (hardware access)
2424  */
2425 class YSIG_API SignallingInterface : virtual public SignallingComponent
2426 {
YCLASS(SignallingInterface,SignallingComponent)2427     YCLASS(SignallingInterface,SignallingComponent)
2428     friend class SignallingReceiver;
2429 public:
2430     /**
2431      * Interface control operations
2432      */
2433     enum Operation {
2434 	Specific  = 0,
2435 	EnableTx  = 0x01,
2436 	EnableRx  = 0x02,
2437 	Enable    = 0x03,
2438 	DisableTx = 0x04,
2439 	DisableRx = 0x08,
2440 	Disable   = 0x0c,
2441 	FlushTx   = 0x10,
2442 	FlushRx   = 0x20,
2443 	Flush     = 0x30,
2444 	QueryTx   = 0x40,
2445 	QueryRx   = 0x80,
2446 	Query     = 0xc0
2447     };
2448 
2449     /**
2450      * Interface generated notifications
2451      */
2452     enum Notification {
2453 	LinkUp = 0,
2454 	LinkDown,
2455 	HardwareError,
2456 	TxClockError,
2457 	RxClockError,
2458 	AlignError,
2459 	CksumError,
2460 	TxOversize,
2461 	RxOversize,
2462 	TxOverflow,
2463 	RxOverflow,
2464 	TxUnderrun,
2465 	RxUnderrun,
2466     };
2467 
2468     /**
2469      * Packet types
2470      */
2471     enum PacketType {
2472 	Unknown = 0,
2473 	SS7Fisu,
2474 	SS7Lssu,
2475 	SS7Msu,
2476 	Q921
2477     };
2478 
2479     /**
2480      * Constructor
2481      */
SignallingInterface()2482     inline SignallingInterface()
2483 	: m_recvMutex(true,"SignallingInterface::recv"), m_receiver(0)
2484 	{ }
2485 
2486     /**
2487      * Destructor, stops and detaches the interface
2488      */
2489     virtual ~SignallingInterface();
2490 
2491     /**
2492      * Attach a receiver to the interface. Detach from the old one if valid
2493      * @param receiver Pointer to receiver to attach
2494      */
2495     virtual void attach(SignallingReceiver* receiver);
2496 
2497     /**
2498      * Retrieve the signalling receiver attached to this interface
2499      * @return Pointer to attached receiver, NULL if none
2500      */
receiver()2501     inline SignallingReceiver* receiver() const
2502 	{ return m_receiver; }
2503 
2504     /**
2505      * Execute a control operation. Operations can enable, disable or flush
2506      *  the transmitter, receiver or both. The status (enabled/disabled) can
2507      *  be queried and also interface-specific operations can be executed.
2508      * @param oper Operation to execute
2509      * @param params Optional parameters for the operation
2510      * @return True if the command completed successfully, for query operations
2511      *  also indicates the interface is enabled and operational
2512      */
2513     virtual bool control(Operation oper, NamedList* params = 0);
2514 
2515     /**
2516      * Keeps the names associated with the notifications
2517      */
2518     static const TokenDict s_notifName[];
2519 
2520 protected:
2521     /**
2522      * Transmit a packet over the hardware interface
2523      * @param packet Packet data to send
2524      * @param repeat Continuously send a copy of the packet while no other
2525      *  data is available for transmission
2526      * @param type Type of the packet to send
2527      * @return True if the interface accepted the packet
2528      */
2529     virtual bool transmitPacket(const DataBlock& packet, bool repeat, PacketType type) = 0;
2530 
2531     /**
2532      * Push a valid received Signalling Packet up the protocol stack.
2533      * The starting and ending flags and any CRC are not part of the data.
2534      * @return True if packet was successfully delivered to the receiver
2535      */
2536     bool receivedPacket(const DataBlock& packet);
2537 
2538     /**
2539      * Generate a notification event to the attached receiver
2540      * @param event Notification event to be reported
2541      * @return True if notification was accepted by the receiver
2542      */
2543     bool notify(Notification event);
2544 
2545 private:
2546     Mutex m_recvMutex;                   // Lock receiver pointer operations
2547     SignallingReceiver* m_receiver;
2548 };
2549 
2550 /**
2551  * An interface to an abstraction of a Layer 2 packet data receiver
2552  * @short Abstract Layer 2 packet data receiver
2553  */
2554 class YSIG_API SignallingReceiver : virtual public SignallingComponent
2555 {
2556     YCLASS(SignallingReceiver,SignallingComponent)
2557     friend class SignallingInterface;
2558 public:
2559     /**
2560      * Constructor
2561      * @param name Name of the component to create
2562      */
2563     SignallingReceiver(const char* name = 0);
2564 
2565     /**
2566      * Destructor, stops the interface and detaches from it
2567      */
2568     virtual ~SignallingReceiver();
2569 
2570     /**
2571      * Attach a hardware interface to the data link. Detach from the old one if valid
2572      * @param iface Pointer to interface to attach
2573      * @return Pointer to old attached interface or NULL
2574      */
2575     virtual SignallingInterface* attach(SignallingInterface* iface);
2576 
2577     /**
2578      * Retrieve the interface used by this receiver
2579      * @return Pointer to the attached interface or NULL
2580      */
iface()2581     inline SignallingInterface* iface() const
2582 	{ return m_interface; }
2583 
2584     /**
2585      * Execute a control operation on the attached interface.
2586      * @param oper Operation to execute
2587      * @param params Optional parameters for the operation
2588      * @return True if the command completed successfully, for query operations
2589      *  also indicates the interface is enabled and operational
2590      */
2591     bool control(SignallingInterface::Operation oper, NamedList* params = 0);
2592 
2593 protected:
2594     /**
2595      * Send a packet to the attached interface for transmission
2596      * @param packet Packet data to send
2597      * @param repeat Continuously send a copy of the packet while no other
2598      *  data is available for transmission
2599      * @param type Type of the packet to send
2600      * @return True if the interface accepted the packet
2601      */
2602     bool transmitPacket(const DataBlock& packet, bool repeat,
2603 	SignallingInterface::PacketType type = SignallingInterface::Unknown);
2604 
2605     /**
2606      * Process a Signalling Packet received by the interface
2607      * @return True if message was successfully processed
2608      */
2609     virtual bool receivedPacket(const DataBlock& packet) = 0;
2610 
2611     /**
2612      * Process a notification generated by the attached interface
2613      * @param event Notification event reported by the interface
2614      * @return True if notification was processed
2615      */
2616     virtual bool notify(SignallingInterface::Notification event);
2617 
2618 private:
2619     Mutex m_ifaceMutex;                  // Lock interface pointer operations
2620     SignallingInterface* m_interface;
2621 };
2622 
2623 
2624 /**
2625  * This class keeps a description of a parameter flag used to encode/decode flags
2626  * @short Description of parameter flags
2627  */
2628 struct SignallingFlags
2629 {
2630     /**
2631      * Mask to separate the relevant bits
2632      */
2633     unsigned int mask;
2634 
2635     /**
2636      * Actual value to match
2637      */
2638     unsigned int value;
2639 
2640     /**
2641      * Name of the flag
2642      */
2643     const char* name;
2644 };
2645 
2646 /**
2647  * Provides data and services for SS7 and ISDN
2648  * @short Library wide services and data provider
2649  */
2650 class YSIG_API SignallingUtils
2651 {
2652 public:
2653     /**
2654      * Retreive the dictionary keeping the coding standard flags of ISUP and ISDN parameters as defined in Q.850
2655      * @return Pointer to the coding standards dictionary
2656      */
2657     static const TokenDict* codings();
2658 
2659     /**
2660      * Retreive the dictionary keeping the location flags of ISUP and ISDN parameters as defined in Q.850
2661      * @return Pointer to the locations dictionary
2662      */
2663     static const TokenDict* locations();
2664 
2665     /**
2666      * Retreive a dictionary given by index and coding standard for ISUP and ISDN parameters
2667      * @param index The desired disctionary:
2668      *  0: The release causes of ISUP and ISDN calls as defined in Q.850.
2669      *  1: The formats negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
2670      *  2: The transfer capability negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
2671      *  3: The transfer mode negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
2672      *  4: The transfer rate negotiated in ISDN and ISUP parameters as defined in Q.931/Q.763.
2673      * @param coding Optional coding standard. Defaults to CCITT if 0
2674      * @return Pointer to the requested dictionary or 0
2675      */
2676     static inline const TokenDict* dict(unsigned int index, unsigned char coding = 0)
2677     {
2678 	if (index > 4)
2679 	    return 0;
2680 	return (!coding ? s_dictCCITT[index] : 0);
2681     }
2682 
2683     /**
2684      * Check if a comma separated list of flags has a given flag
2685      * @param flags The list of flags
2686      * @param flag The flag to check
2687      * @return True if the given flag is found
2688      */
2689     static bool hasFlag(const String& flags, const char* flag);
2690 
2691     /**
2692      * Append a flag to a comma separated list of flags if it doesn't exist
2693      * @param flags The list of flags
2694      * @param flag The flag to add
2695      * @return True if the given flag was not found but added
2696      */
2697     static bool appendFlag(String& flags, const char* flag);
2698 
2699     /**
2700      * Remove a flag from a comma separated list of flags
2701      * @param flags The list of flags
2702      * @param flag The flag to remove
2703      * @return True if the given flag was found and removed
2704      */
2705     static bool removeFlag(String& flags, const char* flag);
2706 
2707     /**
2708      * Check if a list's parameter (comma separated list of flags) has a given flag
2709      * @param list The parameter list
2710      * @param param The parameter to check
2711      * @param flag The flag to check
2712      * @return True if the given flag is found
2713      */
2714     static bool hasFlag(const NamedList& list, const char* param, const char* flag);
2715 
2716     /**
2717      * Append a flag to a list parameter (comma separated list), craete parameter if missing
2718      * @param list The parameter list
2719      * @param param The parameter to append to
2720      * @param flag The flag to add
2721      * @return True if the given flag was not found but added
2722      */
2723     static bool appendFlag(NamedList& list, const char* param, const char* flag);
2724 
2725     /**
2726      * Add string (keyword) if found in a dictionary or integer parameter to a named list
2727      * @param list Destination list
2728      * @param param Parameter to add to the list
2729      * @param tokens The dictionary used to find the given value
2730      * @param val The value to find/add to the list
2731      */
2732     static void addKeyword(NamedList& list, const char* param,
2733 	const TokenDict* tokens, unsigned int val);
2734 
2735     /**
2736      * Dump a buffer to a list of parameters
2737      * @param comp Signalling component requesting the service. Used to print debug messages
2738      * @param list The destination list
2739      * @param param Parameter to add to the list
2740      * @param buf The buffer containing the data to dump
2741      * @param len Buffer's length
2742      * @param sep The separator between elements
2743      */
2744     static void dumpData(const SignallingComponent* comp, NamedList& list, const char* param,
2745 	const unsigned char* buf, unsigned int len, char sep = ' ');
2746 
2747     /**
2748      * Dump data from a buffer to a list of parameters. The buffer is parsed until (and including)
2749      *  the first byte with the extension bit (the most significant one) set
2750      * @param comp Signalling component requesting the service. Used to print debug messages
2751      * @param list The destination list
2752      * @param param Parameter to add to the list
2753      * @param buf The buffer containing the data to dump
2754      * @param len Buffer's length
2755      * @param sep The separator between elements
2756      * @return The number of bytes processed. 0 if the end of the buffer was reached without finding
2757      *  a byte with the extension bit set
2758      */
2759     static unsigned int dumpDataExt(const SignallingComponent* comp, NamedList& list, const char* param,
2760 	const unsigned char* buf, unsigned int len, char sep = ' ');
2761 
2762     /**
2763      * Decode a received buffer to a comma separated list of flags and add it to a list of parameters
2764      * @param comp Signalling component requesting the service. Used to print debug messages
2765      * @param list The destination list
2766      * @param param The parameter to add to the list
2767      * @param flags The flags description to use
2768      * @param buf The buffer containing the data to parse
2769      * @param len Buffer's length
2770      * @return False if the flags description or the buffer is missing or the buffer's length exceeds
2771      *  the length of the 'unsigned int' data type
2772      */
2773     static bool decodeFlags(const SignallingComponent* comp, NamedList& list, const char* param,
2774 	const SignallingFlags* flags, const unsigned char* buf, unsigned int len);
2775 
2776     /**
2777      * Decode cause parameters as defined in Q.850
2778      * @param comp Signalling component requesting the service. Used to print debug messages
2779      * @param list The destination list
2780      * @param buf The buffer containing the data to parse
2781      * @param len Buffer's length
2782      * @param prefix The prefix to add to the fields before adding to the destination list
2783      * @param isup True if the requestor is ISUP, false for ISDN requestor
2784      * @return True if successfully parsed
2785      */
2786     static bool decodeCause(const SignallingComponent* comp, NamedList& list, const unsigned char* buf,
2787 	unsigned int len, const char* prefix, bool isup);
2788 
2789     /**
2790      * Decode bearer capabilities as defined in Q.931 (Bearer Capabilities) and Q.763 (User Service Information)
2791      * @param comp Signalling component requesting the service. Used to print debug messages
2792      * @param list The destination list
2793      * @param buf The buffer containing the data to parse
2794      * @param len Buffer's length
2795      * @param prefix The prefix to add to the fields before adding to the destination list
2796      * @param isup True if the requestor is ISUP, false for ISDN requestor
2797      * @return True if successfully parsed
2798      */
2799     static bool decodeCaps(const SignallingComponent* comp, NamedList& list, const unsigned char* buf,
2800 	unsigned int len, const char* prefix, bool isup);
2801 
2802     /**
2803      * Encode a comma separated list of flags. Flags can be prefixed with the '-'
2804      *  character to be reset if previously set
2805      * @param comp Signalling component requesting the service. Used to print debug messages
2806      * @param dest Destination flak mask
2807      * @param flags The flag list
2808      * @param dict Dictionary used to retrieve the flag names and values
2809      * @return The OR'd value of found flags
2810      */
2811     static void encodeFlags(const SignallingComponent* comp, int& dest, const String& flags,
2812 	const TokenDict* dict);
2813 
2814     /**
2815      * Encode a comma separated list of signalling flags
2816      * @param comp Signalling component requesting the service. Used to print debug messages
2817      * @param flags The flag list
2818      * @param dict Signalling flags used to retrieve the flag names and values
2819      * @param paramName Optional flags parameter name used for debug purposes
2820      * @return The OR'd value of found flags
2821      */
2822     static unsigned int encodeFlags(const SignallingComponent* comp, const String& flags,
2823 	const SignallingFlags* dict, const char* paramName = 0);
2824 
2825     /**
2826      * Encode cause parameters as defined in Q.850. Create with normal clearing value if parameter is missing.
2827      * Don't encode diagnostic if total length exceeds 32 bytes for Q.931 requestor
2828      * @param comp Signalling component requesting the service. Used to print debug messages
2829      * @param buf The destination buffer
2830      * @param params The list with the parameters
2831      * @param prefix The prefix of the fields obtained from parameter list
2832      * @param isup True if the requestor is ISUP, false for ISDN requestor
2833      * @param fail Fail if the buffer is too long. Ignored if isup is true
2834      * @return False if the requestor is Q.931, fail is true and the length exceeds 32 bytes
2835      */
2836     static bool encodeCause(const SignallingComponent* comp, DataBlock& buf, const NamedList& params,
2837 	const char* prefix, bool isup, bool fail = false);
2838 
2839     /**
2840      * Encode bearer capabilities as defined in Q.931 (Bearer Capabilities) and Q.763 (User Service Information)
2841      * @param comp Signalling component requesting the service. Used to print debug messages
2842      * @param buf The destination buffer
2843      * @param params The list with the parameters
2844      * @param prefix The prefix of the fields obtained from parameter list
2845      * @param isup True if the requestor is ISUP, false for ISDN requestor
2846      * @return True
2847      */
2848     static bool encodeCaps(const SignallingComponent* comp, DataBlock& buf, const NamedList& params,
2849 	const char* prefix, bool isup);
2850 
2851     /**
2852      * Parse a list of unsigned integers or unsigned integer intervals. Source elements
2853      *  must be separated by a '.' or ',' character. Interval margins must be separated
2854      *  by a '-' character. Empty elements are ignored
2855      * @param source The string to parse
2856      * @param minVal The minimum value for each element in the array
2857      * @param maxVal The maximum value for each element in the array
2858      * @param count On exit will contain the length of the returned array (0 on failure)
2859      * @param discardDup True to discard duplicate values
2860      * @return Pointer to an array of unsigned integers on success (the caller must delete it after use).
2861      *  0 on failure (source is empty or has invalid format or an invalid value was found)
2862      */
2863     static unsigned int* parseUIntArray(const String& source, unsigned int minVal, unsigned int maxVal,
2864 	unsigned int& count, bool discardDup);
2865 
2866 private:
2867     static const TokenDict* s_dictCCITT[5];
2868 };
2869 
2870 /**
2871  * This class holds a signalling message along with timeout value(s)
2872  * @short A pending signalling message
2873  */
2874 class YSIG_API SignallingMessageTimer : public GenObject, public SignallingTimer
2875 {
2876 public:
2877     /**
2878      * Constructor
2879      * @param interval Operation timeout interval
2880      * @param global Operation global timeout interval
2881      */
2882     inline SignallingMessageTimer(u_int64_t interval, u_int64_t global = 0)
SignallingTimer(interval)2883 	: SignallingTimer(interval),
2884 	  m_globalTimer(global), m_msg(0)
2885 	{ }
2886 
2887     /**
2888      * Destructor. Release data
2889      */
~SignallingMessageTimer()2890     virtual ~SignallingMessageTimer()
2891 	{ TelEngine::destruct(m_msg); }
2892 
2893     /**
2894      * Retrieve stored signaling message
2895      * @return Pointer to the stored message
2896      */
message()2897     inline SignallingMessage* message() const
2898 	{ return m_msg; }
2899 
2900     /**
2901      * Set a new message
2902      * @param msg Message to store in the timer
2903      */
message(SignallingMessage * msg)2904     inline void message(SignallingMessage* msg)
2905 	{ m_msg = msg; }
2906 
2907 
2908     /**
2909      * Get access to the global timer
2910      * @return A reference to the global timer
2911      */
global()2912     inline SignallingTimer& global()
2913 	{ return m_globalTimer; }
2914 
2915     /**
2916      * Get const access to the global timer
2917      * @return A const reference to the global timer
2918      */
global()2919     inline const SignallingTimer& global() const
2920 	{ return m_globalTimer; }
2921 
2922     /**
2923      * Get the time this message timer will timeout
2924      * @return The time this message timer will timeout
2925      */
fireTime()2926     inline u_int64_t fireTime() const {
2927 	if (!m_globalTimer.started() || m_globalTimer.fireTime() > SignallingTimer::fireTime())
2928 	    return SignallingTimer::fireTime();
2929 	return m_globalTimer.fireTime();
2930     }
2931 
2932 protected:
2933     SignallingTimer m_globalTimer;
2934     SignallingMessage* m_msg;
2935 };
2936 
2937 /**
2938  * This class holds pending signalling messages.
2939  * The list will keep objects in timeout ascending order
2940  * @short A pending signalling message list
2941  */
2942 class YSIG_API SignallingMessageTimerList : public ObjList
2943 {
2944 public:
2945     /**
2946      * Constructor
2947      */
SignallingMessageTimerList()2948     inline SignallingMessageTimerList()
2949 	{ }
2950 
2951     /**
2952      * Add a pending operation to the list. Start its timer
2953      * @param interval Operation timeout interval
2954      * @param when Current time
2955      * @return Added operation or 0 on failure
2956      */
2957     inline SignallingMessageTimer* add(u_int64_t interval, const Time& when = Time())
2958 	{ return interval ? add(new SignallingMessageTimer(interval),when) : 0; }
2959 
2960     /**
2961      * Add a pending operation to the list. Start its timer
2962      * @param m The Message Timer to add to the pending list
2963      * @param when Current time
2964      * @return Added message
2965      */
2966     SignallingMessageTimer* add(SignallingMessageTimer* m, const Time& when = Time());
2967 
2968     /**
2969      * Check if the first operation timed out. Remove it from list before returning it
2970      * @param when Current time
2971      * @return SignallingMessageTimer pointer or 0 if no timeout occured
2972      */
2973     SignallingMessageTimer* timeout(const Time& when = Time());
2974 };
2975 
2976 /**
2977  * This class is used to manage an analog line and keep data associated with it.
2978  * Also it can be used to monitor a pair of FXS/FXO analog lines
2979  * @short An analog line
2980  */
2981 class YSIG_API AnalogLine : public RefObject, public Mutex
2982 {
YCLASS(AnalogLine,RefObject)2983     YCLASS(AnalogLine,RefObject)
2984     friend class AnalogLineGroup;        // Reset group if destroyed before the line
2985 public:
2986     /**
2987      * Line type enumerator
2988      */
2989     enum Type {
2990 	FXO,                             // Telephone linked to an exchange
2991 	FXS,                             // Telephone exchange linked to a telephone
2992 	Recorder,                        // Passive FXO recording a 2 wire line
2993 	Monitor,                         // Monitor (a pair of FXS/FXO lines)
2994 	Unknown
2995     };
2996 
2997     /**
2998      * Line state enumeration
2999      */
3000     enum State {
3001 	OutOfService   = -1,             // Line is out of service
3002 	Idle           = 0,              // Line is idle (on hook)
3003 	Dialing        = 1,              // FXS line is waiting for the FXO to dial the number
3004 	DialComplete   = 2,              // FXS line: got enough digits from the FXO to reach a destination
3005 	Ringing        = 3,              // Line is ringing
3006 	Answered       = 4,              // Line is answered
3007 	CallEnded      = 5,              // FXS line: notify the FXO on call termination
3008 	OutOfOrder     = 6,              // FXS line: notify the FXO that the hook is off after call ended notification
3009     };
3010 
3011     /**
3012      * Call setup (such as Caller ID) management (send and detect)
3013      */
3014     enum CallSetupInfo {
3015 	After,                           // Send/detect call setup after the first ring
3016 	Before,                          // Send/detect call setup before the first ring
3017 	NoCallSetup                      // No call setup detect or send
3018     };
3019 
3020     /**
3021      * Constructor. Reserve the line's circuit. Connect it if requested. Creation will fail if no group,
3022      *  circuit, caller or the circuit is already allocated for another line in the group
3023      * @param grp The group owning this analog line
3024      * @param cic The code of the signalling circuit used this line
3025      * @param params The line's parameters
3026      */
3027     AnalogLine(AnalogLineGroup* grp, unsigned int cic, const NamedList& params);
3028 
3029     /**
3030      * Destructor
3031      */
3032     virtual ~AnalogLine();
3033 
3034     /**
3035      * Get this line's type
3036      * @return The line type as enumeration
3037      */
type()3038     inline Type type() const
3039 	{ return m_type; }
3040 
3041     /**
3042      * Get the line state
3043      * @return The line state as enumeration
3044      */
state()3045     inline State state() const
3046 	{ return m_state; }
3047 
3048     /**
3049      * Get the group owning this line
3050      * @return The group owning this line
3051      */
group()3052     inline AnalogLineGroup* group()
3053 	{ return m_group; }
3054 
3055     /**
3056      * Get this line's peer if belongs to a pair of monitored lines
3057      * @return This line's peer if belongs to a pair of monitored lines
3058      */
getPeer()3059     inline AnalogLine* getPeer()
3060 	{ return m_peer; }
3061 
3062     /**
3063      * Remove old peer's peer. Set this line's peer
3064      * @param line This line's peer
3065      * @param sync True to synchronize (set/reset) with the old peer
3066      */
3067     void setPeer(AnalogLine* line = 0, bool sync = true);
3068 
3069     /**
3070      * Get the line's circuit
3071      * @return SignallingCircuit pointer or 0 if no circuit was attached to this line
3072      */
circuit()3073     inline SignallingCircuit* circuit()
3074 	{ return m_circuit; }
3075 
3076     /**
3077      * Get the line address: group_name/circuit_number
3078      * @return The line address
3079      */
address()3080     inline const char* address() const
3081 	{ return m_address; }
3082 
3083     /**
3084      * Check if allowed to send outband DTMFs (DTMF events)
3085      * @return True if allowed to send outband DTMFs
3086      */
outbandDtmf()3087     inline bool outbandDtmf() const
3088 	{ return !m_inband; }
3089 
3090     /**
3091      * Check if the line should be answered on polarity change
3092      * @return True if the line should be answered on polarity change
3093      */
answerOnPolarity()3094     inline bool answerOnPolarity() const
3095 	{ return m_answerOnPolarity; }
3096 
3097     /**
3098      * Check if the line should be hanged up on polarity change
3099      * @return True if the line should be hanged up on polarity change
3100      */
hangupOnPolarity()3101     inline bool hangupOnPolarity() const
3102 	{ return m_hangupOnPolarity; }
3103 
3104     /**
3105      * Check if the line polarity change should be used
3106      * @return True if the line polarity change should be used
3107      */
polarityControl()3108     inline bool polarityControl() const
3109 	{ return m_polarityControl; }
3110 
3111     /**
3112      * Check if the line is processing (send/receive) the setup info (such as caller id) and when it does it
3113      * @return Call setup info processing as enumeration
3114      */
callSetup()3115     inline CallSetupInfo callSetup() const
3116 	{ return m_callSetup; }
3117 
3118     /**
3119      * Get the time allowed to ellapse between the call setup data and the first ring
3120      * @return The time allowed to ellapse between the call setup data and the first ring
3121      */
callSetupTimeout()3122     inline u_int64_t callSetupTimeout() const
3123 	{ return m_callSetupTimeout; }
3124 
3125     /**
3126      * Get the time allowed to ellapse without receiving a ring on incoming calls
3127      * @return The time allowed to ellapse without receiving a ring on incoming calls
3128      */
noRingTimeout()3129     inline u_int64_t noRingTimeout() const
3130 	{ return m_noRingTimeout; }
3131 
3132     /**
3133      * Get the time allowed to stay in alarm. This option can be used by the clients to terminate an active call
3134      * @return The time allowed to stay in alarm
3135      */
alarmTimeout()3136     inline u_int64_t alarmTimeout() const
3137 	{ return m_alarmTimeout; }
3138 
3139     /**
3140      * Get the time delay of dialing the called number
3141      * @return The time delay of dialing the called number
3142      */
delayDial()3143     inline u_int64_t delayDial() const
3144 	{ return m_delayDial; }
3145 
3146     /**
3147      * Set/reset accept pulse digits flag
3148      * @param ok True to accept incoming pulse digits, false to ignore them
3149      */
acceptPulseDigit(bool ok)3150     inline void acceptPulseDigit(bool ok)
3151 	{ m_acceptPulseDigit = ok; }
3152 
3153     /**
3154      * Get the private user data of this line
3155      * @return The private user data of this line
3156      */
userdata()3157     inline void* userdata() const
3158 	{ return m_private; }
3159 
3160     /**
3161      * Set the private user data of this line and its peer if any
3162      * @param data The new private user data value of this line
3163      * @param sync True to synchronize (set data) with the peer
3164      */
3165     inline void userdata(void* data, bool sync = true)
3166     {
3167 	Lock lock(this);
3168 	m_private = data;
3169 	if (sync && m_peer)
3170 	    m_peer->userdata(data,false);
3171     }
3172 
3173     /**
3174      * Get this line's address
3175      * @return This line's address
3176      */
toString()3177     virtual const String& toString() const
3178 	{ return m_address; }
3179 
3180     /**
3181      * Reset the line circuit's echo canceller to line default echo canceller state
3182      * @param train Start echo canceller training if enabled
3183      */
3184     void resetEcho(bool train);
3185 
3186     /**
3187      * Reset the line's circuit (change its state to Reserved)
3188      * @return True if the line's circuit state was changed to Reserved
3189      */
resetCircuit()3190     inline bool resetCircuit()
3191 	{ return state() != OutOfService && m_circuit && m_circuit->reserve(); }
3192 
3193     /**
3194      * Set a parameter of this line's circuit
3195      * @param param Parameter name
3196      * @param value Optional parameter value
3197      * @return True if the line's circuit parameter was set
3198      */
3199     inline bool setCircuitParam(const char* param, const char* value = 0)
3200 	{ return m_circuit && m_circuit->setParam(param,value); }
3201 
3202     /**
3203      * Connect the line's circuit. Reset line echo canceller
3204      * @param sync True to synchronize (connect) the peer
3205      * @return True if the line's circuit state was changed to Connected
3206      */
3207     bool connect(bool sync);
3208 
3209     /**
3210      * Disconnect the line's circuit. Reset line echo canceller
3211      * @param sync True to synchronize (disconnect) the peer
3212      * @return True if the line's circuit was disconnected (changed state from Connected to Reserved)
3213      */
3214     bool disconnect(bool sync);
3215 
3216     /**
3217      * Send an event through this line if not out of service
3218      * @param type The type of the event to send
3219      * @param params Optional event parameters
3220      * @return True on success
3221      */
3222     bool sendEvent(SignallingCircuitEvent::Type type, NamedList* params = 0);
3223 
3224     /**
3225      * Send an event through this line if not out of service and change its state on success
3226      * @param type The type of the event to send
3227      * @param newState The new state of the line if the event was sent
3228      * @param params Optional event parameters
3229      * @return True on success
3230      */
3231     inline bool sendEvent(SignallingCircuitEvent::Type type, State newState,
3232 	NamedList* params = 0)
3233     {
3234 	if (!sendEvent(type,params))
3235 	    return false;
3236 	changeState(newState,false);
3237 	return true;
3238     }
3239 
3240     /**
3241      * Get events from the line's circuit if not out of service. Check timeouts
3242      * @param when The current time
3243      * @return AnalogLineEvent pointer or 0 if no events
3244      */
3245     virtual AnalogLineEvent* getEvent(const Time& when);
3246 
3247     /**
3248      * Alternate get events from this line or peer
3249      * @param when The current time
3250      * @return AnalogLineEvent pointer or 0 if no events
3251      */
3252     virtual AnalogLineEvent* getMonitorEvent(const Time& when);
3253 
3254     /**
3255      * Check timeouts if the line is not out of service and no event was generated by the circuit
3256      * @param when Time to use as computing base for timeouts
3257      */
checkTimeouts(const Time & when)3258     virtual void checkTimeouts(const Time& when)
3259 	{ }
3260 
3261     /**
3262      * Change the line state if neither current or new state are OutOfService
3263      * @param newState The new state of the line
3264      * @param sync True to synchronize (change state) the peer
3265      * @return True if line state changed
3266      */
3267     bool changeState(State newState, bool sync = false);
3268 
3269     /**
3270      * Enable/disable line. Change circuit's state to Disabled/Reserved when
3271      *  entering/exiting the OutOfService state
3272      * @param ok Enable (change state to Idle) or disable (change state to OutOfService) the line
3273      * @param sync True to synchronize (enable/disable) the peer
3274      * @param connectNow Connect the line if enabled. Ignored if the line will be disabled
3275      * @return True if line state changed
3276      */
3277     bool enable(bool ok, bool sync, bool connectNow = true);
3278 
3279     /**
3280      * Line type names dictionary
3281      */
3282     static const TokenDict* typeNames();
3283 
3284     /**
3285      * Line state names dictionary
3286      */
3287     static const TokenDict* stateNames();
3288 
3289     /**
3290      * Call setup info names
3291      */
3292     static const TokenDict* csNames();
3293 
3294 protected:
3295     /**
3296      * Deref the circuit. Remove itself from group
3297      */
3298     virtual void destroyed();
3299 
3300 private:
3301     Type m_type;                               // Line type
3302     State m_state;                             // Line state
3303     bool m_inband;                             // Refuse to send DTMFs if they should be sent in band
3304     int m_echocancel;                          // Default echo canceller state (0: managed by the circuit, -1: off, 1: on)
3305     bool m_acceptPulseDigit;                   // Accept incoming pulse digits
3306     bool m_answerOnPolarity;                   // Answer on line polarity change
3307     bool m_hangupOnPolarity;                   // Hangup on line polarity change
3308     bool m_polarityControl;                    // Set line polarity flag
3309     CallSetupInfo m_callSetup;                 // Call setup management
3310     u_int64_t m_callSetupTimeout;              // FXO: timeout period for received call setup data before first ring
3311     u_int64_t m_noRingTimeout;                 // FXO: timeout period with no ring received on incoming calls
3312     u_int64_t m_alarmTimeout;                  // Timeout period to stay in alarms
3313     u_int64_t m_delayDial;                     // FXO: Time to delay sending number
3314     AnalogLineGroup* m_group;                  // The group owning this line
3315     SignallingCircuit* m_circuit;              // The circuit managed by this line
3316     String m_address;                          // Line address: group and circuit
3317     void* m_private;                           // Private data used by this line's user
3318     // Monitor data
3319     AnalogLine* m_peer;                        // This line's peer if any
3320     bool m_getPeerEvent;                       // Flag used to get events from peer
3321 };
3322 
3323 /**
3324  * An object holding an event generated by an analog line and related references
3325  * @short A single analog line related event
3326  */
3327 class YSIG_API AnalogLineEvent : public GenObject
3328 {
3329 public:
3330     /**
3331      * Constructor
3332      * @param line The analog line that generated this event
3333      * @param event The signalling circuit event
3334      */
AnalogLineEvent(AnalogLine * line,SignallingCircuitEvent * event)3335     AnalogLineEvent(AnalogLine* line, SignallingCircuitEvent* event)
3336 	: m_line(0), m_event(event)
3337 	{ if (line && line->ref()) m_line = line; }
3338 
3339     /**
3340      * Destructor, dereferences any resources
3341      */
~AnalogLineEvent()3342     virtual ~AnalogLineEvent()
3343     {
3344 	TelEngine::destruct(m_line);
3345 	TelEngine::destruct(m_event);
3346     }
3347 
3348     /**
3349      * Get the analog line that generated this event
3350      * @return The analog line that generated this event
3351      */
line()3352     inline AnalogLine* line()
3353 	{ return m_line; }
3354 
3355     /**
3356      * Get the signalling circuit event carried by this analog line event
3357      * @return The signalling circuit event carried by this analog line event
3358      */
event()3359     inline SignallingCircuitEvent* event()
3360 	{ return m_event; }
3361 
3362     /**
3363      * Disposes the memory
3364      */
destruct()3365     virtual void destruct()
3366     {
3367 	TelEngine::destruct(m_line);
3368 	TelEngine::destruct(m_event);
3369 	GenObject::destruct();
3370     }
3371 
3372 private:
3373     AnalogLine* m_line;
3374     SignallingCircuitEvent* m_event;
3375 };
3376 
3377 /**
3378  * This class is an analog line container.
3379  * It may contain another group when used to monitor analog lines
3380  * @short A group of analog lines
3381  */
3382 class YSIG_API AnalogLineGroup : public SignallingCircuitGroup
3383 {
3384     YCLASS(AnalogLineGroup,SignallingCircuitGroup)
3385 public:
3386     /**
3387      * Constructor. Construct an analog line group owning single lines
3388      * @param type Line type as enumeration
3389      * @param name Name of this component
3390      * @param slave True if this is an FXO group owned by an FXS one. Ignored if type is not FXO
3391      */
3392     AnalogLineGroup(AnalogLine::Type type, const char* name, bool slave = false);
3393 
3394     /**
3395      * Constructor. Construct an FXS analog line group owning another group of FXO analog lines.
3396      * The fxo group is owned by this component and will be destructed if invalid (not FXO type)
3397      * @param name Name of this component
3398      * @param fxo The FXO group
3399      */
3400     AnalogLineGroup(const char* name, AnalogLineGroup* fxo);
3401 
3402     /**
3403      * Destructor
3404      */
3405     virtual ~AnalogLineGroup();
3406 
3407     /**
3408      * Get this group's type
3409      * @return The group's type
3410      */
type()3411     inline AnalogLine::Type type() const
3412 	{ return m_type; }
3413 
3414     /**
3415      * Get the analog lines belonging to this group
3416      * @return The group's lines list
3417      */
lines()3418     inline ObjList& lines()
3419 	{ return m_lines; }
3420 
3421     /**
3422      * Get the group holding the FXO lines if present
3423      * @return The group holding the FXO lines or 0
3424      */
fxo()3425     inline AnalogLineGroup* fxo()
3426 	{ return m_fxo; }
3427 
3428     /**
3429      * Check if this is an FXO group owned by an FXS one
3430      * @return True if this is an FXO group owned by an FXS one
3431      */
slave()3432     inline bool slave()
3433 	{ return m_slave; }
3434 
3435     /**
3436      * Append a line to this group. Line must have the same type as this group and must be owned by this group
3437      * @param line The line to append
3438      * @param destructOnFail Destroy line if failed to append. Defaults to true
3439      * @return True on success
3440      */
3441     bool appendLine(AnalogLine* line, bool destructOnFail = true);
3442 
3443     /**
3444      * Remove a line from the list and destruct it
3445      * @param cic The signalling circuit's code used by the line
3446      */
3447     void removeLine(unsigned int cic);
3448 
3449     /**
3450      * Remove a line from the list without destroying it
3451      * @param line The line to be removed
3452      */
3453     void removeLine(AnalogLine* line);
3454 
3455     /**
3456      * Find a line by its circuit
3457      * @param cic The signalling circuit's code used by the line
3458      * @return AnalogLine pointer or 0 if not found
3459      */
3460     AnalogLine* findLine(unsigned int cic);
3461 
3462     /**
3463      * Find a line by its address
3464      * @param address The address of the line
3465      * @return AnalogLine pointer or 0 if not found
3466      */
3467     AnalogLine* findLine(const String& address);
3468 
3469     /**
3470      * Iterate through the line list to get an event
3471      * @param when The current time
3472      * @return AnalogLineEvent pointer or 0 if no events
3473      */
3474     virtual AnalogLineEvent* getEvent(const Time& when);
3475 
3476 protected:
3477     /**
3478      * Remove all lines. Release object
3479      */
3480     virtual void destroyed();
3481 
3482     /**
3483      * The analog lines belonging to this group
3484      */
3485     ObjList m_lines;
3486 
3487 private:
3488     AnalogLine::Type m_type;             // Line type
3489     AnalogLineGroup* m_fxo;              // The group containing the FXO lines if this is a monitor
3490     bool m_slave;                        // True if this is an FXO group owned by an FXS one
3491 };
3492 
3493 /**
3494  * An universal SS7 Layer 3 routing Code Point
3495  * @short SS7 Code Point
3496  */
3497 class YSIG_API SS7PointCode : public GenObject
3498 {
3499     YCLASS(SS7PointCode,GenObject)
3500 public:
3501     /**
3502      * Different incompatible types of points codes
3503      */
3504     enum Type {
3505 	Other  = 0,
3506 	ITU    = 1, // ITU-T Q.704
3507 	ANSI   = 2, // ANSI T1.111.4
3508 	ANSI8  = 3, // 8-bit SLS
3509 	China  = 4, // GF 001-9001
3510 	Japan  = 5, // JT-Q704, NTT-Q704
3511 	Japan5 = 6, // 5-bit SLS
3512 	// Do not change the next line, must be past last defined type
3513 	DefinedTypes
3514     };
3515 
3516     /**
3517      * Constructor from components
3518      * @param network ANSI Network Identifier / ITU-T Zone Identification
3519      * @param cluster ANSI Network Cluster / ITU-T Area/Network Identification
3520      * @param member ANSI Cluster Member / ITU-T Signalling Point Identification
3521      */
3522     inline SS7PointCode(unsigned char network = 0, unsigned char cluster = 0, unsigned char member = 0)
m_network(network)3523 	: m_network(network), m_cluster(cluster), m_member(member)
3524 	{ }
3525 
3526     /**
3527      * Constructor from unpacked format
3528      * @param type Type of the unpacking desired
3529      * @param packed Packed format of the point code
3530      */
SS7PointCode(Type type,unsigned int packed)3531     inline SS7PointCode(Type type, unsigned int packed)
3532 	: m_network(0), m_cluster(0), m_member(0)
3533 	{ unpack(type,packed); }
3534 
3535     /**
3536      * Copy constructor
3537      * @param original Code point to be copied
3538      */
SS7PointCode(const SS7PointCode & original)3539     inline SS7PointCode(const SS7PointCode& original)
3540 	: m_network(original.network()), m_cluster(original.cluster()), m_member(original.member())
3541 	{ }
3542 
3543     /**
3544      * Destructor
3545      */
~SS7PointCode()3546     inline ~SS7PointCode()
3547 	{ }
3548 
3549     /**
3550      * Retrieve the Network / Zone component of the Code Point
3551      * @return ANSI Network Identifier / ITU-T Zone Identification
3552      */
network()3553     inline unsigned char network() const
3554 	{ return m_network; }
3555 
3556     /**
3557      * Retrieve the Cluster / Area component of the Code Point
3558      * @return ANSI Network Cluster / ITU-T Area/Network Identification
3559      */
cluster()3560     inline unsigned char cluster() const
3561 	{ return m_cluster; }
3562 
3563     /**
3564      * Retrieve the Cluster / Point component of the Code Point
3565      * @return ANSI Cluster Member / ITU-T Signalling Point Identification
3566      */
member()3567     inline unsigned char member() const
3568 	{ return m_member; }
3569 
3570     /**
3571      * Assignment from components
3572      * @param network ANSI Network Identifier / ITU-T Zone Identification
3573      * @param cluster ANSI Network Cluster / ITU-T Area/Network Identification
3574      * @param member ANSI Cluster Member / ITU-T Signalling Point Identification
3575      */
assign(unsigned char network,unsigned char cluster,unsigned char member)3576     inline void assign(unsigned char network, unsigned char cluster, unsigned char member)
3577 	{ m_network = network; m_cluster = cluster; m_member = member; }
3578 
3579     /**
3580      * Assign data members from a given string of form 'network-cluster-member'
3581      * @param src Source string
3582      * @param type Type of the point code if numeric (packed) representation is used
3583      * @return False if the string has incorrect format or individual elements are not in the range 0..255
3584      */
3585     bool assign(const String& src, Type type = Other);
3586 
3587     /**
3588      * Assign data members from a packed memory block
3589      * @param type Type of the point code in memory
3590      * @param src Pointer to packed point code in memory
3591      * @param len Length of data, negative to not check validity
3592      * @param spare Pointer to variable to save spare bits, NULL to ignore them
3593      * @return True if success, false if invalid type or memory area
3594      */
3595     bool assign(Type type, const unsigned char* src, int len = -1, unsigned char* spare = 0);
3596 
3597     /**
3598      * Assignment operator
3599      * @param original Code point to be copied
3600      */
3601     inline SS7PointCode& operator=(const SS7PointCode& original)
3602 	{ assign(original.network(),original.cluster(),original.member()); return *this; }
3603 
3604     /**
3605      * Equality operator
3606      * @param original Code point to be compared with
3607      */
3608     inline bool operator==(const SS7PointCode& original) const
3609 	{ return m_network == original.network() && m_cluster == original.cluster() && m_member == original.member(); }
3610 
3611     /**
3612      * Inequality operator
3613      * @param original Code point to be compared with
3614      */
3615     inline bool operator!=(const SS7PointCode& original) const
3616 	{ return m_network != original.network() || m_cluster != original.cluster() || m_member != original.member(); }
3617 
3618     /**
3619      * Check if the point code is compatible with a packing type
3620      * @return True if the Network and Member fit in the packing format
3621      */
3622     bool compatible(Type type) const;
3623 
3624     /**
3625      * Pack the code point into a single integer number.
3626      * @param type Type of the packing desired
3627      * @return Compact code point as integer or zero if the packing type is not supported
3628      */
3629     unsigned int pack(Type type) const;
3630 
3631     /**
3632      * Unpack an integer number into a point code
3633      * @param type Type of the unpacking desired
3634      * @param packed Packed format of the point code
3635      * @return True if the unpacking succeeded and the point code was updated
3636      */
3637     bool unpack(Type type, unsigned int packed);
3638 
3639     /**
3640      * Store the point code in a memory area
3641      * @param type Type of the packing desired
3642      * @param dest Location to store the label info, must be at least length() long
3643      * @param spare Spare bits to store after the point code if applicable (ITU)
3644      * @return True if the unpacking succeeded and the memory was updated
3645      */
3646     bool store(Type type, unsigned char* dest, unsigned char spare = 0) const;
3647 
3648     /**
3649      * Get the size (in bits) of a packed code point according to its type
3650      * @param type Type of the packing
3651      * @return Number of bits required to represent the code point, zero if unknown
3652      */
3653     static unsigned char size(Type type);
3654 
3655     /**
3656      * Get the length (in octets) of a packed code point according to its type
3657      * @param type Type of the packing
3658      * @return Number of octets required to represent the code point, zero if unknown
3659      */
3660     static unsigned char length(Type type);
3661 
3662     /**
3663      * Get a point type associated to a given text
3664      * @param text Text to find
3665      * @return Point code type as enumeration
3666      */
lookup(const char * text)3667     static Type lookup(const char* text)
3668 	{ return (Type)TelEngine::lookup(text,s_names,(int)Other); }
3669 
3670     /**
3671      * Get the text associated to a point type
3672      * @param type Type to find
3673      * @return The requested text or 0 if not found
3674      */
lookup(Type type)3675     static const char* lookup(Type type)
3676 	{ return TelEngine::lookup((int)type,s_names); }
3677 
3678 private:
3679     static const TokenDict s_names[];    // Keep the strigns associated with point code type
3680     unsigned char m_network;
3681     unsigned char m_cluster;
3682     unsigned char m_member;
3683 };
3684 
3685 // The number of valid point code types
3686 #define YSS7_PCTYPE_COUNT (SS7PointCode::DefinedTypes-1)
3687 
3688 /**
3689  * Operator to write a point code to a string
3690  * @param str String to append to
3691  * @param cp Point code to append to the string
3692  */
3693 YSIG_API String& operator<<(String& str, const SS7PointCode& cp);
3694 
3695 /**
3696  * A SS7 Layer 3 routing label, both ANSI and ITU capable
3697  * @short SS7 Routing Label
3698  */
3699 class YSIG_API SS7Label
3700 {
3701 public:
3702     /**
3703      * Constructor of an empty, invalid label
3704      */
3705     SS7Label();
3706 
3707     /**
3708      * Copy constructor
3709      * @param original Label to copy
3710      */
3711     SS7Label(const SS7Label& original);
3712 
3713     /**
3714      * Swapping constructor, puts SPC into DPC and the other way around
3715      * @param original Label to swap
3716      * @param sls Signalling Link Selection
3717      * @param spare Spare bits
3718      */
3719     SS7Label(const SS7Label& original, unsigned char sls, unsigned char spare = 0);
3720 
3721     /**
3722      * Constructor from label components
3723      * @param type Type of point code used to pack the label
3724      * @param dpc Destination Point Code
3725      * @param opc Originating Point Code
3726      * @param sls Signalling Link Selection
3727      * @param spare Spare bits
3728      */
3729     SS7Label(SS7PointCode::Type type, const SS7PointCode& dpc,
3730 	const SS7PointCode& opc, unsigned char sls, unsigned char spare = 0);
3731 
3732     /**
3733      * Constructor from packed label components
3734      * @param type Type of point code used to pack the label
3735      * @param dpc Destination Point Code
3736      * @param opc Originating Point Code
3737      * @param sls Signalling Link Selection
3738      * @param spare Spare bits
3739      */
3740     SS7Label(SS7PointCode::Type type, unsigned int dpc,
3741 	unsigned int opc, unsigned char sls, unsigned char spare = 0);
3742 
3743     /**
3744      * Constructor from type and received MSU
3745      * @param type Type of point code to use to decode the MSU
3746      * @param msu A received MSU to be parsed
3747      */
3748     SS7Label(SS7PointCode::Type type, const SS7MSU& msu);
3749 
3750     /**
3751      * Assignment from label components
3752      * @param type Type of point code used to pack the label
3753      * @param dpc Destination Point Code
3754      * @param opc Originating Point Code
3755      * @param sls Signalling Link Selection
3756      * @param spare Spare bits
3757      */
3758     void assign(SS7PointCode::Type type, const SS7PointCode& dpc,
3759 	const SS7PointCode& opc, unsigned char sls, unsigned char spare = 0);
3760 
3761     /**
3762      * Assignment from packed label components
3763      * @param type Type of point code used to pack the label
3764      * @param dpc Destination Point Code
3765      * @param opc Originating Point Code
3766      * @param sls Signalling Link Selection
3767      * @param spare Spare bits
3768      */
3769     void assign(SS7PointCode::Type type, unsigned int dpc,
3770 	unsigned int opc, unsigned char sls, unsigned char spare = 0);
3771 
3772     /**
3773      * Assignment from type and received MSU
3774      * @param type Type of point code to use to decode the MSU
3775      * @param msu A received MSU to be parsed
3776      * @return True if the assignment succeeded
3777      */
3778     bool assign(SS7PointCode::Type type, const SS7MSU& msu);
3779 
3780     /**
3781      * Assignment from a packed memory block
3782      * @param type Type of the point codes in memory block
3783      * @param src Pointer to packed label in memory
3784      * @param len Length of data, negative to not check validity
3785      * @return True if success, false if invalid type or memory area
3786      */
3787     bool assign(SS7PointCode::Type type, const unsigned char* src, int len = -1);
3788 
3789     /**
3790      * Pack and store the label in a memory location
3791      * @param dest Location to store the label info, must be at least length() long
3792      * @return True on success, false if type is invalid
3793      */
3794     bool store(unsigned char* dest) const;
3795 
3796     /**
3797      * Check if the label is compatible with another packing type
3798      * @return True if the DLC, SLC and SLS fit in the new packing format
3799      */
3800     bool compatible(SS7PointCode::Type type) const;
3801 
3802     /**
3803      * Get the type (SS7 dialect) of the routing label
3804      * @return Dialect of the routing label as enumeration
3805      */
type()3806     inline SS7PointCode::Type type() const
3807 	{ return m_type; }
3808 
3809     /**
3810      * Get the Destination Code Point inside the label
3811      * @return Reference of the destination code point
3812      */
dpc()3813     inline const SS7PointCode& dpc() const
3814 	{ return m_dpc; }
3815 
3816     /**
3817      * Get a writable reference to the Destination Code Point inside the label
3818      * @return Reference of the destination code point
3819      */
dpc()3820     inline SS7PointCode& dpc()
3821 	{ return m_dpc; }
3822 
3823     /**
3824      * Get the Originating Code Point inside the label
3825      * @return Reference of the source code point
3826      */
opc()3827     inline const SS7PointCode& opc() const
3828 	{ return m_opc; }
3829 
3830     /**
3831      * Get a writable reference to the Originating Code Point inside the label
3832      * @return Reference of the originating code point
3833      */
opc()3834     inline SS7PointCode& opc()
3835 	{ return m_opc; }
3836 
3837     /**
3838      * Get the Signalling Link Selection inside the label
3839      * @return Value of the SLS field
3840      */
sls()3841     inline unsigned char sls() const
3842 	{ return m_sls; }
3843 
3844     /**
3845      * Set the Signalling Link Selection inside the label
3846      * @param sls New value of the SLS/SLC field
3847      */
setSls(unsigned char sls)3848     inline void setSls(unsigned char sls)
3849 	{ m_sls = sls; }
3850 
3851     /**
3852      * Get the spare bits inside the label
3853      * @return Value of the bits not included in DPC, OPC, or SLS
3854      */
spare()3855     inline unsigned char spare() const
3856 	{ return m_spare; }
3857 
3858     /**
3859      * Set the spare bits inside the label
3860      * @param spare New value of the spare bits
3861      */
setSpare(unsigned char spare)3862     inline void setSpare(unsigned char spare)
3863 	{ m_spare = spare; }
3864 
3865     /**
3866      * Get the length (in bytes) of this routing label
3867      * @return Number of bytes required to represent the label, zero if unknown
3868      */
length()3869     inline unsigned int length() const
3870 	{ return length(m_type); }
3871 
3872     /**
3873      * Get the length (in bytes) of a packed routing label according to its type
3874      * @param type Type of the packing
3875      * @return Number of bytes required to represent the label, zero if unknown
3876      */
3877     static unsigned int length(SS7PointCode::Type type);
3878 
3879     /**
3880      * Get the size (in bits) of this routing label except the spare bits
3881      * @return Number of bits required to represent this label, zero if unknown
3882      */
size()3883     inline unsigned char size() const
3884 	{ return size(m_type); }
3885 
3886     /**
3887      * Get the size (in bits) of a packed routing label according to its type
3888      * @param type Type of the packing
3889      * @return Number of bits required to represent the label, zero if unknown
3890      */
3891     static unsigned char size(SS7PointCode::Type type);
3892 
3893 private:
3894     SS7PointCode::Type m_type;
3895     SS7PointCode m_dpc;
3896     SS7PointCode m_opc;
3897     unsigned char m_sls;
3898     unsigned char m_spare;
3899 };
3900 
3901 /**
3902  * Operator to write a routing label to a string
3903  * @param str String to append to
3904  * @param label Label to append to the string
3905  */
3906 YSIG_API String& operator<<(String& str, const SS7Label& label);
3907 
3908 // Maximum size of a MTP2 MSU including SIO + Routing Label + data (Q.703 2.3.8)
3909 #define MAX_TDM_MSU_SIZE 273
3910 
3911 /**
3912  * A raw data block with a little more understanding about MSU format
3913  * @short A block of data that holds a Message Signal Unit
3914  */
3915 class YSIG_API SS7MSU : public DataBlock
3916 {
3917     YCLASS(SS7MSU,DataBlock)
3918 public:
3919     /**
3920      * Service indicator values
3921      */
3922     enum Services {
3923 	// Signalling Network Management
3924 	SNM   =  0,
3925 	// Maintenance
3926 	MTN   =  1,
3927 	// Maintenance special
3928 	MTNS  =  2,
3929 	// Signalling Connection Control Part
3930 	SCCP  =  3,
3931 	// Telephone User Part
3932 	TUP   =  4,
3933 	// ISDN User Part
3934 	ISUP  =  5,
3935 	// Data User Part - call and circuit related
3936 	DUP_C =  6,
3937 	// Data User Part - facility messages
3938 	DUP_F =  7,
3939 	// MTP Testing User Part (reserved)
3940 	MTP_T =  8,
3941 	// Broadband ISDN User Part
3942 	BISUP =  9,
3943 	// Satellite ISDN User Part
3944 	SISUP = 10,
3945 	// AAL type2 Signaling
3946 	AAL2  = 12,
3947 	// Bearer Independent Call Control
3948 	BICC  = 13,
3949 	// Gateway Control Protocol
3950 	GCP   = 14,
3951     };
3952 
3953     /**
3954      * Priority values
3955      */
3956     enum Priority {
3957 	Regular  = 0x00,
3958 	Special  = 0x10,
3959 	Circuit  = 0x20,
3960 	Facility = 0x30
3961     };
3962 
3963     /**
3964      * Subservice types
3965      */
3966     enum NetIndicator {
3967 	International      = 0x00,
3968 	SpareInternational = 0x40,
3969 	National           = 0x80,
3970 	ReservedNational   = 0xc0
3971     };
3972 
3973     /**
3974      * Empty MSU constructor
3975      */
SS7MSU()3976     inline SS7MSU()
3977 	{ }
3978 
3979     /**
3980      * Copy constructor
3981      * @param value Original MSU
3982      */
SS7MSU(const SS7MSU & value)3983     inline SS7MSU(const SS7MSU& value)
3984 	: DataBlock(value)
3985 	{ }
3986 
3987     /**
3988      * Constructor from data block
3989      * @param value Raw data block to copy
3990      */
SS7MSU(const DataBlock & value)3991     inline SS7MSU(const DataBlock& value)
3992 	: DataBlock(value)
3993 	{ }
3994 
3995     /**
3996      * Constructor of an initialized MSU
3997      * @param value Data to assign, may be NULL to fill with zeros
3998      * @param len Length of data, may be zero (then value is ignored)
3999      * @param copyData True to make a copy of the data, false to use the pointer
4000      */
4001     inline SS7MSU(void* value, unsigned int len, bool copyData = true)
DataBlock(value,len,copyData)4002 	: DataBlock(value,len,copyData)
4003 	{ }
4004 
4005     /**
4006      * Constructor from routing label and raw data
4007      * @param sio Service Information Octet
4008      * @param label Routing label
4009      * @param len Length of data, may be zero (then value is ignored)
4010      * @param value Data to assign, may be NULL to fill with zeros
4011      */
4012     SS7MSU(unsigned char sio, const SS7Label label, void* value = 0, unsigned int len = 0);
4013 
4014     /**
4015      * Constructor from routing label and raw data
4016      * @param sif Service Information Field
4017      * @param ssf Subservice Field
4018      * @param label Routing label
4019      * @param len Length of data, may be zero (then value is ignored)
4020      * @param value Data to assign, may be NULL to fill with zeros
4021      */
4022     SS7MSU(unsigned char sif, unsigned char ssf, const SS7Label label, void* value = 0, unsigned int len = 0);
4023 
4024     /**
4025      * Destructor
4026      */
4027     virtual ~SS7MSU();
4028 
4029     /**
4030      * Assignment operator
4031      * @param value Original MSU
4032      * @return A reference to this MSU
4033      */
4034     inline SS7MSU& operator=(const SS7MSU& value)
4035 	{ DataBlock::operator=(value); return *this; }
4036 
4037     /**
4038      * Assignment operator from data block
4039      * @param value Data block to assign
4040      * @return A reference to this MSU
4041      */
4042     inline SS7MSU& operator=(const DataBlock& value)
4043 	{ DataBlock::operator=(value); return *this; }
4044 
4045     /**
4046      * Check if the MSU length appears valid
4047      * @return True if the MSU length is valid
4048      */
4049     bool valid() const;
4050 
4051     /**
4052      * Get a pointer to raw data
4053      * @param offs Offset in the MSU
4054      * @param len Minimum length of data requested
4055      * @return Pointer to data or NULL if invalid offset or length
4056      */
4057     inline unsigned char* getData(unsigned int offs, unsigned int len = 1)
4058 	{ return (offs+len <= length()) ? offs + (unsigned char*)data() : 0; }
4059 
4060     /**
4061      * Get a const pointer to raw data
4062      * @param offs Offset in the MSU
4063      * @param len Minimum length of data requested
4064      * @return Pointer to data or NULL if invalid offset or length
4065      */
4066     inline const unsigned char* getData(unsigned int offs, unsigned int len = 1) const
4067 	{ return (offs+len <= length()) ? offs + (const unsigned char*)data() : 0; }
4068 
4069     /**
4070      * Get a pointer to raw user part data after a routing label
4071      * @param label Routing label of the MSU
4072      * @param len Minimum length of data requested
4073      * @return Pointer to data or NULL if invalid offset or length
4074      */
4075     inline unsigned char* getData(const SS7Label& label, unsigned int len = 1)
4076 	{ return getData(label.length()+1,len); }
4077 
4078     /**
4079      * Get a const pointer to raw user part data after a routing label
4080      * @param label Routing label of the MSU
4081      * @param len Minimum length of data requested
4082      * @return Pointer to data or NULL if invalid offset or length
4083      */
4084     inline const unsigned char* getData(const SS7Label& label, unsigned int len = 1) const
4085 	{ return getData(label.length()+1,len); }
4086 
4087     /**
4088      * Retrieve the Service Information Octet
4089      * @return Value of the SIO or -1 if the MSU is empty
4090      */
getSIO()4091     inline int getSIO() const
4092 	{ return null() ? -1 : *(const unsigned char*)data(); }
4093 
4094     /**
4095      * Retrieve the Service Information Field
4096      * @return Value of the SIF or -1 if the MSU is empty
4097      */
getSIF()4098     inline int getSIF() const
4099 	{ return null() ? -1 : 0x0f & *(const unsigned char*)data(); }
4100 
4101     /**
4102      * Retrieve the Subservice Field (SSF)
4103      * @return Value of the subservice or -1 if the MSU is empty
4104      */
getSSF()4105     inline int getSSF() const
4106 	{ return null() ? -1 : 0xf0 & *(const unsigned char*)data(); }
4107 
4108     /**
4109      * Retrieve the Priority Field
4110      * @return Value of the priority or -1 if the MSU is empty
4111      */
getPrio()4112     inline int getPrio() const
4113 	{ return null() ? -1 : 0x30 & *(const unsigned char*)data(); }
4114 
4115     /**
4116      * Retrieve the Network Indicator (NI)
4117      * @return Value of the subservice or -1 if the MSU is empty
4118      */
getNI()4119     inline int getNI() const
4120 	{ return null() ? -1 : 0xc0 & *(const unsigned char*)data(); }
4121 
4122     /**
4123      * Retrieve the name of the Service as decoded from the SIF
4124      * @return Name of the service, NULL if unknown or invalid MSU
4125      */
4126     const char* getServiceName() const;
4127 
4128     /**
4129      * Retrieve the name of the Priority as decoded from the SIF
4130      * @return Name of the priority, NULL if unknown or invalid MSU
4131      */
4132     const char* getPriorityName() const;
4133 
4134     /**
4135      * Retrieve the name of the Network Indicator as decoded from the SIF
4136      * @return Name of the network indicator, NULL if unknown or invalid MSU
4137      */
4138     const char* getIndicatorName() const;
4139 
4140     /**
4141      * Get the priority associated with a given name
4142      * @param name Priority name to find
4143      * @param defVal Default value to return if not found
4144      * @return The priority value or the given default one if not exists
4145      */
4146     static unsigned char getPriority(const char* name, unsigned char defVal = Regular);
4147 
4148     /**
4149      * Get the network indicator associated with a given name
4150      * @param name Network indicator name to find
4151      * @param defVal Default value to return if not found
4152      * @return The network indicator value or the given default one if not exists
4153      */
4154     static unsigned char getNetIndicator(const char* name, unsigned char defVal = National);
4155 };
4156 
4157 /**
4158  * Simple inline class used to know if a MSU was handled and if not why
4159  * @short MSU handling result codes (Q.704 15.17.5 and more)
4160  */
4161 class HandledMSU
4162 {
4163 public:
4164     enum Result {
4165 	Rejected     =  0,
4166 	Unequipped   =  1,
4167 	Inaccessible =  2,
4168 	// private used (non Q.704)
4169 	Accepted     = 16,
4170 	Failure      = 17,
4171 	NoAddress    = 18,
4172 	NoCircuit    = 19,
4173     };
4174 
4175     /**
4176      * Regular constructor
4177      * @param result MSU handling result
4178      */
4179     inline HandledMSU(Result result = Rejected)
4180 	{ m_result = result; }
4181 
4182     /**
4183      * Constructor from boolean success
4184      * @param success True signifies Accepted, false for Failure
4185      */
HandledMSU(bool success)4186     inline HandledMSU(bool success)
4187 	{ m_result = success ? Accepted : Failure; }
4188 
4189     /**
4190      * Copy constructor
4191      * @param original Result to copy
4192      */
HandledMSU(const HandledMSU & original)4193     inline HandledMSU(const HandledMSU& original)
4194 	{ m_result = original; }
4195 
4196     /**
4197      * Assignment from Result enumeration
4198      * @param result MSU handling result
4199      */
4200     inline HandledMSU& operator=(Result result)
4201 	{ m_result = result; return *this; }
4202 
4203     /**
4204      * Assignment operator
4205      * @param original Result to assign from
4206      */
4207     inline HandledMSU& operator=(const HandledMSU& original)
4208 	{ m_result = original; return *this; }
4209 
4210     /**
4211      * Equality operator
4212      * @param result Handling result value to compare to
4213      */
4214     inline bool operator==(Result result)
4215 	{ return m_result == result; }
4216 
4217     /**
4218      * Equality operator
4219      * @param result Handling result value to compare to
4220      */
4221     inline bool operator==(const HandledMSU& result)
4222 	{ return m_result == result; }
4223 
4224     /**
4225      * Inequality operator
4226      * @param result Handling result value to compare to
4227      */
4228     inline bool operator!=(Result result)
4229 	{ return m_result != result; }
4230 
4231     /**
4232      * Inequality operator
4233      * @param result Handling result value to compare to
4234      */
4235     inline bool operator!=(const HandledMSU& result)
4236 	{ return m_result != result; }
4237 
4238     /**
4239      * Result retrieval operator
4240      * @return Handling result enumeration
4241      */
Result()4242     inline operator Result() const
4243 	{ return m_result; }
4244 
4245     /**
4246      * Success checking
4247      * @return True if MSU was handled, false for any other result
4248      */
ok()4249     inline bool ok() const
4250 	{ return Accepted == m_result; }
4251 
4252     /**
4253      * Retrieve Q.704 15.17.5 UPU cause code
4254      * @return UPU cause code, 0 (Unknown) for all private causes
4255      */
upu()4256     inline unsigned char upu() const
4257 	{ return (Accepted > m_result) ? m_result : Rejected; }
4258 
4259 private:
4260     Result m_result;
4261 };
4262 
4263 /**
4264  * A an abstraction offering connectivity to a SIGTRAN transport
4265  * @short An abstract SIGTRAN transport layer
4266  */
4267 class YSIG_API SIGTransport : public SignallingComponent
4268 {
YCLASS(SIGTransport,SignallingComponent)4269     YCLASS(SIGTransport,SignallingComponent)
4270     friend class SIGTRAN;
4271 public:
4272     /**
4273      * Type of transport used
4274      */
4275     enum Transport {
4276 	None = 0,
4277 	Sctp,
4278 	// All the following transports are not standard
4279 	Tcp,
4280 	Udp,
4281 	Unix,
4282     };
4283 
4284     /**
4285      * Get the SIGTRAN component attached to this transport
4286      * @return Pointer to adaptation layer or NULL
4287      */
sigtran()4288      inline SIGTRAN* sigtran() const
4289 	{ return m_sigtran; }
4290 
4291     /**
4292      * Get the default SCTP/TCP/UDP port used
4293      * @return Default protocol port, 0 if unknown, not set or no SIGTRAN attached
4294      */
4295     u_int32_t defPort() const;
4296 
4297     /**
4298      * Check if transport layer is reliable
4299      * @return true if transport is reliable
4300      */
4301     virtual bool reliable() const = 0;
4302 
4303     /**
4304      * Notify the SIGTRAN layer about transport status changes
4305      * @param status Status to notify
4306      */
4307     void notifyLayer(SignallingInterface::Notification status);
4308 
4309     /**
4310      * Configure and initialize the component and any subcomponents it may have
4311      * @param config Optional configuration parameters override
4312      * @return True if the component was initialized properly
4313      */
initialize(const NamedList * config)4314     virtual bool initialize(const NamedList* config)
4315 	{ return false;}
4316 
4317     /**
4318      * Check if the network transport layer is connected
4319      * @param streamId Identifier of the stream to check if applicable
4320      * @return True if the transport (and stream if applicable) is connected
4321      */
4322     virtual bool connected(int streamId) const = 0;
4323 
4324     /**
4325      * Attach an user adaptation layer
4326      * @param sigtran SIGTRAN component to attach, can be NULL
4327      */
4328     void attach(SIGTRAN* sigtran);
4329 
4330     /**
4331      * Send a complete message to the adaptation layer for processing
4332      * @param msgVersion Version of the protocol
4333      * @param msgClass Class of the message
4334      * @param msgType Type of the message, depends on the class
4335      * @param msg Message data, may be empty
4336      * @param streamId Identifier of the stream the message was received on
4337      * @return True if the message was handled
4338      */
4339     bool processMSG(unsigned char msgVersion, unsigned char msgClass,
4340 	unsigned char msgType, const DataBlock& msg, int streamId) const;
4341 
4342     /**
4343      * Force the underlaying transport to reconnect
4344      * @param force True to force transport socket reconnection
4345      */
4346     virtual void reconnect(bool force = false)
4347 	{ }
4348 
4349     /**
4350      * Get sctp socket parameters.
4351      * @param params List of parameters to obtain
4352      * @param result List of parameters to fill
4353      * @return True if operation was successful, false if an error occurred
4354      */
getSocketParams(const String & params,NamedList & result)4355     virtual bool getSocketParams(const String& params, NamedList& result)
4356 	{ return false; }
4357 
4358     /**
4359      * Notification that a new incomming connection has been made
4360      * NOTE newTransport needs to be destroyed if will not be used
4361      * @param newTransport The new created transport
4362      * @param addr The newly created transport socket address
4363      * @return True if the newTransport will be used.
4364      */
4365     virtual bool transportNotify(SIGTransport* newTransport, const SocketAddr& addr);
4366 
4367     /**
4368      * Check if the transport thread is still running
4369      * @return True if the thread is still running.
4370      */
hasThread()4371     virtual bool hasThread()
4372 	{ return false; }
4373 
4374     /**
4375      * Stop the transport thread
4376      */
stopThread()4377     virtual void stopThread()
4378 	{ }
4379 protected:
4380     /**
4381      * Constructor
4382      * @param name Default empty component name
4383      */
4384     inline explicit SIGTransport(const char* name = 0)
SignallingComponent(name)4385 	: SignallingComponent(name), m_sigtran(0)
4386 	{ }
4387 
4388     /**
4389      * Notification if the attached state changed
4390      * @param hasUAL True if an User Adaptation Layer is now attached
4391      */
4392     virtual void attached(bool hasUAL) = 0;
4393 
4394     /**
4395      * Transmit a message to the network
4396      * @param msgVersion Version of the protocol
4397      * @param msgClass Class of the message
4398      * @param msgType Type of the message, depends on the class
4399      * @param msg Message data, may be empty
4400      * @param streamId Identifier of the stream to send the data over
4401      * @return True if the message was transmitted to network
4402      */
4403     virtual bool transmitMSG(unsigned char msgVersion, unsigned char msgClass,
4404 	unsigned char msgType, const DataBlock& msg, int streamId = 0);
4405 
4406     /**
4407      * Transmit a prepared message to the network
4408      * @param header Message header, typically 8 octets
4409      * @param msg Message data, may be empty
4410      * @param streamId Identifier of the stream to send the data over
4411      * @return True if the message was transmitted to network
4412      */
4413     virtual bool transmitMSG(const DataBlock& header, const DataBlock& msg, int streamId = 0) = 0;
4414 
4415 private:
4416     SIGTRAN* m_sigtran;
4417 };
4418 
4419 /**
4420  * An interface to a Signalling Transport user adaptation component
4421  * @short Abstract SIGTRAN user adaptation component
4422  */
4423 class YSIG_API SIGTRAN
4424 {
4425     friend class SIGTransport;
4426 public:
4427     /**
4428      * Message classes
4429      */
4430     enum MsgClass {
4431 	// Management (IUA/M2UA/M3UA/SUA)
4432 	MGMT  =  0,
4433 	// Transfer (M3UA)
4434 	TRAN  =  1,
4435 	// SS7 Signalling Network Management (M3UA/SUA)
4436 	SSNM  =  2,
4437 	// ASP State Maintenance (IUA/M2UA/M3UA/SUA)
4438 	ASPSM =  3,
4439 	// ASP Traffic Maintenance (IUA/M2UA/M3UA/SUA)
4440 	ASPTM =  4,
4441 	// Q.921/Q.931 Boundary Primitives Transport (IUA)
4442 	QPTM  =  5,
4443 	// MTP2 User Adaptation (M2UA)
4444 	MAUP  =  6,
4445 	// Connectionless Messages (SUA)
4446 	CLMSG =  7,
4447 	// Connection-Oriented Messages (SUA)
4448 	COMSG =  8,
4449 	// Routing Key Management (M3UA/SUA)
4450 	RKM   =  9,
4451 	// Interface Identifier Management (M2UA)
4452 	IIM   = 10,
4453 	// M2PA Messages (M2PA)
4454 	M2PA  = 11,
4455     };
4456 
4457     /**
4458      * Management messages
4459      */
4460     enum MsgMGMT {
4461 	MgmtERR  =  0,
4462 	MgmtNTFY =  1,
4463     };
4464 
4465     /**
4466      * Signalling Network Management messages
4467      */
4468     enum MsgSSNM {
4469 	SsnmDUNA =  1, // Destination Unavailable
4470 	SsnmDAVA =  2, // Destination Available
4471 	SsnmDAUD =  3, // Destination State Audit
4472 	SsnmSCON =  4, // Signalling Congestion
4473 	SsnmDUPU =  5, // Destination User Part Unavailable
4474 	SsnmDRST =  6, // Destination Restricted
4475     };
4476 
4477     /**
4478      * ASP State Maintenance messages
4479      */
4480     enum MsgASPSM {
4481 	AspsmUP       =  1,
4482 	AspsmDOWN     =  2,
4483 	AspsmBEAT     =  3,
4484 	AspsmUP_ACK   =  4,
4485 	AspsmDOWN_ACK =  5,
4486 	AspsmBEAT_ACK =  6,
4487     };
4488 
4489     /**
4490      * ASP Traffic Maintenance messages
4491      */
4492     enum MsgASPTM {
4493 	AsptmACTIVE       =  1,
4494 	AsptmINACTIVE     =  2,
4495 	AsptmACTIVE_ACK   =  3,
4496 	AsptmINACTIVE_ACK =  4,
4497     };
4498 
4499     /**
4500      * Routing Key Management messages
4501      */
4502     enum MsgRKM {
4503 	RkmREG_REQ    =  1,
4504 	RkmREG_RSP    =  2,
4505 	RkmDEREG_REQ  =  3,
4506 	RkmDEREG_RSP  =  4,
4507     };
4508 
4509     /**
4510      * Interface Identifier Management messages
4511      */
4512     enum MsgIIM {
4513 	IimREG_REQ    =  1,
4514 	IimREG_RSP    =  2,
4515 	IimDEREG_REQ  =  3,
4516 	IimDEREG_RSP  =  4,
4517     };
4518 
4519     /**
4520      * Constructs an uninitialized signalling transport
4521      * @param payload SCTP payload code, ignored for other transports
4522      * @param port SCTP/TCP/UDP default port used for transport
4523      */
4524     explicit SIGTRAN(u_int32_t payload = 0, u_int16_t port = 0);
4525 
4526     /**
4527      * Destructor, terminates transport layer
4528      */
4529     virtual ~SIGTRAN();
4530 
4531     /**
4532      * Attach a transport (connectivity provider)
4533      * @param trans Transport to attach to this component
4534      */
4535     virtual void attach(SIGTransport* trans);
4536 
4537     /**
4538      * Get the transport of this user adaptation component
4539      * @return Pointer to the transport layer or NULL
4540      */
transport()4541     inline SIGTransport* transport() const
4542 	{ return m_trans; }
4543 
4544     /**
4545      * Get the SCTP payload of this user adaptation component
4546      * @return SCTP payload code
4547      */
payload()4548     inline u_int32_t payload() const
4549 	{ return m_payload; }
4550 
4551     /**
4552      * Get the default SCTP/TCP/UDP port used for transport
4553      * @return Default protocol port, 0 if unknown or not set
4554      */
defPort()4555     inline u_int16_t defPort() const
4556 	{ return m_defPort; }
4557 
4558     /**
4559      * Check if the network transport layer is connected
4560      * @param streamId Identifier of the stream to check if applicable
4561      * @return True if the transport (and stream if applicable) is connected
4562      */
4563     bool connected(int streamId = 0) const;
4564 
notifyLayer(SignallingInterface::Notification status)4565     virtual void notifyLayer(SignallingInterface::Notification status)
4566 	{ }
4567 
4568     /**
4569      * Message class names dictionary
4570      * @return Pointer to dictionary of message classes
4571      */
4572     static const TokenDict* classNames();
4573 
4574     /**
4575      * Message types name lookup
4576      * @param msgClass Class of the message to look up
4577      * @param msgType Type of the message, depends on the class
4578      * @param defValue Value to return if lookup fails
4579      * @return Pointer to message type name
4580      */
4581     static const char* typeName(unsigned char msgClass, unsigned char msgType,
4582 	const char* defValue = 0);
4583 
4584     /**
4585      * Transmit a message to the network transport layer
4586      * @param msgVersion Version of the protocol
4587      * @param msgClass Class of the message
4588      * @param msgType Type of the message, depends on the class
4589      * @param msg Message data, may be empty
4590      * @param streamId Identifier of the stream to send the data over
4591      * @return True if the message was transmitted to network
4592      */
4593     bool transmitMSG(unsigned char msgVersion, unsigned char msgClass,
4594 	unsigned char msgType, const DataBlock& msg, int streamId = 0) const;
4595 
4596     /**
4597      * Transmit a message with default version to the network transport layer
4598      * @param msgClass Class of the message
4599      * @param msgType Type of the message, depends on the class
4600      * @param msg Message data, may be empty
4601      * @param streamId Identifier of the stream to send the data over
4602      * @return True if the message was transmitted to network
4603      */
4604     inline bool transmitMSG(unsigned char msgClass, unsigned char msgType,
4605 	const DataBlock& msg, int streamId = 0) const
4606 	{ return transmitMSG(1,msgClass,msgType,msg,streamId); }
4607 
4608     /**
4609      * Restart the underlaying transport
4610      * @param force True to hard restart, false to force restart if transport is down
4611      * @return True if the transport was notified that it needs to restart
4612      */
4613     bool restart(bool force);
4614 
4615     /**
4616      * Get sctp socket parameters.
4617      * @param params List of parameters to obtain
4618      * @param result List of parameters to fill
4619      * @return True if operation was successful, false if an error occurred
4620      */
4621     bool getSocketParams(const String& params, NamedList& result);
4622 
4623     /**
4624      * Notification that a new incomming connection has been made
4625      * @param newTransport The new created transport
4626      * @param addr The newly created transport socket address
4627      * @return True if the newTransport will be used.
4628      */
transportNotify(SIGTransport * newTransport,const SocketAddr & addr)4629     virtual bool transportNotify(SIGTransport* newTransport, const SocketAddr& addr)
4630 	{ TelEngine::destruct(newTransport); return false; }
4631 
4632     /**
4633      * Check if the transport thread is running
4634      * @return true if the transport thread is running
4635      */
4636     bool hasTransportThread();
4637 
4638     /**
4639      * Stop the transport thread
4640      */
4641     void stopTransportThread();
4642 
4643 protected:
4644     /**
4645      * Process a complete message
4646      * @param msgVersion Version of the protocol
4647      * @param msgClass Class of the message
4648      * @param msgType Type of the message, depends on the class
4649      * @param msg Message data, may be empty
4650      * @param streamId Identifier of the stream the message was received on
4651      * @return True if the message was handled
4652      */
4653     virtual bool processMSG(unsigned char msgVersion, unsigned char msgClass,
4654 	unsigned char msgType, const DataBlock& msg, int streamId) = 0;
4655 
4656 private:
4657     SIGTransport* m_trans;
4658     u_int32_t m_payload;
4659     u_int16_t m_defPort;
4660     mutable Mutex m_transMutex;
4661 };
4662 
4663 /**
4664  * An interface to a Signalling Transport User Adaptation component
4665  * @short Abstract SIGTRAN User Adaptation component
4666  */
4667 class YSIG_API SIGAdaptation : public SignallingComponent, public SIGTRAN, public Mutex
4668 {
4669     YCLASS(SIGAdaptation,SignallingComponent)
4670 public:
4671     /**
4672      * Traffic modes
4673      */
4674     enum TrafficMode {
4675 	TrafficUnused    = 0,
4676 	TrafficOverride  = 1,
4677 	TrafficLoadShare = 2,
4678 	TrafficBroadcast = 3,
4679     };
4680 
4681     enum HeartbeatState {
4682 	HeartbeatDisabled     = 0,
4683 	HeartbeatEnabled      = 1,
4684 	HeartbeatWaitResponse = 2,
4685     };
4686 
4687     enum Errors {
4688 	InvalidVersion            = 0x01,
4689 	InvalidIID                = 0x02,
4690 	UnsupportedMessageClass   = 0x03,
4691 	UnsupportedMessageType    = 0x04,
4692 	UnsupportedTrafficMode    = 0x05,
4693 	UnexpectedMessage         = 0x06,
4694 	ProtocolError             = 0x07,
4695 	UnsupportedIIDType        = 0x08,
4696 	InvalidStreamIdentifier   = 0x09,
4697 	UnassignedTEI             = 0x0a,
4698 	UnrecognizedSAPI          = 0x0b,
4699 	InvalidTEISAPI            = 0x0c,
4700 	ManagementBlocking        = 0x0d,
4701 	ASPIDRequired             = 0x0e,
4702 	InvalidASPID              = 0x0f,
4703 	ASPActiveIID              = 0x10,
4704 	InvalidParameterValue     = 0x11,
4705 	ParameterFieldError       = 0x12,
4706 	UnexpectedParameter       = 0x13,
4707 	DestinationStatusUnknown  = 0x14,
4708 	InvalidNetworkAppearance  = 0x15,
4709 	MissingParameter          = 0x16,
4710 	InvalidRoutingContext     = 0x19,
4711 	NotConfiguredAS           = 0x1a,
4712 	SubsystemStatusUnknown    = 0x1b,
4713 	InvalidLoadsharingLabel   = 0x1c
4714     };
4715 
4716     /**
4717      * Destructor
4718      */
4719     virtual ~SIGAdaptation();
4720 
4721     /**
4722      * Transport initialization
4723      * @param config Configuration section for the adaptation
4724      */
4725     virtual bool initialize(const NamedList* config);
4726 
4727     /**
4728      * Advance to next tag in a Type-Length-Value set of parameters
4729      * @param data Block of data containing TLV parameters
4730      * @param offset Offset of current parameter in block, initialize to negative for first tag
4731      * @param tag Type tag of returned parameter
4732      * @param length Unpadded length of returned parameter in octets
4733      * @return True if the current parameter was valid
4734      */
4735     static bool nextTag(const DataBlock& data, int& offset, uint16_t& tag, uint16_t& length);
4736 
4737     /**
4738      * Find a specific tag in a Type-Length-Value set of parameters
4739      * @param data Block of data containing TLV parameters
4740      * @param offset Offset of current parameter in block, gets updated
4741      * @param tag Type tag of searched parameter
4742      * @param length Unpadded length of returned parameter in octets
4743      * @return True if the requested parameter was found
4744      */
4745     static bool findTag(const DataBlock& data, int& offset, uint16_t tag, uint16_t& length);
4746 
4747     /**
4748      * Get the value of a 32 bit integer parameter
4749      * @param data Block of data containing TLV parameters
4750      * @param tag Type tag of searched parameter
4751      * @param value Variable to store the decoded parameter if found
4752      * @return True if the requested parameter was found and decoded
4753      */
4754     static bool getTag(const DataBlock& data, uint16_t tag, uint32_t& value);
4755 
4756     /**
4757      * Get the value of a String parameter
4758      * @param data Block of data containing TLV parameters
4759      * @param tag Type tag of searched parameter
4760      * @param value Variable to store the decoded parameter if found
4761      * @return True if the requested parameter was found and decoded
4762      */
4763     static bool getTag(const DataBlock& data, uint16_t tag, String& value);
4764 
4765     /**
4766      * Get the value of a raw binary parameter
4767      * @param data Block of data containing TLV parameters
4768      * @param tag Type tag of searched parameter
4769      * @param value Variable to store the decoded parameter if found
4770      * @return True if the requested parameter was found and decoded
4771      */
4772     static bool getTag(const DataBlock& data, uint16_t tag, DataBlock& value);
4773 
4774     /**
4775      * Add a 32 bit integer parameter
4776      * @param data Block of data containing TLV parameters
4777      * @param tag Type tag of parameter to add
4778      * @param value Value of parameter to add
4779      */
4780     static void addTag(DataBlock& data, uint16_t tag, uint32_t value);
4781 
4782     /**
4783      * Add a String parameter
4784      * @param data Block of data containing TLV parameters
4785      * @param tag Type tag of parameter to add
4786      * @param value Value of parameter to add
4787      */
4788     static void addTag(DataBlock& data, uint16_t tag, const String& value);
4789 
4790     /**
4791      * Add a raw binary parameter
4792      * @param data Block of data containing TLV parameters
4793      * @param tag Type tag of parameter to add
4794      * @param value Value of parameter to add
4795      */
4796     static void addTag(DataBlock& data, uint16_t tag, const DataBlock& value);
4797 
4798     /**
4799      * Method called when the transport status has been changed
4800      * @param status Status of the transport causing the notification
4801      */
4802     void notifyLayer(SignallingInterface::Notification status);
4803 
4804 protected:
4805     /**
4806      * Constructs an uninitialized User Adaptation component
4807      * @param name Name of this component
4808      * @param params Optional pointer to creation parameters
4809      * @param payload SCTP payload code, ignored for other transports
4810      * @param port SCTP/TCP/UDP default port used for transport
4811      */
4812     explicit SIGAdaptation(const char* name = 0, const NamedList* params = 0,
4813 	u_int32_t payload = 0, u_int16_t port = 0);
4814 
4815     /**
4816      * Processing of common management messages
4817      * @param msgClass Class of the message
4818      * @param msgType Type of the message, depends on the class
4819      * @param msg Message data, may be empty
4820      * @param streamId Identifier of the stream the message was received on
4821      * @return True if the message was handled
4822      */
4823     virtual bool processCommonMSG(unsigned char msgClass,
4824 	unsigned char msgType, const DataBlock& msg, int streamId);
4825 
4826     /**
4827      * Abstract processing of Management messages
4828      * @param msgType Type of the message, depends on the class
4829      * @param msg Message data, may be empty
4830      * @param streamId Identifier of the stream the message was received on
4831      * @return True if the message was handled
4832      */
4833     virtual bool processMgmtMSG(unsigned char msgType, const DataBlock& msg, int streamId) = 0;
4834 
4835     /**
4836      * Abstract processing of ASP State Maintenance messages
4837      * @param msgType Type of the message, depends on the class
4838      * @param msg Message data, may be empty
4839      * @param streamId Identifier of the stream the message was received on
4840      * @return True if the message was handled
4841      */
4842     virtual bool processAspsmMSG(unsigned char msgType, const DataBlock& msg, int streamId) = 0;
4843 
4844     /**
4845      * Abstract processing of ASP Traffic Maintenance messages
4846      * @param msgType Type of the message, depends on the class
4847      * @param msg Message data, may be empty
4848      * @param streamId Identifier of the stream the message was received on
4849      * @return True if the message was handled
4850      */
4851     virtual bool processAsptmMSG(unsigned char msgType, const DataBlock& msg, int streamId) = 0;
4852 
4853     /**
4854      * Method called periodically by the engine to keep everything alive
4855      * @param when Time to use as computing base for events and timeouts
4856      */
4857     virtual void timerTick(const Time& when);
4858 
4859     /**
4860      * Process the heartbeat messages
4861      * @param msgType The message type
4862      * @param msg Message data
4863      * @param streamId Identifier of the stream the message was received on
4864      * @return True if the message was handled
4865      */
4866     bool processHeartbeat(unsigned char msgType, const DataBlock& msg,
4867 	int streamId);
4868 
4869     /**
4870      * Reset heartbeat for all streams
4871      */
resetHeartbeat()4872     inline void resetHeartbeat()
4873     {
4874 	Lock myLock(this);
4875 	for (int i = 0;i < 32;i++)
4876 	    m_streamsHB[i] = HeartbeatDisabled;
4877     }
4878 
4879     /**
4880      * Enable heartbeat for the specifyed steam id
4881      * @param streamId The stream id
4882      */
enableHeartbeat(unsigned char streamId)4883     inline void enableHeartbeat(unsigned char streamId) {
4884 	if (streamId > 31)
4885 	    return;
4886 	m_streamsHB[streamId] = HeartbeatEnabled;
4887     }
4888 private:
4889     unsigned int m_maxRetransmit;
4890     SignallingTimer m_sendHeartbeat;
4891     SignallingTimer m_waitHeartbeatAck;
4892     unsigned char m_streamsHB[32];
4893 };
4894 
4895 /**
4896  * Generic client side (ASP) Signalling Transport User Adaptation component
4897  * @short Client side SIGTRAN User Adaptation component
4898  */
4899 class YSIG_API SIGAdaptClient : public SIGAdaptation
4900 {
4901     friend class SIGAdaptUser;
4902     YCLASS(SIGAdaptClient,SIGAdaptation)
4903 public:
4904     /**
4905      * ASP Client states
4906      */
4907     enum AspState {
4908 	AspDown = 0,
4909 	AspUpRq,
4910 	AspUp,
4911 	AspActRq,
4912 	AspActive
4913     };
4914 
4915     /**
4916      * Method called when the transport status has been changed
4917      * @param status Status of the transport causing the notification
4918      */
4919     virtual void notifyLayer(SignallingInterface::Notification status);
4920 
4921 protected:
4922     /**
4923      * Constructs an uninitialized User Adaptation client component
4924      * @param name Name of this component
4925      * @param params Optional pointer to creation parameters
4926      * @param payload SCTP payload code, ignored for other transports
4927      * @param port SCTP/TCP/UDP default port used for transport
4928      */
4929     explicit SIGAdaptClient(const char* name = 0, const NamedList* params = 0,
4930 	u_int32_t payload = 0, u_int16_t port = 0);
4931 
4932     /**
4933      * Process Management messages as ASP
4934      * @param msgType Type of the message, depends on the class
4935      * @param msg Message data, may be empty
4936      * @param streamId Identifier of the stream the message was received on
4937      * @return True if the message was handled
4938      */
4939     virtual bool processMgmtMSG(unsigned char msgType, const DataBlock& msg, int streamId);
4940 
4941     /**
4942      * Process ASP State Maintenance messages as ASP
4943      * @param msgType Type of the message, depends on the class
4944      * @param msg Message data, may be empty
4945      * @param streamId Identifier of the stream the message was received on
4946      * @return True if the message was handled
4947      */
4948     virtual bool processAspsmMSG(unsigned char msgType, const DataBlock& msg, int streamId);
4949 
4950     /**
4951      * Process ASP Traffic Maintenance messages as ASP
4952      * @param msgType Type of the message, depends on the class
4953      * @param msg Message data, may be empty
4954      * @param streamId Identifier of the stream the message was received on
4955      * @return True if the message was handled
4956      */
4957     virtual bool processAsptmMSG(unsigned char msgType, const DataBlock& msg, int streamId);
4958 
4959     /**
4960      * Traffic activity state change notification
4961      * @param active True if the ASP is active and traffic is allowed
4962      */
4963     virtual void activeChange(bool active);
4964 
4965     /**
4966      * Check if the ASP is Up
4967      * @return True if the ASPSM is in UP state
4968      */
aspUp()4969     inline bool aspUp() const
4970 	{ return m_state >= AspUp; }
4971 
4972     /**
4973      * Check if the ASP is Active
4974      * @return True if the ASPTM is in ACTIVE state
4975      */
aspActive()4976     inline bool aspActive() const
4977 	{ return m_state >= AspActive; }
4978 
4979     /**
4980      * Request activation of the ASP
4981      * @return True if ASP activation started, false on failure
4982      */
4983     bool activate();
4984 
4985     /**
4986      * Set the state of the ASP, notify user components of changes
4987      * @param state New state of the ASP
4988      * @param notify True to notify user layers, false if the changes are internal
4989      */
4990     void setState(AspState state, bool notify = true);
4991 
4992     /**
4993      * Get access to the list of Adaptation Users of this component
4994      * @return Reference to the list of Adaptation Users
4995      */
users()4996     inline ObjList& users()
4997 	{ return m_users; }
4998 
4999     /**
5000      * ASP Identifier for ASPSM UP messages
5001      */
5002     int32_t m_aspId;
5003 
5004     /**
5005      * Traffic mode for ASPTM ACTIVE messages
5006      */
5007     TrafficMode m_traffic;
5008 
5009 private:
5010     void attach(SIGAdaptUser* user);
5011     void detach(SIGAdaptUser* user);
5012     ObjList m_users;
5013     AspState m_state;
5014 };
5015 
5016 /**
5017  * Generic server side (SG) Signalling Transport User Adaptation component
5018  * @short Server side SIGTRAN User Adaptation component
5019  */
5020 class YSIG_API SIGAdaptServer : public SIGAdaptation
5021 {
YCLASS(SIGAdaptServer,SIGAdaptation)5022     YCLASS(SIGAdaptServer,SIGAdaptation)
5023 protected:
5024     /**
5025      * Constructs an uninitialized User Adaptation server component
5026      * @param name Name of this component
5027      * @param params Optional pointer to creation parameters
5028      * @param payload SCTP payload code, ignored for other transports
5029      * @param port SCTP/TCP/UDP default port used for transport
5030      */
5031     inline explicit SIGAdaptServer(const char* name = 0, const NamedList* params = 0,
5032 	u_int32_t payload = 0, u_int16_t port = 0)
5033 	: SIGAdaptation(name,params,payload,port)
5034 	{ }
5035 
5036     /**
5037      * Process Management messages as SG
5038      * @param msgType Type of the message, depends on the class
5039      * @param msg Message data, may be empty
5040      * @param streamId Identifier of the stream the message was received on
5041      * @return True if the message was handled
5042      */
5043     virtual bool processMgmtMSG(unsigned char msgType, const DataBlock& msg, int streamId);
5044 
5045     /**
5046      * Process ASP State Maintenance messages as SG
5047      * @param msgType Type of the message, depends on the class
5048      * @param msg Message data, may be empty
5049      * @param streamId Identifier of the stream the message was received on
5050      * @return True if the message was handled
5051      */
5052     virtual bool processAspsmMSG(unsigned char msgType, const DataBlock& msg, int streamId);
5053 
5054     /**
5055      * Process ASP Traffic Maintenance messages as SG
5056      * @param msgType Type of the message, depends on the class
5057      * @param msg Message data, may be empty
5058      * @param streamId Identifier of the stream the message was received on
5059      * @return True if the message was handled
5060      */
5061     virtual bool processAsptmMSG(unsigned char msgType, const DataBlock& msg, int streamId);
5062 };
5063 
5064 /**
5065  * An interface to a Signalling Transport Adaptation user
5066  * @short Abstract SIGTRAN Adaptation user
5067  */
5068 class YSIG_API SIGAdaptUser
5069 {
5070     friend class SIGAdaptClient;
5071 public:
5072     /**
5073      * Destructor
5074      */
5075     virtual ~SIGAdaptUser();
5076 
5077 protected:
5078     /**
5079      * Default constructor
5080      */
SIGAdaptUser()5081     inline SIGAdaptUser()
5082 	: m_autostart(false), m_streamId(1), m_adaptation(0)
5083 	{ }
5084 
5085     /**
5086      * Get the User Adaptation to which this component belongs
5087      * @return Pointer to the User Adaptation layer
5088      */
adaptation()5089     inline SIGAdaptClient* adaptation() const
5090 	{ return m_adaptation; }
5091 
5092     /**
5093      * Get the transport of the user adaptation component
5094      * @return Pointer to the transport layer or NULL
5095      */
transport()5096     inline SIGTransport* transport() const
5097 	{ return m_adaptation ? m_adaptation->transport() : 0; }
5098 
5099     /**
5100      * Set the User Adaptation to which this component belongs
5101      * @param adapt Pointer to the new User Adaptation layer
5102      */
5103     void adaptation(SIGAdaptClient* adapt);
5104 
5105     /**
5106      * Traffic activity state change notification
5107      * @param active True if the ASP is active and traffic is allowed
5108      */
5109     virtual void activeChange(bool active) = 0;
5110 
5111     /**
5112      * Request activation of the ASP
5113      * @return True if ASP activation started, false on failure
5114      */
activate()5115     inline bool activate()
5116 	{ return m_adaptation && m_adaptation->activate(); }
5117 
5118     /**
5119      * Check if the ASP is Up
5120      * @return True if the ASPSM is in UP state
5121      */
aspUp()5122     inline bool aspUp() const
5123 	{ return m_adaptation && m_adaptation->aspUp(); }
5124 
5125     /**
5126      * Check if the ASP is Active
5127      * @return True if the ASPTM is in ACTIVE state
5128      */
aspActive()5129     inline bool aspActive() const
5130 	{ return m_adaptation && m_adaptation->aspActive(); }
5131 
5132     /**
5133      * Obtain the stream id to use for data messages
5134      * @return The stream id
5135      */
getStreamId()5136     inline unsigned char getStreamId()
5137 	{ return m_streamId; }
5138 
5139     /**
5140      * Automatically start on init flag
5141      */
5142     bool m_autostart;
5143 
5144     /**
5145      * The SCTP streamId
5146      */
5147     unsigned char m_streamId;
5148 
5149 private:
5150     SIGAdaptClient* m_adaptation;
5151 };
5152 
5153 /**
5154  * An interface to a SS7 Application Signalling Part user
5155  * @short Abstract SS7 ASP user interface
5156  */
5157 class YSIG_API ASPUser
5158 {
5159 };
5160 
5161 /**
5162  * An interface to a SS7 SCCP Global Title Translation
5163  * @short Abstract SS7 SCCP GTT interface
5164  */
5165 class YSIG_API GTT : virtual public SignallingComponent
5166 {
5167 public:
5168     /**
5169      * Constructor
5170      */
5171     GTT(const NamedList& config);
5172 
5173     /**
5174      * Destructor
5175      */
5176     virtual ~GTT();
5177 
5178     /**
5179      * Route a SCCP message based on Global Title
5180      * @param gt The original global title used for message routing
5181      * @param prefix Optional prefix for gt params
5182      * @param nextPrefix Optional prefix for gt params
5183      * @return A new SCCP called party address or null if no route was found.
5184      */
5185     virtual NamedList* routeGT(const NamedList& gt, const String& prefix, const String& nextPrefix);
5186 
5187     /**
5188      * Initialize this GTT
5189      */
5190     virtual bool initialize(const NamedList* config);
5191 
5192     /**
5193      * Attach a SCCP to us
5194      * @param sccp Pointer to the SCCP to use
5195      */
5196     virtual void attach(SCCP* sccp);
5197 
5198     /**
5199      * Request to update Translations tables.
5200      * Called when a remote pointcode or ssn has become reachable / unreachable
5201      * @param params List of parameters that fired this request
5202      */
updateTables(const NamedList & params)5203     virtual void updateTables(const NamedList& params)
5204 	{ }
5205 
5206     /**
5207      * Retrieve the SCCP attached to this translator
5208      * @return Pointer to the attached SCCP
5209      */
sccp()5210     inline SCCP* sccp() const
5211 	{ return m_sccp; }
5212 
5213 protected:
5214     virtual void destroyed();
5215 
5216 private:
5217     SCCP* m_sccp;
5218 
5219 };
5220 
5221 /**
5222  * An interface to a SS7 Signalling Connection Control Part
5223  * @short Abstract SS7 SCCP interface
5224  */
5225 class YSIG_API SCCP : virtual public SignallingComponent
5226 {
YCLASS(SCCP,SignallingComponent)5227     YCLASS(SCCP,SignallingComponent)
5228     friend class SCCPManagement;
5229 public:
5230 
5231     enum Type {                     // used in management status method                                 Flow
5232          CoordinateRequest         = 0, // Request that a subsystem to go oos (out of service)              (User->SCCP)
5233          CoordinateConfirm         = 1, // Confirmation that a subsystem can go oos                         (SCCP->User)
5234          CoordinateIndication      = 2, // Indication that a subsystem requires to go oos                   (SCCP->User)
5235          CoordinateResponse        = 3, // Response to a subsystem requires to go oos                       (User->SCCP)
5236          StatusIndication          = 4, // Indication form SCCP that a subsystem status has been changed    (SCCP->User)
5237          StatusRequest             = 5, // Indication from a user that a subsystem status has been changed  (User->SCCP)
5238          PointCodeStatusIndication = 6, // Indication to User that a point code is available / unavailable  (SCCP->User)
5239          TraficIndication          = 7, // ANSI only! Indication that a traffic mix has been detected       (SCCP->User).
5240          SubsystemStatus           = 8, // Request from sccp t users to find the status of a local subsystem
5241      };
5242 
5243     /**
5244      * Constructor
5245      */
5246     SCCP();
5247 
5248     /**
5249      * Destructor
5250      */
5251     virtual ~SCCP();
5252 
5253     /**
5254      * Send a message
5255      * @param data Data to be transported trough SCCP protocol
5256      * @param params SCCP parameters
5257      * SCCP parameters :
5258      * MessageReturn : boolean / integer True or 0x08 to return message on error. NOTE int values should me below 0x0f
5259      * sequenceControl : boolean. True to send messages in sequence
5260      * LocalPC : integer. Local pointcode
5261      * RemotePC : integer. Remote pointcode
5262      * Address Parameter:
5263      * 	Address parameter starts with : CallingPartyAddress or CalledPartyAddress followed by:
5264      *	    .ssn             : integer (0-255) Subsequence number
5265      *	    .pointcode       : integer Packed pointcode
5266      *	    .gt              : string The digits of the global title
5267      *	    .gt.plan         : integer GT numbering plan
5268      *	    .gt.encoding     : integer GT encoding scheme
5269      *	    .gt.translation  : integer GT Translation type
5270      *	    .gt.nature       : integer Gt nature of address indicator (ITU only)
5271      * Importance : integer (0-7) Importance of the message! (ITU only)
5272      */
5273     virtual int sendMessage(DataBlock& data, const NamedList& params);
5274 
5275     /**
5276       * Receive management information from attached users.
5277       * @param type The type of management message
5278       * @param params List of parameters (Affected subsystem [M])
5279       * @return True if the notification was processed
5280       */
5281      virtual bool managementStatus(Type type, NamedList& params);
5282 
5283     /**
5284      * Attach an user to this SS7 SCCP
5285      * @param user Pointer to the SCCP user
5286      */
5287     virtual void attach(SCCPUser* user);
5288 
5289     /**
5290      * Detach an user from this SS7 SCCP
5291      * @param user Pointer to the SCCP user
5292      */
5293     virtual void detach(SCCPUser* user);
5294 
5295     /**
5296      * Attach an Global Title Translator to this SS7 SCCP
5297      * @param gtt Pointer to the Global Title Translator
5298      */
5299     virtual void attachGTT(GTT* gtt);
5300 
5301     /**
5302      * Obtain the dictionary for notifications types
5303      * @return Pointer to the notification types dictionary
5304      */
5305     static const TokenDict* notifTypes();
5306 
updateTables(const NamedList & params)5307     virtual void updateTables(const NamedList& params)
5308 	{
5309 	    Lock lock(m_translatorLocker);
5310 	    if (m_translator)
5311 		m_translator->updateTables(params);
5312 	}
5313 protected:
5314     /**
5315      * Translate a Global Title
5316      * @param params The Global Title content
5317      * @param prefix The prefix of the global title content parameters
5318      * @param nextPrefix Other prefix of the global title content parameters
5319      * @return a new SCCP route or 0 is no route was found
5320      */
5321     NamedList* translateGT(const NamedList& params, const String& prefix,
5322 	    const String& nextPrefix);
5323 
5324     /**
5325      * Send a SCCP message to users list for processing
5326      * @param data The message data
5327      * @param params The list of parameters
5328      * @param ssn The ssn of the SCCP user
5329      * @return HandledMSU enum value
5330      */
5331     HandledMSU pushMessage(DataBlock& data, NamedList& params, int ssn);
5332 
5333     /**
5334      * Notify the users that a message failed to be delivered to destination
5335      * @param data The message data
5336      * @param params The list of parameters
5337      * @param ssn The ssn of the SCCP user
5338      * @return HandledMSU enum value
5339      */
5340     HandledMSU notifyMessage(DataBlock& data, NamedList& params, int ssn);
5341 
5342     /**
5343      * Broadcast a management message to all attached users
5344      * @param type The type of notification
5345      * @param params The list of parameters
5346      * @return True if at least one user processed the message
5347      */
5348     bool managementMessage(Type type, NamedList& params);
5349 
5350     /**
5351      * Check if this sccp is an endpoint
5352      * @return False
5353      */
isEndpoint()5354     virtual bool isEndpoint()
5355 	{ return false; }
5356 
5357     /**
5358      * Copy the parameters returned by Global Title Translator in the SCCP Message
5359      * @param msg The SCCP message
5360      * @param gtParams The parameters returned by GTT
5361      */
5362     void resolveGTParams(SS7MsgSCCP* msg, const NamedList* gtParams);
5363 private:
5364     ObjList m_users;
5365     Mutex m_translatorLocker;
5366     Mutex m_usersLocker;
5367     GTT* m_translator;
5368 };
5369 
5370 class YSIG_API SubsystemStatusTest : public RefObject
5371 {
YCLASS(SubsystemStatusTest,RefObject)5372     YCLASS(SubsystemStatusTest,RefObject)
5373 public:
5374     /**
5375      * Constructor
5376      * @param interval The time interval in milliseconds representing the test duration
5377      */
5378     inline SubsystemStatusTest(u_int32_t interval)
5379 	: m_interval(interval), m_statusInfo(interval), m_remoteSccp(0), m_remoteSubsystem(0),
5380 	m_markAllowed(false)
5381 	{ }
5382 
5383     /**
5384      * Destructor
5385      */
5386     virtual ~SubsystemStatusTest();
5387 
5388     /**
5389      * Start this subsystem status test
5390      * @param remoteSccp The remote sccp where the subsystem is located
5391      * @param rSubsystem The remote subsystem for witch the test is performed
5392      * @return True if the test has successfully started
5393      */
5394     bool startTest(SccpRemote* remoteSccp, SccpSubsystem* rSubsystem);
5395 
5396     /**
5397      * Obtain the remote SCCP of this status test
5398      * @return Remote Sccp
5399      */
getRemote()5400     inline SccpRemote* getRemote()
5401 	{ return m_remoteSccp; };
5402 
5403     /**
5404      * Helper method to check for timeouts
5405      * @return True if timed out
5406      */
timeout()5407     inline bool timeout()
5408 	{ return m_statusInfo.started() && m_statusInfo.timeout(); }
5409     /**
5410      * Get the subsystem who caused this test
5411      * @return The subsystem for who this test was initiated
5412      */
getSubsystem()5413     inline SccpSubsystem* getSubsystem()
5414 	{ return m_remoteSubsystem; }
5415 
5416     /**
5417      * Restart subsystem status test with exponential backoff
5418      */
5419     void restartTimer();
5420 
5421     /**
5422      * Helper method used to find if we should mark the remote subsystem as allowed at the end of the test
5423      */
markAllowed()5424     inline bool markAllowed()
5425 	{ return m_markAllowed; }
5426 
5427     /**
5428      * Mark the tested subsystem as allowed at the end of the test
5429      * @param allowed True to set the subsystem allowed at the end of the test
5430      */
setAllowed(bool allowed)5431     inline void setAllowed(bool allowed)
5432 	{ m_markAllowed = allowed; }
5433 private:
5434     u_int32_t m_interval;
5435     SignallingTimer m_statusInfo;
5436     SccpRemote* m_remoteSccp;
5437     SccpSubsystem* m_remoteSubsystem;
5438     bool m_markAllowed;
5439 };
5440 
5441 /**
5442  * An interface to a SS7 Signalling Connection Control Part user
5443  * @short Abstract SS7 SCCP user interface
5444  */
5445 class YSIG_API SCCPUser : virtual public SignallingComponent
5446 {
5447     YCLASS(SCCPUser,SignallingComponent)
5448 public:
5449     /**
5450      * Constructor
5451      */
5452     SCCPUser(const NamedList& params);
5453 
5454     /**
5455      * Destructor, detaches from the SCCP implementation
5456      */
5457     virtual ~SCCPUser();
5458 
5459     /**
5460      * Configure and initialize the component and any subcomponents it may have
5461      * @param config Optional configuration parameters override
5462      * @return True if the component was initialized properly
5463      */
5464     virtual bool initialize(const NamedList* config);
5465 
5466     /**
5467      * Send a message to SCCP for transport
5468      * @param data User data
5469      * @param params SCCP parameters
5470      * Note! If the request is made with return option set there is no warranty that a notification
5471      * will be received in case that the message failed to be delivered
5472      */
5473     virtual bool sendData(DataBlock& data, NamedList& params);
5474 
5475     /**
5476      * Send a request / notification from users to sccp regarding a subsystem status
5477      * <pre>
5478       Type : CoordinateRequest -> Request from a user to sccp to go OOS
5479            params: "ssn" The ssn to go OOS
5480      	           "smi" Subsystem multiplicity indicator
5481      		   "backups" The number of backup subsystems
5482      		   "backup.N.ssn" The ssn of the backup subsystem number N
5483      		   "backup.N.pointcode" The ssn of the backup subsystem number N
5484       Type : CoordinateResponse -> Indication from a user to sccp in response to CoordinateIndication<
5485            params: "ssn" The subsystem number that approved the indication
5486                    "smi" 0
5487       Type : StatusRequest -> Request from user to sccp to update a subsystem status
5488        	   params: "ssn" The affected subsystem number
5489        		   "smi" 0;
5490       		   "subsystem-status": The requested status: UserOutOfService, UserInService
5491       </pre>
5492      * @param type The type of request / notification
5493      * @param params List of parameters
5494      * @return True if sccp management has processed the request / notification.
5495      */
5496     virtual bool sccpNotify(SCCP::Type type, NamedList& params);
5497 
5498     /**
5499      * Notification from SCCP that a message has arrived
5500      * @param data Received user data
5501      * @param params SCCP parameters
5502      * @return True if this user has processed the message, false otherwise
5503      */
5504      virtual HandledMSU receivedData(DataBlock& data, NamedList& params);
5505 
5506     /**
5507      * Notification from SCCP that a message failed to arrive to it's destination
5508      * @param data User data send.
5509      * @param params SCCP parameters
5510      * Note! The data may not contain the full message block previously sent (in case of SCCP segmentation),
5511      * but it must always must contain the first segment
5512      */
5513      virtual HandledMSU notifyData(DataBlock& data, NamedList& params);
5514 
5515      /**
5516       * Notification from SCCP management to a sccp user about pointcodes status, OOS responses/indications, subsystems status
5517       * <pre>
5518       Type: CoordinateIndication -> Indication from a remote SCCP User that requires to go OOS
5519           params: "ssn" -> The subsystem number of the remote SCCP User
5520       	          "smi" -> Subsystem multiplicity indicator
5521       	          "pointcode" -> The pointcode of the remote SCCP User
5522       Type: SubsystemStatus -> Request from SCCP Management to SCCP Users to query the specified subsystem status.
5523                                This happens when a SubsystemStatusTest(SST) message is received
5524       	  params: "ssn" -> The requested subsystem
5525           returned params:
5526       	          "subsystem-status" -> The status of the subsystem: UserOutOfService, UserInService
5527       	        		        Missing = UserOutOfService
5528       </pre>
5529       * @param type The type of notification
5530       * @param params List of parameters
5531       * @return False on error
5532       */
5533      virtual bool managementNotify(SCCP::Type type, NamedList& params);
5534 
5535     /**
5536      * Attach as user to a SCCP
5537      * @param sccp Pointer to the SCCP to use
5538      * NOTE: This method will deref the pointer if is the same with the one that we already have!!
5539      * When this method is called the sccp pointer reference counter must be incremented for this
5540      * SCCPUser.
5541      */
5542     virtual void attach(SCCP* sccp);
5543 
5544     /**
5545      * Retrieve the SCCP to which this component is attached
5546      * @return Pointer to the attached SCCP or NULL
5547      */
sccp()5548     inline SCCP* sccp() const
5549 	{ return m_sccp; }
5550 
5551 protected:
5552     virtual void destroyed();
5553 
5554 private:
5555     SCCP* m_sccp;
5556     Mutex m_sccpMutex;
5557     int m_sls;
5558 };
5559 
5560 /**
5561  * An interface to a SS7 Transactional Capabilities Application Part user
5562  * @short Abstract SS7 TCAP user interface
5563  */
5564 class YSIG_API TCAPUser : public SignallingComponent
5565 {
YCLASS(TCAPUser,SignallingComponent)5566     YCLASS(TCAPUser,SignallingComponent)
5567     friend class SS7TCAP;
5568 public:
5569     TCAPUser(const char* name, const NamedList* params = 0)
5570       : SignallingComponent(name,params),
5571 	m_tcap(0)
5572 	{}
5573     /**
5574      * Destructor, detaches from the TCAP implementation
5575      */
5576     virtual ~TCAPUser();
5577 
5578     /**
5579      * Attach as user to a SS7 TCAP
5580      * @param tcap Pointer to the TCAP to use
5581      */
5582     virtual void attach(SS7TCAP* tcap);
5583 
5584     /**
5585      * Receive a TCAP message from TCAP layer
5586      * @param params The message in NamedList form
5587      * @return True or false if the message was processed by this user
5588      */
5589     virtual bool tcapIndication(NamedList& params);
5590 
5591     /**
5592      * Retrieve the TCAP to which this user is attached
5593      * @return Pointer to a SS7 TCAP interface or NULL
5594      */
tcap()5595     inline SS7TCAP* tcap() const
5596 	{ return m_tcap; }
5597 
5598     /**
5599      * Received a management notification from SCCP layer
5600      * @param type SCCP management notification type
5601      * @param params Management notification params
5602      * @return True or false if the notification was handled bu this user
5603      */
5604     virtual bool managementNotify(SCCP::Type type, NamedList& params);
5605 
5606     /**
5607      * Get TCAP user management state
5608      * @return The state of the user
5609      */
5610     virtual int managementState();
5611 
5612     /**
5613      * This method is called to clean up and destroy the object after the
5614      *  reference counter becomes zero
5615      */
5616     virtual void  destroyed();
5617 
5618 protected:
setTCAP(SS7TCAP * tcap)5619     inline void setTCAP(SS7TCAP* tcap)
5620     {
5621 	Lock l(m_tcapMtx);
5622 	m_tcap = tcap;
5623     }
5624 
5625 private:
5626     SS7TCAP* m_tcap;
5627     Mutex m_tcapMtx;
5628 };
5629 
5630 
5631 /**
5632  * An user of a Layer 2 (data link) SS7 message transfer part
5633  * @short Abstract user of SS7 layer 2 (data link) message transfer part
5634  */
5635 class YSIG_API SS7L2User : virtual public SignallingComponent
5636 {
5637     YCLASS(SS7L2User,SignallingComponent)
5638     friend class SS7Layer2;
5639 public:
5640     /**
5641      * Attach a SS7 Layer 2 (data link) to the user component
5642      * @param link Pointer to data link to attach
5643      */
5644     virtual void attach(SS7Layer2* link) = 0;
5645 
5646     /**
5647      * Detach a SS7 Layer 2 (data link) from the user component
5648      * @param link Pointer to data link to detach
5649      */
5650     virtual void detach(SS7Layer2* link) = 0;
5651 
5652 protected:
5653     /**
5654      * Process a MSU received from the Layer 2 component
5655      * @param msu Message data, starting with Service Indicator Octet
5656      * @param link Data link that delivered the MSU
5657      * @param sls Signalling Link the MSU was received from
5658      * @return True if the MSU was processed
5659      */
5660     virtual bool receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls) = 0;
5661 
5662     /**
5663      * Process a MSU recovered from the Layer 2 component after failure
5664      * @param msu Message data, starting with Service Indicator Octet
5665      * @param link Data link from where the MSU was recovered
5666      * @param sls Signalling Link the MSU was recovered from
5667      * @return True if the MSU was processed
5668      */
5669     virtual bool recoveredMSU(const SS7MSU& msu, SS7Layer2* link, int sls) = 0;
5670 
5671     /**
5672      * Process a notification generated by the attached data link
5673      * @param link Data link that generated the notification
5674      */
5675     virtual void notify(SS7Layer2* link) = 0;
5676 };
5677 
5678 /**
5679  * An interface to a Layer 2 (data link) SS7 message transfer part
5680  * @short Abstract SS7 layer 2 (data link) message transfer part
5681  */
5682 class YSIG_API SS7Layer2 : virtual public SignallingComponent
5683 {
YCLASS(SS7Layer2,SignallingComponent)5684     YCLASS(SS7Layer2,SignallingComponent)
5685     friend class SS7MTP3;
5686 public:
5687     /**
5688      * LSSU Status Indications
5689      */
5690     enum LinkStatus {
5691 	OutOfAlignment = 0,
5692 	NormalAlignment = 1,
5693 	EmergencyAlignment = 2,
5694 	OutOfService = 3,
5695 	ProcessorOutage = 4,
5696 	Busy = 5,
5697 	// short versions as defined by RFC
5698 	O = OutOfAlignment,
5699 	N = NormalAlignment,
5700 	E = EmergencyAlignment,
5701 	OS = OutOfService,
5702 	PO = ProcessorOutage,
5703 	B = Busy,
5704     };
5705 
5706     /**
5707      * Control primitives
5708      */
5709     enum Operation {
5710 	// take link out of service
5711 	Pause  = 0x100,
5712 	// start link operation, align if it needs to
5713 	Resume = 0x200,
5714 	// start link, force realignment
5715 	Align  = 0x300,
5716 	// get operational status
5717 	Status = 0x400,
5718     };
5719 
5720     /**
5721      * Link inhibition reason bits
5722      */
5723     enum Inhibitions {
5724 	// basic maintenance checks not performed
5725 	Unchecked = 0x01,
5726 	// management inactivation
5727 	Inactive  = 0x02,
5728 	// locally inhibited
5729 	Local     = 0x04,
5730 	// remotely inhibited
5731 	Remote    = 0x08,
5732     };
5733 
5734     /**
5735      * Push a Message Signal Unit down the protocol stack
5736      * @param msu Message data, starting with Service Indicator Octet
5737      * @return True if message was successfully queued
5738      */
5739     virtual bool transmitMSU(const SS7MSU& msu) = 0;
5740 
5741     /**
5742      * Remove the MSUs waiting in the transmit queue and return them
5743      * @param sequence First sequence number to recover, flush earlier packets
5744      */
recoverMSU(int sequence)5745     virtual void recoverMSU(int sequence)
5746 	{ }
5747 
5748     /**
5749      * Retrieve the current link status indications
5750      * @return Link status indication bits
5751      */
5752     virtual unsigned int status() const;
5753 
5754     /**
5755      * Get the name of a Layer 2 status
5756      * @param status Status indication value
5757      * @param brief Request to return the short status name
5758      * @return String describing the status
5759      */
5760     virtual const char* statusName(unsigned int status, bool brief) const;
5761 
5762     /**
5763      * Get the name of the current local Layer 2 status
5764      * @param brief Request to return the short status name
5765      * @return String describing the status
5766      */
5767     inline const char* statusName(bool brief = false) const
5768 	{ return statusName(status(),brief); }
5769 
5770     /**
5771      * Check if the link is fully operational
5772      * @return True if the link is aligned and operational
5773      */
5774     virtual bool operational() const = 0;
5775 
5776     /**
5777      * Get the uptime of the link
5778      * @return Time since link got up in seconds
5779      */
upTime()5780     unsigned int upTime() const
5781 	{ return m_lastUp ? (Time::secNow() - m_lastUp) : 0; }
5782 
5783     /**
5784      * Attach a Layer 2 user component to the data link. Detach from the old one if valid
5785      * @param l2user Pointer to Layer 2 user component to attach
5786      */
5787     void attach(SS7L2User* l2user);
5788 
5789     /**
5790      * Get the Layer 2 user component that works with this data link
5791      * @return Pointer to the user component to which the messages are sent
5792      */
user()5793     inline SS7L2User* user() const
5794 	{ return m_l2user; }
5795 
5796     /**
5797      * Get the Signalling Link Selection number allocated to this link
5798      * @return SLS value assigned by the upper layer
5799      */
sls()5800     inline int sls() const
5801 	{ return m_sls; }
5802 
5803     /**
5804      * Assign a new Signalling Link Selection number
5805      * @param linkSel New SLS to assign to this link
5806      */
sls(int linkSel)5807     inline void sls(int linkSel)
5808 	{ if ((m_sls < 0) || !m_l2user) m_sls = linkSel; }
5809 
5810     /**
5811      * Retrieve the inhibition flags set by MTP3 Management
5812      * @return Inhibition flags ORed together, zero if not inhibited
5813      */
inhibited()5814     inline int inhibited() const
5815 	{ return m_inhibited; }
5816 
5817     /**
5818      * Check some of the inhibition flags set by MTP3 Management
5819      * @param flags Flags to check for, ORed together
5820      * @return True if any of the specified inhibition flags is active
5821      */
inhibited(int flags)5822     inline bool inhibited(int flags) const
5823 	{ return (m_inhibited & flags) != 0; }
5824 
5825     /**
5826      * Get the current congestion level of the link
5827      * @return Congestion level, 0 if not congested, 3 if maximum congestion
5828      */
congestion()5829     virtual unsigned int congestion()
5830 	{ return m_congestion; }
5831 
5832     /**
5833      * Get the sequence number of the last MSU received
5834      * @return Last FSN received, negative if not available
5835      */
getSequence()5836     virtual int getSequence()
5837 	{ return m_lastSeqRx; }
5838 
5839     /**
5840      * Execute a control operation. Operations can change the link status or
5841      *  can query the aligned status.
5842      * @param oper Operation to execute
5843      * @param params Optional parameters for the operation
5844      * @return True if the command completed successfully, for query operations
5845      *  also indicates the data link is aligned and operational
5846      */
5847     virtual bool control(Operation oper, NamedList* params = 0);
5848 
5849     /**
5850      * Query or modify layer's settings or operational parameters
5851      * @param params The list of parameters to query or change
5852      * @return True if the control operation was executed
5853      */
5854     virtual bool control(NamedList& params);
5855 
5856 protected:
5857     /**
5858      * Constructor
5859      */
SS7Layer2()5860     inline SS7Layer2()
5861 	: m_autoEmergency(true), m_lastSeqRx(-1), m_congestion(0),
5862 	  m_l2userMutex(true,"SS7Layer2::l2user"), m_l2user(0), m_sls(-1),
5863 	  m_checkTime(0), m_checkFail(0), m_inhibited(Unchecked), m_lastUp(0),
5864 	  m_notify(false)
5865 	{ }
5866 
5867     /**
5868      * Method called periodically by the engine to keep everything alive
5869      * @param when Time to use as computing base for events and timeouts
5870      */
5871     virtual void timerTick(const Time& when);
5872 
5873     /**
5874      * Push a received Message Signal Unit up the protocol stack
5875      * @param msu Message data, starting with Service Indicator Octet
5876      * @return True if message was successfully delivered to the user component
5877      */
receivedMSU(const SS7MSU & msu)5878     inline bool receivedMSU(const SS7MSU& msu)
5879     {
5880 	m_l2userMutex.lock();
5881 	RefPointer<SS7L2User> tmp = m_l2user;
5882 	m_l2userMutex.unlock();
5883 	return tmp && tmp->receivedMSU(msu,this,m_sls);
5884     }
5885 
5886     /**
5887      * Push a recovered Message Signal Unit back up the protocol stack
5888      * @param msu Message data, starting with Service Indicator Octet
5889      * @return True if message was successfully delivered to the user component
5890      */
recoveredMSU(const SS7MSU & msu)5891     inline bool recoveredMSU(const SS7MSU& msu)
5892     {
5893 	m_l2userMutex.lock();
5894 	RefPointer<SS7L2User> tmp = m_l2user;
5895 	m_l2userMutex.unlock();
5896 	return tmp && tmp->recoveredMSU(msu,this,m_sls);
5897     }
5898 
5899     /**
5900      * Set the notify flag.
5901      * The user part will be notified on timer tick about status change
5902      */
5903     void notify();
5904 
5905     /**
5906      * Set and clear inhibition flags, method used by MTP3
5907      * @param setFlags Flag bits to set ORed together
5908      * @param clrFlags Flag bits to clear  ORed together (optional)
5909      * @return True if inhibition flags were set
5910      */
5911     bool inhibit(int setFlags, int clrFlags = 0);
5912 
5913     /**
5914      * Get a best guess of the emergency alignment requirement
5915      * @param params Optional parameters whose "emergency" is used
5916      * @param emg Default emergency state
5917      * @return True if emergency alignment should be used
5918      */
5919     bool getEmergency(NamedList* params = 0, bool emg = false) const;
5920 
5921     /**
5922      * Flag to automatically perform emergency alignment when linkset is down
5923      */
5924     bool m_autoEmergency;
5925 
5926     /**
5927      * Last received MSU sequence number, -1 if unknown, bit 24 set if long FSN
5928      */
5929     int m_lastSeqRx;
5930 
5931     /**
5932      * Current congestion level
5933      */
5934     unsigned int m_congestion;
5935 
5936 private:
5937     Mutex m_l2userMutex;
5938     SS7L2User* m_l2user;
5939     int m_sls;
5940     u_int64_t m_checkTime;
5941     int m_checkFail;
5942     int m_inhibited;
5943     u_int32_t m_lastUp;
5944     bool m_notify;                       // Notify on timer tick
5945 };
5946 
5947 /**
5948  * Keeps a packed destination point code, a network priority or a list of networks used
5949  *  to route to the enclosed destination point code
5950  * @short A SS7 MSU route
5951  */
5952 class YSIG_API SS7Route : public RefObject, public Mutex
5953 {
5954     friend class SS7Layer3;
5955     friend class SS7Router;
5956 public:
5957     /**
5958      * Route state
5959      */
5960     enum State {
5961 	Unknown       = 0x80,
5962 	// Standard route states
5963 	Prohibited    = 0x01,
5964 	Restricted    = 0x02,
5965 	Congestion    = 0x04,
5966 	Allowed       = 0x08,
5967 	// Masks for typical combinations
5968 	NotAllowed    = 0x77,
5969 	NotCongested  = 0x78,
5970 	NotRestricted = 0x7c,
5971 	NotProhibited = 0x7e,
5972 	KnownState    = 0x7f,
5973 	AnyState      = 0xff
5974     };
5975 
5976     /**
5977      * Constructor
5978      * @param packed The packed value of the destination point code
5979      * @param type The destination point code type
5980      * @param priority Optional value of the network priority
5981      * @param shift SLS right shift to apply for balancing between linksets
5982      * @param maxDataLength The maximum data that can be transported on this
5983      *        route
5984      */
5985     inline SS7Route(unsigned int packed, SS7PointCode::Type type,
5986 	    unsigned int priority = 0, unsigned int shift = 0,
5987 	    unsigned int maxDataLength = MAX_TDM_MSU_SIZE)
5988 	: Mutex(true,"SS7Route"), m_packed(packed), m_type(type),
5989 	m_priority(priority), m_shift(shift),m_maxDataLength(maxDataLength),
5990 	m_state(Unknown),m_buffering(0), m_congCount(0),m_congBytes(0)
5991 	{ m_networks.setDelete(false); }
5992 
5993     /**
5994      * Copy constructor
5995      * @param original The original route
5996      */
SS7Route(const SS7Route & original)5997     inline SS7Route(const SS7Route& original)
5998 	: Mutex(true,"SS7Route"), m_packed(original.packed()),
5999 	  m_type(original.m_type), m_priority(original.priority()),
6000 	  m_shift(original.shift()), m_maxDataLength(original.getMaxDataLength()),
6001 	  m_state(original.state()), m_buffering(0), m_congCount(0), m_congBytes(0)
6002 	{ m_networks.setDelete(false); }
6003 
6004     /**
6005      * Destructor
6006      */
~SS7Route()6007     virtual ~SS7Route()
6008 	{ }
6009 
6010     /**
6011      * Retrieve the current state of the route
6012      * @return Current route state
6013      */
state()6014     State state() const
6015 	{ return m_state; }
6016 
6017     /**
6018      * Retrieve the state names token table
6019      * @return Pointer to the token table mapping states to names
6020      */
6021     static const TokenDict* stateNames();
6022 
6023     /**
6024      * Retrieve the name of the current state
6025      * @return Name of the state, NULL if invalid
6026      */
stateName()6027     const char* stateName() const
6028 	{ return lookup(m_state,stateNames()); }
6029 
6030     /**
6031      * Retrieve the name of an arbitrary state
6032      * @param state Route state whose name to return
6033      * @return Name of the state, NULL if invalid
6034      */
stateName(State state)6035     static const char* stateName(State state)
6036 	{ return lookup(state,stateNames()); }
6037 
6038     /**
6039      * Get the priority of this route
6040      * @return Route priority, zero = highest (adjacent)
6041      */
priority()6042     unsigned int priority() const
6043 	{ return m_priority; }
6044 
6045     /**
6046      * Get the maximum data length that can be transported on this route
6047      * @return The maximum data length
6048      */
getMaxDataLength()6049     unsigned int getMaxDataLength() const
6050 	{ return m_maxDataLength; }
6051 
6052     /**
6053      * Get the packed Point Code of this route
6054      * @return Packed Point Code of the route's destination
6055      */
packed()6056     unsigned int packed() const
6057 	{ return m_packed; }
6058 
6059     /**
6060      * Get the SLS right shift for this route
6061      * @return How many bits of SLS to shift off right when selecting linkset
6062      */
shift()6063     unsigned int shift() const
6064 	{ return m_shift; }
6065 
6066     /**
6067      * Attach a network to use for this destination or change its priority.
6068      * This method is thread safe
6069      * @param network The network to attach or change priority
6070      * @param type The point code type used to get the priority from the given network or the networks already in the list
6071      */
6072     void attach(SS7Layer3* network, SS7PointCode::Type type);
6073 
6074     /**
6075      * Remove a network from the list without deleting it.
6076      * This method is thread safe
6077      * @param network The network to remove
6078      * @return False if the list of networks is empty
6079      */
6080     bool detach(SS7Layer3* network);
6081 
6082     /**
6083      * Check if this route goes to a specific network
6084      * @param network Pointer to the network to search
6085      * @return True if the network was found in the route's list
6086      */
6087     bool hasNetwork(const SS7Layer3* network);
6088 
6089     /**
6090      * Check if this route goes to a specific network
6091      * @param network Pointer to the network to search
6092      * @return True if the network was found in the route's list
6093      */
6094     bool hasNetwork(const SS7Layer3* network) const;
6095 
6096     /**
6097      * Check if the at least one network/linkset is fully operational
6098      * @param sls Signalling Link to check, negative to check if any is operational
6099      * @return True if the route has at least one linkset operational
6100      */
6101     bool operational(int sls = -1);
6102 
6103     /**
6104      * Try to transmit a MSU through one of the attached networks.
6105      * This method is thread safe
6106      * @param router The router requesting the operation (used for debug)
6107      * @param msu Message data, starting with Service Indicator Octet
6108      * @param label Routing label of the MSU
6109      * @param sls Signalling Link Selection, negative to choose best
6110      * @param source Avoided network where the packet was received from
6111      * @param states The states a network can have to be a transmission candidate
6112      * @return Link the message was successfully queued to, negative for error
6113      */
6114     int transmitMSU(const SS7Router* router, const SS7MSU& msu,
6115 	const SS7Label& label, int sls, State states, const SS7Layer3* source = 0);
6116 
6117     /**
6118      * Check the current congestion status according to Q.704 11.2.3.1
6119      * @return True if a TFC should be sent
6120      */
6121     bool congested();
6122 
6123     /**
6124      * Initiate controlled rerouting procedure, buffer user part messages for T6
6125      */
6126     void reroute();
6127 
6128 private:
6129     int transmitInternal(const SS7Router* router, const SS7MSU& msu,
6130 	const SS7Label& label, int sls, State states, const SS7Layer3* source);
6131     void rerouteCheck(u_int64_t when);
6132     void rerouteFlush();
6133     unsigned int m_packed;               // Packed destination point code
6134     SS7PointCode::Type m_type;           // The point code type
6135     unsigned int m_priority;             // Network priority for the given destination (used by SS7Layer3)
6136     unsigned int m_shift;                // SLS right shift when selecting linkset
6137     unsigned int m_maxDataLength;        // The maximum data length that can be transported on this route
6138     ObjList m_networks;                  // List of networks used to route to the given destination (used by SS7Router)
6139     State m_state;                       // State of the route
6140     u_int64_t m_buffering;               // Time when controlled rerouting ends
6141     ObjList m_reroute;                   // Controlled rerouting buffer
6142     unsigned int m_congCount;            // Congestion event count
6143     unsigned int m_congBytes;            // Congestion MSU bytes count
6144 };
6145 
6146 /**
6147  * An user of a Layer 3 (data link) SS7 message transfer part
6148  * @short Abstract user of SS7 layer 3 (network) message transfer part
6149  */
6150 class YSIG_API SS7L3User : virtual public SignallingComponent
6151 {
6152     friend class SS7Layer3;
6153     friend class SS7Router;
6154 public:
6155     /**
6156      * Attach a SS7 Layer 3 (network) to the user component
6157      * @param network Pointer to network component to attach
6158      */
6159     virtual void attach(SS7Layer3* network) = 0;
6160 
6161 protected:
6162     /**
6163      * Process a MSU received from the Layer 3 component
6164      * @param msu Message data, starting with Service Indicator Octet
6165      * @param label Routing label of the received MSU
6166      * @param network Network layer that delivered the MSU
6167      * @param sls Signalling Link the MSU was received from
6168      * @return Result of MSU processing
6169      */
6170     virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls) = 0;
6171 
6172     /**
6173      * Reroute a recovered Message Signal Unit
6174      * @param msu Message data, starting with Service Indicator Octet
6175      * @param label Routing label of the recovered MSU
6176      * @param network Network layer that recovered the MSU
6177      * @param sls Signalling Link the MSU was recovered from
6178      * @return True if the MSU was successfully rerouted
6179      */
recoveredMSU(const SS7MSU & msu,const SS7Label & label,SS7Layer3 * network,int sls)6180     virtual bool recoveredMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls)
6181 	{ return false; }
6182 
6183     /**
6184      * Notification for receiving User Part Unavailable
6185      * @param type Type of Point Code
6186      * @param node Node on which the User Part is unavailable
6187      * @param part User Part (service) reported unavailable
6188      * @param cause Unavailability cause - Q.704 15.17.5
6189      * @param label Routing label of the UPU message
6190      * @param sls Signaling link the UPU was received on
6191      */
receivedUPU(SS7PointCode::Type type,const SS7PointCode node,SS7MSU::Services part,unsigned char cause,const SS7Label & label,int sls)6192     virtual void receivedUPU(SS7PointCode::Type type, const SS7PointCode node,
6193 	SS7MSU::Services part, unsigned char cause, const SS7Label& label, int sls)
6194 	{ }
6195 
6196     /**
6197      * Process a notification generated by the attached network layer
6198      * @param link Network or linkset that generated the notification
6199      * @param sls Signalling Link that generated the notification, negative if none
6200      */
6201     virtual void notify(SS7Layer3* link, int sls);
6202 
6203     /**
6204      * Process route status changed notifications
6205      * @param type Type of Point Code
6206      * @param node Destination node witch state has changed
6207      * @param state The new route state
6208      */
routeStatusChanged(SS7PointCode::Type type,const SS7PointCode & node,SS7Route::State state)6209     virtual void routeStatusChanged(SS7PointCode::Type type, const SS7PointCode& node, SS7Route::State state)
6210 	{ }
6211 
6212     /**
6213      * Retrieve the route table of a network for a specific Point Code type
6214      * @param network Network layer to retrieve routes from
6215      * @param type Point Code type of the desired table
6216      * @return Pointer to the list of SS7Route or NULL if no such route
6217      */
6218     static ObjList* getNetRoutes(SS7Layer3* network, SS7PointCode::Type type);
6219 
6220     /**
6221      * Retrieve the route table of a network for a specific Point Code type
6222      * @param network Network layer to retrieve routes from
6223      * @param type Point Code type of the desired table
6224      * @return Pointer to the list of SS7Route or NULL if no such route
6225      */
6226     static const ObjList* getNetRoutes(const SS7Layer3* network, SS7PointCode::Type type);
6227 };
6228 
6229 /**
6230  * An interface to a Layer 3 (network) SS7 message transfer part
6231  * @short Abstract SS7 layer 3 (network) message transfer part
6232  */
6233 class YSIG_API SS7Layer3 : virtual public SignallingComponent
6234 {
6235     YCLASS(SS7Layer3,SignallingComponent)
6236     friend class SS7L3User;
6237     friend class SS7Router;              // Access the data members to build the routing table
6238     friend class SS7Route;
6239 public:
6240     /**
6241      * Destructor
6242      */
~SS7Layer3()6243     virtual ~SS7Layer3()
6244 	 { attach(0); }
6245 
6246     /**
6247      * Initialize the network layer, connect it to the SS7 router
6248      * @param config Optional configuration parameters override
6249      * @return True if the network was initialized properly
6250      */
6251     virtual bool initialize(const NamedList* config);
6252 
6253     /**
6254      * Push a Message Signal Unit down the protocol stack
6255      * @param msu Message data, starting with Service Indicator Octet
6256      * @param label Routing label of the MSU to use in routing
6257      * @param sls Signalling Link Selection, negative to choose best
6258      * @return Link the message was successfully queued to, negative for error
6259      */
6260     virtual int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1) = 0;
6261 
6262     /**
6263      * Check if the network/linkset is fully operational
6264      * @param sls Signalling Link to check, negative to check if any is operational
6265      * @return True if the linkset is enabled and operational
6266      */
6267     virtual bool operational(int sls = -1) const = 0;
6268 
6269     /**
6270      * Retrieve inhibition flags of a specific link
6271      * @param sls Signalling Link to check
6272      * @return Inhibitions of the specified link, zero if not inhibited
6273      */
inhibited(int sls)6274     virtual int inhibited(int sls) const
6275 	{ return 0; }
6276 
6277     /**
6278      * Check some of the inhibition flags of a specific link
6279      * @param sls Signalling Link to check
6280      * @param flags Flags to check for, ORed together
6281      * @return True if any of the specified inhibition flags is active
6282      */
inhibited(int sls,int flags)6283     inline bool inhibited(int sls, int flags) const
6284 	{ return (inhibited(sls) & flags) != 0; }
6285 
6286     /**
6287      * Set and clear inhibition flags on the links
6288      * @param sls Signalling Link to modify
6289      * @param setFlags Flag bits to set ORed together
6290      * @param clrFlags Flag bits to clear ORed together (optional)
6291      * @return True if inhibition flags were set
6292      */
6293     virtual bool inhibit(int sls, int setFlags, int clrFlags = 0)
6294 	{ return false; }
6295 
6296     /**
6297      * Check if a link is operational and not inhibited
6298      * @param sls Signalling Link to check
6299      * @param ignore Inhibition flags to ignore, ORed together
6300      * @return True if the link is operational and not inhibited
6301      */
6302     inline bool inService(int sls, int ignore = 0)
6303 	{ return operational(sls) && !inhibited(sls,~ignore); }
6304 
6305     /**
6306      * Get the current congestion level of a link
6307      * @param sls Signalling Link to check for congestion, -1 for maximum
6308      * @return Congestion level, 0 if not congested, 3 if maximum congestion
6309      */
congestion(int sls)6310     virtual unsigned int congestion(int sls)
6311 	{ return 0; }
6312 
6313     /**
6314      * Get the sequence number of the last MSU received on a link
6315      * @param sls Signalling Link to retrieve MSU number from
6316      * @return Last FSN received, negative if not available
6317      */
getSequence(int sls)6318     virtual int getSequence(int sls) const
6319 	{ return -1; }
6320 
6321     /**
6322      * Remove the MSUs waiting in the transmit queue and return them
6323      * @param sls Signalling Link to recover MSUs from
6324      * @param sequence First sequence number to recover, flush earlier packets
6325      */
recoverMSU(int sls,int sequence)6326     virtual void recoverMSU(int sls, int sequence)
6327 	{ }
6328 
6329     /**
6330      * Initiate a MTP restart procedure if supported by the network layer
6331      * @return True if a restart was initiated
6332      */
restart()6333     virtual bool restart()
6334 	{ return false; }
6335 
6336     /**
6337      * Attach a Layer 3 user component to this network. Detach the old user if valid.
6338      * Attach itself to the given user
6339      * @param l3user Pointer to Layer 3 user component to attach
6340      */
6341     void attach(SS7L3User* l3user);
6342 
6343     /**
6344      * Retrieve the Layer 3 user component to which this network is attached
6345      * @return Pointer to the Layer 3 user this network is attached to
6346      */
user()6347     inline SS7L3User* user() const
6348 	{ return m_l3user; }
6349 
6350     /**
6351      * Retrieve the point code type of this Layer 3 component for a MSU type
6352      * @param netType Type of the network like coded in the MSU NI field
6353      * @return The type of codepoint this component will use
6354      */
6355     SS7PointCode::Type type(unsigned char netType) const;
6356 
6357     /**
6358      * Set the point code of this Layer 3 component for a network type
6359      * @param type Point code type to set for the network type
6360      * @param netType Type of the network like coded in the MSU NI field
6361      */
6362     void setType(SS7PointCode::Type type, unsigned char netType);
6363 
6364     /**
6365      * Set the point code of this Layer 3 component for all network types
6366      * @param type Point code type to set
6367      */
6368     void setType(SS7PointCode::Type type);
6369 
6370     /**
6371      * Check if the network can possibly handle a Point Code type
6372      * @param pcType Point code type to check
6373      * @return True if there is one network type that can handle the Point Code
6374      */
6375     bool hasType(SS7PointCode::Type pcType) const;
6376 
6377     /**
6378      * Get the Network Indicator bits that would match a Point Code type
6379      * @param pcType Point Code type to search for
6380      * @param defNI Default Network Indicator bits to use
6381      * @return Network Indicator bits matching the Point Code type
6382      */
6383     virtual unsigned char getNI(SS7PointCode::Type pcType, unsigned char defNI) const;
6384 
6385     /**
6386      * Get the Network Indicator bits that would match a Point Code type
6387      * @param pcType Point Code type to search for
6388      * @return Network Indicator bits matching the Point Code type
6389      */
getNI(SS7PointCode::Type pcType)6390     inline unsigned char getNI(SS7PointCode::Type pcType) const
6391 	{ return getNI(pcType,m_defNI); }
6392 
6393     /**
6394      * Get the default Network Indicator bits
6395      * @return Default Network Indicator bits for this layer
6396      */
getNI()6397     inline unsigned char getNI() const
6398 	{ return m_defNI; }
6399 
6400     /**
6401      * Set the default Network Indicator bits
6402      * @param defNI Network Indicator bits to set as defaults
6403      */
6404     void setNI(unsigned char defNI);
6405 
6406     /**
6407      * Build the list of outgoing routes serviced by this network. Clear the list before re-building it.
6408      * This method is thread safe
6409      * @param params The parameter list
6410      * @return False if no route available
6411      */
6412     bool buildRoutes(const NamedList& params);
6413 
6414     /**
6415      * Get the maximum data length of a route by packed Point Code.
6416      * This method is thread safe
6417      * @param type Destination point code type
6418      * @param packedPC The packed point code
6419      * @return The maximum data length that can be transported on the route. Maximum msu size (273) if no route to the given point code
6420      */
6421     unsigned int getRouteMaxLength(SS7PointCode::Type type, unsigned int packedPC);
6422 
6423     /**
6424      * Get the priority of a route by packed Point Code.
6425      * This method is thread safe
6426      * @param type Destination point code type
6427      * @param packedPC The packed point code
6428      * @return The priority of the route. -1 if no route to the given point code
6429      */
6430     unsigned int getRoutePriority(SS7PointCode::Type type, unsigned int packedPC);
6431 
6432     /**
6433      * Get the priority of a route by unpacked Point Code.
6434      * This method is thread safe
6435      * @param type Destination point code type
6436      * @param dest The destination point code
6437      * @return The priority of the route. -1 if no route to the given point code
6438      */
getRoutePriority(SS7PointCode::Type type,const SS7PointCode & dest)6439     inline unsigned int getRoutePriority(SS7PointCode::Type type, const SS7PointCode& dest)
6440 	{ return getRoutePriority(type,dest.pack(type)); }
6441 
6442     /**
6443      * Get the current state of a route by packed Point Code.
6444      * This method is thread safe
6445      * @param type Destination point code type
6446      * @param packedPC The packed point code
6447      * @param checkAdjacent True to take into account the adjacent STP
6448      * @return The state of the route, SS7Route::Unknown if no route to the given point code
6449      */
6450     SS7Route::State getRouteState(SS7PointCode::Type type, unsigned int packedPC, bool checkAdjacent = false);
6451 
6452     /**
6453      * Get the current state of a route by unpacked Point Code.
6454      * This method is thread safe
6455      * @param type Destination point code type
6456      * @param dest The destination point code
6457      * @param checkAdjacent True to take into account the adjacent STP
6458      * @return The state of the route, SS7Route::Unknown if no route to the given point code
6459      */
6460     inline SS7Route::State getRouteState(SS7PointCode::Type type, const SS7PointCode& dest, bool checkAdjacent = false)
6461 	{ return getRouteState(type,dest.pack(type),checkAdjacent); }
6462 
6463     /**
6464      * Check if access to a specific Point Code is allowed from this network
6465      * @param type Destination point code type
6466      * @param packedPC The destination point code
6467      * @return True if access to the specified Point Code is allowed
6468      */
allowedTo(SS7PointCode::Type type,unsigned int packedPC)6469     virtual bool allowedTo(SS7PointCode::Type type, unsigned int packedPC) const
6470 	{ return true; }
6471 
6472     /**
6473      * Print the destinations or routing table to output
6474      */
6475     void printRoutes();
6476 
6477     /**
6478      * Retrieve the local Point Code for a specific Point Code type
6479      * @param type Desired Point Code type
6480      * @return Packed local Point Code, zero if not set
6481      */
getLocal(SS7PointCode::Type type)6482     inline unsigned int getLocal(SS7PointCode::Type type) const
6483 	{ return (type < SS7PointCode::DefinedTypes) ? m_local[type-1] : 0; }
6484 
6485     /**
6486      * Retrieve the default local Point Code for a specific Point Code type
6487      * @param type Desired Point Code type
6488      * @return Packed local Point Code, zero if not set
6489      */
getDefaultLocal(SS7PointCode::Type type)6490     virtual unsigned int getDefaultLocal(SS7PointCode::Type type) const
6491 	{ return getLocal(type); }
6492 
6493 protected:
6494     /**
6495      * Constructor
6496      * @param type Default point code type
6497      */
6498     SS7Layer3(SS7PointCode::Type type = SS7PointCode::Other);
6499 
6500     /**
6501      * Push a received Message Signal Unit up the protocol stack
6502      * @param msu Message data, starting with Service Indicator Octet
6503      * @param label Routing label of the received MSU
6504      * @param sls Signalling Link the MSU was received from
6505      * @return Result of MSU processing by user part
6506      */
receivedMSU(const SS7MSU & msu,const SS7Label & label,int sls)6507     inline HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, int sls)
6508     {
6509 	m_l3userMutex.lock();
6510 	RefPointer<SS7L3User> tmp = m_l3user;
6511 	m_l3userMutex.unlock();
6512 	return tmp ? tmp->receivedMSU(msu,label,this,sls) : HandledMSU(HandledMSU::Unequipped);
6513     }
6514 
6515     /**
6516      * Push a recovered Message Signal Unit back up the protocol stack
6517      * @param msu Message data, starting with Service Indicator Octet
6518      * @param label Routing label of the recovered MSU
6519      * @param sls Signalling Link the MSU was recovered from
6520      * @return True if the MSU was successfully rerouted
6521      */
recoveredMSU(const SS7MSU & msu,const SS7Label & label,int sls)6522     inline bool recoveredMSU(const SS7MSU& msu, const SS7Label& label, int sls)
6523     {
6524 	m_l3userMutex.lock();
6525 	RefPointer<SS7L3User> tmp = m_l3user;
6526 	m_l3userMutex.unlock();
6527 	return tmp && tmp->recoveredMSU(msu,label,this,sls);
6528     }
6529 
6530     /**
6531      * Notify out user part about a status change
6532      * @param sls Link that generated the notification, -1 if none
6533      */
6534     inline void notify(int sls = -1)
6535     {
6536 	m_l3userMutex.lock();
6537 	RefPointer<SS7L3User> tmp = m_l3user;
6538 	m_l3userMutex.unlock();
6539 	if (tmp)
6540 	    tmp->notify(this,sls);
6541     }
6542 
6543     /**
6544      * Callback called from maintenance when valid SLTA or SLTM are received
6545      * @param sls Link that was checked by maintenance
6546      * @param remote True if remote checked the link, false if local success
6547      */
linkChecked(int sls,bool remote)6548     virtual void linkChecked(int sls, bool remote)
6549 	{ }
6550 
6551     /**
6552      * Default processing of a MTN (Maintenance MSU)
6553      * @param msu Message data, starting with Service Indicator Octet
6554      * @param label Routing label of the received MSU
6555      * @param sls Signalling Link the MSU was received from
6556      * @return True if the MSU was processed
6557      */
6558     virtual bool maintenance(const SS7MSU& msu, const SS7Label& label, int sls);
6559 
6560     /**
6561      * Default processing of a SNM (Management MSU)
6562      * @param msu Message data, starting with Service Indicator Octet
6563      * @param label Routing label of the received MSU
6564      * @param sls Signalling Link the MSU was received from
6565      * @return True if the MSU was processed
6566      */
6567     virtual bool management(const SS7MSU& msu, const SS7Label& label, int sls);
6568 
6569     /**
6570      * Default processing of an unknown MSU - emit an User Part Unavailable
6571      * @param msu Message data, starting with Service Indicator Octet
6572      * @param label Routing label of the received MSU
6573      * @param sls Signalling Link the MSU was received from
6574      * @param cause Unavailability cause code (Q.704 15.17.5)
6575      * @return True if the MSU was processed
6576      */
6577     virtual bool unavailable(const SS7MSU& msu, const SS7Label& label, int sls, unsigned char cause = 0);
6578 
6579     /**
6580      * Send a Transfer Prohibited if an unexpected MSU is received in STP mode
6581      * @param ssf Subservice Field of received MSU
6582      * @param label Routing label of the received MSU
6583      * @param sls Signalling Link the MSU was received from
6584      * @return True if the TFP was sent
6585      */
6586     virtual bool prohibited(unsigned char ssf, const SS7Label& label, int sls);
6587 
6588     /**
6589      * Check if we should answer with SLTA to received SLTM in maintenance()
6590      * @return True to send a SLTA for each good received SLTM
6591      */
responder()6592     virtual bool responder() const
6593 	{ return true; }
6594 
6595     /**
6596      * Find a route having the specified point code type and packed point code.
6597      * This method is thread safe
6598      * @param type The point code type used to choose the list of packed point codes
6599      * @param packed The packed point code to find in the list
6600      * @return SS7Route pointer or 0 if type is invalid or the given packed point code was not found
6601      */
6602     SS7Route* findRoute(SS7PointCode::Type type, unsigned int packed);
6603 
6604     /**
6605      * Retrieve the route table for a specific Point Code type
6606      * @param type Point Code type of the desired table
6607      * @return Pointer to the list of SS7Route or NULL if no such route
6608      */
getRoutes(SS7PointCode::Type type)6609     inline ObjList* getRoutes(SS7PointCode::Type type)
6610 	{ return (type < SS7PointCode::DefinedTypes) ? &m_route[type-1] : 0; }
6611 
6612     /**
6613      * Retrieve the route table for a specific Point Code type
6614      * @param type Point Code type of the desired table
6615      * @return Pointer to the list of SS7Route or NULL if no such route
6616      */
getRoutes(SS7PointCode::Type type)6617     inline const ObjList* getRoutes(SS7PointCode::Type type) const
6618 	{ return (type < SS7PointCode::DefinedTypes) ? &m_route[type-1] : 0; }
6619 
6620     /** Mutex to lock routing list operations */
6621     Mutex m_routeMutex;
6622 
6623     /** Outgoing point codes serviced by a network (for each point code type) */
6624     ObjList m_route[YSS7_PCTYPE_COUNT];
6625 
6626 private:
6627     Mutex m_l3userMutex;                 // Mutex to lock L3 user pointer
6628     SS7L3User* m_l3user;
6629     SS7PointCode::Type m_cpType[4];      // Map incoming MSUs net indicators to point code type
6630                                          // or the routing table of a message router
6631     unsigned int m_local[YSS7_PCTYPE_COUNT];
6632     unsigned char m_defNI;               // Default Network Indicator
6633 };
6634 
6635 /**
6636  * An interface to a Layer 4 (application) SS7 protocol
6637  * @short Abstract SS7 layer 4 (application) protocol
6638  */
6639 class YSIG_API SS7Layer4 : public SS7L3User
6640 {
6641 public:
6642     /**
6643      * This method is called to clean up and destroy the object after the
6644      *  reference counter becomes zero
6645      */
6646     virtual void destroyed();
6647 
6648     /**
6649      * Initialize the application layer, connect it to the SS7 router
6650      * @param config Optional configuration parameters override
6651      * @return True if the application was initialized properly
6652      */
6653     virtual bool initialize(const NamedList* config);
6654 
6655     /**
6656      * Attach a SS7 network or router to this service. Detach itself from the old one if valid
6657      * @param network Pointer to network or router to attach
6658      */
6659     virtual void attach(SS7Layer3* network);
6660 
6661     /**
6662      * Retrieve the SS7 network or router to which this service is attached
6663      * @return Pointer to the network or router this service is attached to
6664      */
network()6665     inline SS7Layer3* network() const
6666 	{ return m_layer3; }
6667 
6668     /**
6669      * Get the default sending Service Information Octet for this protocol
6670      * @return SIO value
6671      */
sio()6672     inline unsigned char sio() const
6673 	{ return m_sio; }
6674 
6675     /**
6676      * Get the Service Information Field (SS7 protocol number)
6677      * @return SIF value used in matching and sending MSUs
6678      */
sif()6679     inline unsigned char sif() const
6680 	{ return m_sio & 0x0f; }
6681 
6682     /**
6683      * Get the default sending Service Switching Function bits for this protocol
6684      * @return Combined Priority and Network Indicator bits
6685      */
ssf()6686     inline unsigned char ssf() const
6687 	{ return m_sio & 0xf0; }
6688 
6689     /**
6690      * Get the default sending Priority bits for this protocol
6691      * @return Priority bits
6692      */
prio()6693     inline unsigned char prio() const
6694 	{ return m_sio & 0x30; }
6695 
6696     /**
6697      * Get the default sending Network Indicator bits for this protocol
6698      * @return Network Indicator bits
6699      */
ni()6700     inline unsigned char ni() const
6701 	{ return m_sio & 0xc0; }
6702 
6703     /**
6704      * Get a SIO value from a parameters list
6705      * @param params Parameter list to retrieve "service", "priority" and "netindicator"
6706      * @param sif Default Service Information Field to apply parameters to
6707      * @param prio Default Priority Field to apply parameters to
6708      * @param ni Default Network Indicator Field to apply parameters to
6709      * @return Adjusted SIO value
6710      */
6711     static unsigned char getSIO(const NamedList& params, unsigned char sif, unsigned char prio, unsigned char ni);
6712 
6713     /**
6714      * Get a SIO value from a parameters list
6715      * @param params Parameter list to retrieve "service", "priority" and "netindicator"
6716      * @param sif Default Service Information Field to apply parameters to
6717      * @param ssf Default Subservice Field to apply parameters to
6718      * @return Adjusted SIO value
6719      */
getSIO(const NamedList & params,unsigned char sif,unsigned char ssf)6720     static inline unsigned char getSIO(const NamedList& params, unsigned char sif, unsigned char ssf)
6721 	{ return getSIO(params,sif,ssf & 0x30,ssf & 0xc0); }
6722 
6723     /**
6724      * Get a SIO value from a parameters list
6725      * @param params Parameter list to retrieve "service", "priority" and "netindicator"
6726      * @param sio Default SIO to apply parameters to
6727      * @return Adjusted SIO value
6728      */
getSIO(const NamedList & params,unsigned char sio)6729     static inline unsigned char getSIO(const NamedList& params, unsigned char sio)
6730 	{ return getSIO(params,sio & 0x0f,sio & 0x30,sio & 0xc0); }
6731 
6732     /**
6733      * Get a SIO value from a parameters list
6734      * @param params Parameter list to retrieve "service", "priority" and "netindicator"
6735      * @return Adjusted SIO value
6736      */
getSIO(const NamedList & params)6737     inline unsigned char getSIO(const NamedList& params) const
6738 	{ return getSIO(params,m_sio); }
6739 
6740 protected:
6741     /**
6742      * Constructor
6743      * @param sio Default value of Service Information Octet
6744      * @param params Optional parameters to alter the value of SIO
6745      */
6746     SS7Layer4(unsigned char sio = SS7MSU::National, const NamedList* params = 0);
6747 
6748     /**
6749      * Ask the Layer 3 to push a Message Signal Unit down the protocol stack
6750      * @param msu Message data, starting with Service Indicator Octet
6751      * @param label Routing label of the MSU to use in routing
6752      * @param sls Signalling Link Selection, negative to choose best
6753      * @return Link the message was successfully queued to, negative for error
6754      */
6755     inline int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1)
6756     {
6757 	m_l3Mutex.lock();
6758 	RefPointer<SS7Layer3> tmp = m_layer3;
6759 	m_l3Mutex.unlock();
6760 	return tmp ? tmp->transmitMSU(msu,label,sls) : -1;
6761     }
6762 
6763     /**
6764      * Service Information Octet (SIO) for this protocol
6765      */
6766     unsigned char m_sio;
6767 
6768 private:
6769     Mutex m_l3Mutex;                     // Lock pointer use operations
6770     SS7Layer3* m_layer3;
6771 };
6772 
6773 /**
6774  * A message router between Transfer and Application layers.
6775  *  Messages are distributed according to the service type.
6776  * @short Main router for SS7 message transfer and applications
6777  */
6778 class YSIG_API SS7Router : public SS7L3User, public SS7Layer3, public Mutex
6779 {
6780     YCLASS2(SS7Router,SS7L3User,SS7Layer3)
6781 public:
6782     /**
6783      * Control primitives
6784      */
6785     enum Operation {
6786 	// stop MTP operation, disable the router
6787 	Pause     = 0x100,
6788 	// start router, restart MTP if needed
6789 	Resume    = 0x200,
6790 	// forcibly execute MTP restart
6791 	Restart   = 0x300,
6792 	// get operational status
6793 	Status    = 0x400,
6794 	// forcibly advertise availability to adjacent routes
6795 	Traffic   = 0x500,
6796 	// forcibly advertise available routes
6797 	Advertise = 0x600,
6798     };
6799 
6800     /**
6801      * Default constructor
6802      * @param params The list with the parameters
6803      */
6804     SS7Router(const NamedList& params);
6805 
6806     /**
6807      * Destructor
6808      */
6809     virtual ~SS7Router();
6810 
6811     /**
6812      * Configure and initialize the router, maintenance and management
6813      * @param config Optional configuration parameters override
6814      * @return True if the router was initialized properly
6815      */
6816     virtual bool initialize(const NamedList* config);
6817 
6818     /**
6819      * Push a Message Signal Unit down the protocol stack
6820      * @param msu Message data, starting with Service Indicator Octet
6821      * @param label Routing label of the MSU to use in routing
6822      * @param sls Signalling Link Selection, negative to choose best
6823      * @return Link the message was successfully queued to, negative for error
6824      */
6825     virtual int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1);
6826 
6827     /**
6828      * Check if the router is fully operational
6829      * @param sls Signalling Link to check, negative to check if any is operational
6830      * @return True if the router is enabled and operational
6831      */
6832     virtual bool operational(int sls = -1) const;
6833 
6834     /**
6835      * Initiate a MTP restart procedure
6836      * @return True if a restart was initiated
6837      */
6838     virtual bool restart();
6839 
6840     /**
6841      * Attach a SS7 Layer 3 (network) to the router. Attach the router to the given network
6842      * @param network Pointer to network to attach
6843      */
6844     virtual void attach(SS7Layer3* network);
6845 
6846     /**
6847      * Detach a SS7 Layer 3 (network) from the router. Detach the router from the given network
6848      * @param network Pointer to network to detach
6849      */
6850     virtual void detach(SS7Layer3* network);
6851 
6852     /**
6853      * Attach a SS7 Layer 4 (service) to the router. Attach itself to the service
6854      * @param service Pointer to service to attach
6855      */
6856     void attach(SS7Layer4* service);
6857 
6858     /**
6859      * Detach a SS7 Layer 4 (service) from the router. Detach itself from the service
6860      * @param service Pointer to service to detach
6861      */
6862     void detach(SS7Layer4* service);
6863 
6864     /**
6865      * Management request uninhibiting a signaling link
6866      * @param network SS7 Layer 3 owning the link to uninhibit
6867      * @param sls Signalink Link Selection
6868      * @param remote True to uninhibit the remote side of the link
6869      * @return True if an uninhibition request was sent
6870      */
6871     bool uninhibit(SS7Layer3* network, int sls, bool remote);
6872 
6873     /**
6874      * Set and clear inhibition flags on a link of an attached network
6875      * @param link Signalling Link to modify identified by a routing label
6876      * @param setFlags Flag bits to set ORed together
6877      * @param clrFlags Flag bits to clear  ORed together (optional)
6878      * @param notLast Do not apply inhibition to the last usable link
6879      * @return True if inhibition flags were set
6880      */
6881     bool inhibit(const SS7Label& link, int setFlags, int clrFlags = 0, bool notLast = false);
6882 
6883     /**
6884      * Check inhibition flags on a link of a router attached network
6885      * @param link Signalling Link to check identified by a routing label
6886      * @param flags Flag bits to check ORed together
6887      * @return True if any of the specified inhibition flags are set
6888      */
6889     bool inhibited(const SS7Label& link, int flags);
6890 
6891     /**
6892      * Get the sequence number of the last MSU received on a link
6893      * @param link Routing label identifying the link to retrieve the sequence from
6894      * @return Last FSN received, negative if not available
6895      */
6896     int getSequence(const SS7Label& link);
6897 
6898     /**
6899      * Remove the MSUs waiting in the transmit queue and return them
6900      * @param link Routing label identifying the link to recover MSUs
6901      * @param sequence First sequence number to recover, flush earlier packets
6902      */
6903     void recoverMSU(const SS7Label& link, int sequence);
6904 
6905     /**
6906      * Notification for receiving User Part Unavailable
6907      * @param type Type of Point Code
6908      * @param node Node on which the User Part is unavailable
6909      * @param part User Part (service) reported unavailable
6910      * @param cause Unavailability cause - Q.704 15.17.5
6911      * @param label Routing label of the UPU message
6912      * @param sls Signaling link the UPU was received on
6913      */
6914     virtual void receivedUPU(SS7PointCode::Type type, const SS7PointCode node,
6915 	SS7MSU::Services part, unsigned char cause, const SS7Label& label, int sls);
6916 
6917     /**
6918      * Check if the transfer function and STP management is enabled
6919      * @return True if acting as a full STP
6920      */
transfer()6921     inline bool transfer() const
6922 	{ return m_transfer; }
6923 
6924     /**
6925      * Check if the messages are transferred even if STP management may be disabled
6926      * @return True if messages are transferred between networks
6927      */
transferring()6928     inline bool transferring() const
6929 	{ return m_transfer || m_transferSilent; }
6930 
6931     /**
6932      * Check if the MTP is restarting
6933      * @return True if MTP restart procedure is in progress
6934      */
starting()6935     inline bool starting() const
6936 	{ return !m_started; }
6937 
6938     /**
6939      * Get access to the Management component if available
6940      * @return A pointer to the SS7Management or NULL if not created
6941      */
getManagement()6942     inline SS7Management* getManagement() const
6943 	{ return m_mngmt; }
6944 
6945     /**
6946      * Get the Network Indicator bits that would match a Point Code type
6947      * @param pcType Point Code type to search for
6948      * @param defNI Default Network Indicator bits to use
6949      * @return Network Indicator bits matching the Point Code type
6950      */
6951     virtual unsigned char getNI(SS7PointCode::Type pcType, unsigned char defNI) const;
6952 
6953     /**
6954      * Retrieve the default local Point Code for a specific Point Code type
6955      * @param type Desired Point Code type
6956      * @return Packed local Point Code, zero if not set
6957      */
6958     virtual unsigned int getDefaultLocal(SS7PointCode::Type type) const;
6959 
6960 protected:
6961     /**
6962      * Reset state of all routes of a network to Unknown
6963      */
6964     void clearView(const SS7Layer3* network);
6965 
6966     /**
6967      * Get the state of a route as seen from another network or adjacent point code
6968      * @param type Point Code type to search for
6969      * @param packedPC The packed point code whose state is viewed
6970      * @param remotePC The point code of an adjacent viewer, its network is skipped
6971      * @param network The network that will be not included in the view
6972      * @return State of the route as viewed from the specified point code or network
6973      */
6974     SS7Route::State getRouteView(SS7PointCode::Type type, unsigned int packedPC,
6975         unsigned int remotePC = 0, const SS7Layer3* network = 0);
6976 
6977     /**
6978      * Set the current state of a route by packed Point Code.
6979      * This method is thread safe
6980      * @param type Destination point code type
6981      * @param packedPC The packed point code
6982      * @param state The new state of the route
6983      * @param remotePC The point code that caused the route change
6984      * @param network The network that caused the route change
6985      * @return True if the route was found and its state changed
6986      */
6987     bool setRouteState(SS7PointCode::Type type, unsigned int packedPC, SS7Route::State state,
6988         unsigned int remotePC = 0, const SS7Layer3* network = 0);
6989 
6990     /**
6991      * Set the current state of a route by unpacked Point Code.
6992      * This method is thread safe
6993      * @param type Destination point code type
6994      * @param dest The destination point code
6995      * @param state The new state of the route
6996      * @param remotePC The point code that caused the route change
6997      * @param network The network that caused the route change
6998      * @return True if the route was found and its state changed
6999      */
7000     inline bool setRouteState(SS7PointCode::Type type, const SS7PointCode& dest, SS7Route::State state,
7001         unsigned int remotePC = 0, const SS7Layer3* network = 0)
7002 	{ return setRouteState(type,dest.pack(type),state,remotePC,network); }
7003 
7004     /**
7005      * Load the default local Point Codes from a list of parameters
7006      * @param params List of parameters to load "local=" entries from
7007      */
7008     void loadLocalPC(const NamedList& params);
7009 
7010     /**
7011      * Periodical timer tick used to perform state transition and housekeeping
7012      * @param when Time to use as computing base for events and timeouts
7013      */
7014     virtual void timerTick(const Time& when);
7015 
7016     /**
7017      * Process a MSU received from the Layer 3 component
7018      * @param msu Message data, starting with Service Indicator Octet
7019      * @param label Routing label of the received MSU
7020      * @param network Network layer that delivered the MSU
7021      * @param sls Signalling Link the MSU was received from
7022      * @return Result of MSU processing
7023      */
7024     virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
7025 
7026     /**
7027      * Add a network to the routing table. Clear all its routes before appending it to the table
7028      * This method is thread safe
7029      * @param network The network to add to the routing table
7030      */
7031     void updateRoutes(SS7Layer3* network);
7032 
7033     /**
7034      * Remove the given network from all destinations in the routing table.
7035      * Remove the entry in the routing table if empty (no more routes to the point code).
7036      * This method is thread safe
7037      * @param network The network to remove
7038      */
7039     void removeRoutes(SS7Layer3* network);
7040 
7041     /**
7042      * Trigger the route changed notification for each route that is not Unknown
7043      * @param states Mask of required states of the route
7044      * @param onlyPC The only point code that should receive notifications
7045      */
7046     void notifyRoutes(SS7Route::State states = SS7Route::AnyState, unsigned int onlyPC = 0);
7047 
7048     /**
7049      * Trigger the route changed notification for each route that is not Unknown
7050      * @param states Mask of required states of the route
7051      * @param network Notify to adjacent nodes of this network
7052      */
7053     void notifyRoutes(SS7Route::State states, const SS7Layer3* network);
7054 
7055     /**
7056      * Notification callback when a route state changed to other than Unknown.
7057      * This method is called with the route mutex locked
7058      * @param route Pointer to the route whose state has changed
7059      * @param type Type of the pointcode of the route
7060      * @param remotePC The point code that caused the route change
7061      * @param network The network that caused the route change
7062      * @param onlyPC If set only advertise to this point code
7063      * @param forced Notify even if the route view didn't change
7064      */
7065     virtual void routeChanged(const SS7Route* route, SS7PointCode::Type type,
7066         unsigned int remotePC = 0, const SS7Layer3* network = 0,
7067         unsigned int onlyPC = 0, bool forced = false);
7068 
7069     /**
7070      * Process a notification generated by the attached network layer
7071      * @param network Network or linkset that generated the notification
7072      * @param sls Signallink Link that generated the notification, negative if none
7073      * @return True if notification was processed
7074      */
7075     virtual void notify(SS7Layer3* network, int sls);
7076 
7077     /**
7078      * Query or modify the management settings or operational parameters
7079      * @param params The list of parameters to query or change
7080      * @return True if the control operation was executed
7081      */
7082     virtual bool control(NamedList& params);
7083 
7084     /**
7085      * Detach management
7086      */
7087     virtual void destroyed();
7088 
7089     /** List of L3 (networks) attached to this router */
7090     ObjList m_layer3;
7091     /** List of L4 (services) attached to this router */
7092     ObjList m_layer4;
7093     /** Counter used to spot changes in the lists of L3 or L4 */
7094     int m_changes;
7095     /** Locally unhandled MSUs are to be routed to other networks */
7096     bool m_transfer;
7097     /** STP phase 2 of restart procedure in effect */
7098     bool m_phase2;
7099     /** MTP restart procedure has completed */
7100     bool m_started;
7101     /** MTP overall restart timer T20 */
7102     SignallingTimer m_restart;
7103     /** MTP isolation timer T1 */
7104     SignallingTimer m_isolate;
7105 
7106 private:
7107     void restart2();
7108     void disable();
7109     void sendRestart(const SS7Layer3* network = 0);
7110     void sendRestart(SS7PointCode::Type type, unsigned int packedPC);
7111     void silentAllow(const SS7Layer3* network = 0);
7112     void silentAllow(SS7PointCode::Type type, unsigned int packedPC);
7113     void checkRoutes(const SS7Layer3* noResume = 0);
7114     void clearRoutes(SS7Layer3* network, bool ok);
7115     void reroute(const SS7Layer3* network);
7116     void rerouteCheck(const Time& when);
7117     void rerouteFlush();
7118     bool setRouteSpecificState(SS7PointCode::Type type, unsigned int packedPC,
7119 	unsigned int srcPC, SS7Route::State state, const SS7Layer3* changer = 0);
7120     inline bool setRouteSpecificState(SS7PointCode::Type type, const SS7PointCode& dest,
7121 	const SS7PointCode&src, SS7Route::State state, const SS7Layer3* changer = 0)
7122 	{ return setRouteSpecificState(type,dest.pack(type),src.pack(type),state,changer); }
7123     void sendRouteTest();
7124     int routeMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls, SS7Route::State states);
7125     void buildView(SS7PointCode::Type type, ObjList& view, SS7Layer3* network);
7126     void buildViews();
7127     void printStats();
7128     Mutex m_statsMutex;
7129     SignallingTimer m_trafficOk;
7130     SignallingTimer m_trafficSent;
7131     SignallingTimer m_routeTest;
7132     bool m_testRestricted;
7133     bool m_transferSilent;
7134     bool m_checkRoutes;
7135     bool m_autoAllowed;
7136     bool m_sendUnavail;
7137     bool m_sendProhibited;
7138     unsigned long m_rxMsu;
7139     unsigned long m_txMsu;
7140     unsigned long m_fwdMsu;
7141     unsigned long m_failMsu;
7142     unsigned long m_congestions;
7143     SS7Management* m_mngmt;
7144 };
7145 
7146 /**
7147  * RFC4165 SS7 Layer 2 implementation over SCTP/IP.
7148  * M2PA is intended to be used as a symmetrical Peer-to-Peer replacement of
7149  *  a hardware based SS7 data link.
7150  * @short SIGTRAN MTP2 User Peer-to-Peer Adaptation Layer
7151  */
7152 class YSIG_API SS7M2PA : public SS7Layer2, public SIGTRAN
7153 {
7154     YCLASS(SS7M2PA,SS7Layer2)
7155 public:
7156     enum m2paState {
7157 	Alignment = 1,
7158 	ProvingNormal = 2,
7159 	ProvingEmergency = 3,
7160 	Ready = 4,
7161 	ProcessorOutage = 5,
7162 	ProcessorRecovered = 6,
7163 	Busy = 7,
7164 	BusyEnded = 8,
7165 	OutOfService = 9,
7166     };
7167 
7168     enum msgType {
7169 	UserData = 1,
7170 	LinkStatus = 2
7171     };
7172 
7173     enum sctpState {
7174 	Idle,
7175 	Associating,
7176 	Established
7177     };
7178 
7179     enum M2PAOperations {
7180 	Pause        = SS7Layer2::Pause,
7181 	// start link operation, align if it needs to
7182 	Resume       = SS7Layer2::Resume,
7183 	// start link, force realignment
7184 	Align        = SS7Layer2::Align,
7185 	// get operational status
7186 	Status       = SS7Layer2::Status,
7187 	// restart transport layer
7188 	TransRestart = 0x500
7189     };
7190 
7191     /**
7192      * Constructor
7193      */
7194     SS7M2PA(const NamedList& params);
7195 
7196     /**
7197      * Destructor
7198      */
7199     ~SS7M2PA();
7200 
7201     /**
7202      * Configure and initialize M2PA and its transport
7203      * @param config Optional configuration parameters override
7204      * @return True if M2PA and the transport were initialized properly
7205      */
7206     virtual bool initialize(const NamedList* config);
7207 
7208      /**
7209      * Query or modify layer's settings or operational parameters
7210      * @param params The list of parameters to query or change
7211      * @return True if the control operation was executed
7212      */
7213     virtual bool control(NamedList& params);
7214 
7215     /**
7216      * Execute a control operation. Operations can change the link status or
7217      *  can query the aligned status.
7218      * @param oper Operation to execute
7219      * @param params Optional parameters for the operation
7220      * @return True if the command completed successfully, for query operations
7221      *  also indicates the data link is aligned and operational
7222      */
7223     virtual bool control(M2PAOperations oper, NamedList* params = 0);
7224 
7225     /**
7226      * Execute a control operation. Operations can change the link status or
7227      *  can query the aligned status.
7228      * @param oper Operation to execute
7229      * @param params Optional parameters for the operation
7230      * @return True if the command completed successfully, for query operations
7231      *  also indicates the data link is aligned and operational
7232      */
7233     virtual bool control(SS7Layer2::Operation oper, NamedList* params = 0)
7234 	{ return control((M2PAOperations)oper,params); }
7235 
7236     /**
7237      * Retrieve the current link status indications
7238      * @return Link status indication bits
7239      */
7240     virtual unsigned int status() const;
7241 
7242     /**
7243      * Push a Message Signal Unit down the protocol stack
7244      * @param msu MSU data to transmit
7245      * @return True if message was successfully queued
7246      */
7247     virtual bool transmitMSU(const SS7MSU& msu);
7248 
7249     /**
7250      * Method called when the transport status has been changed
7251      * @param status Up or down
7252      */
7253     virtual void notifyLayer(SignallingInterface::Notification status);
7254 
7255     /**
7256      * Remove the MSUs waiting in the transmit queue and return them
7257      * @param sequence First sequence number to recover, flush earlier packets
7258      */
7259     virtual void recoverMSU(int sequence);
7260 
7261     /**
7262      * Decode sequence numbers from message and process them
7263      * @param data The message
7264      * @param msgType The message type
7265      * @return True if sequence numbers ar as we expected to be
7266      */
7267     bool decodeSeq(const DataBlock& data, u_int8_t msgType);
7268 
7269     /**
7270      * Helper method called when an error was detected
7271      * Change state to OutOfService and notifys upper layer
7272      * @param info Debuging purpose, Information about detected error
7273      */
7274     void abortAlignment(const char* info = 0);
7275 
7276     /**
7277      * Send link status message to inform the peer about ouer curent state
7278      * @param streamId The id of the stream who should send the message
7279      */
7280     void transmitLS(int streamId = 0);
7281 
7282     /**
7283      * Create M2PA header (sequence numbers)
7284      * @param data The data where the header will be stored
7285      */
7286     void setHeader(DataBlock& data);
7287 
7288     /**
7289      * Decode and process link status message
7290      * @param data The message
7291      * @param streamId The stream id witch received the message
7292      * @return True if the message was procesed
7293      */
7294     bool processLinkStatus(DataBlock& data, int streamId);
7295 
7296     /**
7297      * Decode and process link status message in more strict manner
7298      * @param data The message
7299      * @param streamId The stream id witch received the message
7300      * @return True if the message was procesed
7301      */
7302     bool processSLinkStatus(DataBlock& data, int streamId);
7303 
7304     /**
7305      * Helper method used to acknowledge the last received message
7306      * when no data are to transmit
7307      */
7308     void sendAck();
7309 
7310     /**
7311      * Remove a frame from acknowledgement list
7312      * @param bsn The sequence number of the frame to be removed
7313      * @return True if the frame was found and removed.
7314      */
7315     bool removeFrame(u_int32_t bsn);
7316 
7317     /**
7318      * Check if a sequence number may be a valid next BSN
7319      * @param bsn Backward Sequence Number to check
7320      * @return True if the provided BSN is in the valid range
7321      */
7322     bool nextBsn(u_int32_t bsn) const;
7323 
7324     /**
7325      * Increment the given sequence number
7326      * @param nr Reference of the number to increment
7327      * @return The incremented number
7328      */
increment(u_int32_t & nr)7329     static inline u_int32_t increment(u_int32_t& nr)
7330 	{ return (nr == 0xffffff) ? (nr = 0) : nr++; }
7331 
7332     /**
7333      * Obtain next sequence number
7334      * @param nr The current sequence number
7335      * @return The next number in sequence
7336      */
getNext(u_int32_t nr)7337     static inline u_int32_t getNext(u_int32_t nr)
7338 	{ return (nr == 0xffffff) ? 0 : nr + 1; }
7339 
7340 protected:
7341 
7342     /**
7343      * Periodical timer tick used to perform alignment and housekeeping
7344      * @param when Time to use as computing base for events and timeouts
7345      */
7346     virtual void timerTick(const Time& when);
7347 
7348     /**
7349      * Check if the link is aligned.
7350      * The link may not be operational, the other side may be still proving.
7351      * @return True if the link is aligned
7352      */
7353     virtual bool aligned() const;
7354 
7355     /**
7356      * Check if the link is aligned and operational
7357      * @return True if the link is operational
7358      */
7359     virtual bool operational() const;
7360 
7361     /**
7362      * Process a complete message
7363      * @param msgVersion Version of the protocol
7364      * @param msgClass Class of the message
7365      * @param msgType Type of the message, depends on the class
7366      * @param msg Message data, may be empty
7367      * @param streamId Identifier of the stream the message was received on
7368      * @return True if the message was handled
7369      */
7370     virtual bool processMSG(unsigned char msgVersion, unsigned char msgClass,
7371 	unsigned char msgType, const DataBlock& msg, int streamId);
7372 
7373     /**
7374      * Initiates alignment and proving procedure
7375      * @param emergency True if emergency alignment is desired
7376      */
7377     void startAlignment(bool emergency = false);
7378 
7379     /**
7380      * Retransmit unacknowledged data
7381      */
7382      void retransData();
7383 
7384      virtual void destroyed();
7385 private:
7386     void dumpMsg(u_int8_t version, u_int8_t mClass, u_int8_t type,
7387 	const DataBlock& data, int stream, bool send);
7388     void setLocalStatus(unsigned int status);
7389     void setRemoteStatus(unsigned int status);
7390     u_int32_t m_seqNr;
7391     u_int32_t m_needToAck;
7392     u_int32_t m_lastAck;
7393     u_int32_t m_confCounter;
7394     u_int32_t m_maxUnack;
7395     u_int32_t m_maxQueueSize;
7396     unsigned int m_localStatus;
7397     unsigned int m_state;
7398     unsigned int m_remoteStatus;
7399     unsigned int m_transportState;
7400     unsigned int m_connFailCounter;
7401     unsigned int m_connFailThreshold;
7402     Mutex m_mutex;
7403     ObjList m_ackList;
7404     SignallingTimer m_t1;
7405     SignallingTimer m_t2;
7406     SignallingTimer m_t3;
7407     SignallingTimer m_t4;
7408     SignallingTimer m_ackTimer;
7409     SignallingTimer m_confTimer;
7410     SignallingTimer m_oosTimer;
7411     SignallingTimer m_waitOosTimer;
7412     SignallingTimer m_connFailTimer;
7413     bool m_autostart;
7414     bool m_sequenced;
7415     bool m_dumpMsg;
7416 };
7417 
7418 /**
7419  * The common client side of SIGTRAN SS7 MTP2 User Adaptation (RFC3331)
7420  * @short Client side of SIGTRAN SS7 MTP2 UA
7421  */
7422 class YSIG_API SS7M2UAClient : public SIGAdaptClient
7423 {
YCLASS(SS7M2UAClient,SIGAdaptClient)7424     YCLASS(SS7M2UAClient,SIGAdaptClient)
7425 public:
7426     /**
7427      * Contructor of an empty IUA client
7428      */
7429     inline SS7M2UAClient(const NamedList& params)
7430 	: SIGAdaptClient(params.safe("SS7M2UAClient"),&params,2,2904)
7431 	{ }
7432     virtual bool processMSG(unsigned char msgVersion, unsigned char msgClass,
7433 	unsigned char msgType, const DataBlock& msg, int streamId);
7434 };
7435 
7436 /**
7437  * RFC3331 SS7 Layer 2 implementation over SCTP/IP.
7438  * M2UA is intended to be used as a Provider-User where real MTP2 runs on a
7439  *  Signalling Gateway and MTP3 runs on an Application Server.
7440  * @short SIGTRAN MTP2 User Adaptation Layer
7441  */
7442 class YSIG_API SS7M2UA : public SS7Layer2, public SIGAdaptUser
7443 {
7444     friend class SS7M2UAClient;
7445     YCLASS(SS7M2UA,SS7Layer2)
7446 public:
7447     /**
7448      * Constructor
7449      * @param params List of construction parameters
7450      */
7451     SS7M2UA(const NamedList& params);
7452 
7453     /**
7454      * Configure and initialize M2UA and its transport
7455      * @param config Optional configuration parameters override
7456      * @return True if M2UA and the transport were initialized properly
7457      */
7458     virtual bool initialize(const NamedList* config);
7459 
7460     /**
7461      * Execute a control operation. Operations can change the link status or
7462      *  can query the aligned status.
7463      * @param oper Operation to execute
7464      * @param params Optional parameters for the operation
7465      * @return True if the command completed successfully, for query operations
7466      *  also indicates the data link is aligned and operational
7467      */
7468     virtual bool control(Operation oper, NamedList* params = 0);
7469 
7470     /**
7471      * Retrieve the current link status indications
7472      * @return Link status indication bits
7473      */
7474     virtual unsigned int status() const;
7475 
7476     /**
7477      * Push a Message Signal Unit down the protocol stack
7478      * @param msu Message data, starting with Service Indicator Octet
7479      * @return True if message was successfully queued
7480      */
7481     virtual bool transmitMSU(const SS7MSU& msu);
7482 
7483     /**
7484      * Remove the MSUs waiting in the transmit queue and return them
7485      * @param sequence First sequence number to recover, flush earlier packets
7486      */
7487     virtual void recoverMSU(int sequence);
7488 
7489     /**
7490      * Check if the link is fully operational
7491      * @return True if the link is aligned and operational
7492      */
7493     virtual bool operational() const;
7494 
7495     /**
7496      * Get the sequence number of the last MSU received, request if not available
7497      * @return Last FSN received, negative if not available
7498      */
7499     virtual int getSequence();
7500 
7501     /**
7502      * Traffic activity state change notification
7503      * @param active True if the ASP is active and traffic is allowed
7504      */
7505     virtual void activeChange(bool active);
7506 
7507     /**
7508      * Retrieve the numeric Interface Identifier (if any)
7509      * @return IID value, -1 if not set
7510      */
iid()7511     inline int32_t iid() const
7512 	{ return m_iid; }
7513 
7514 protected:
7515     enum LinkState {
7516 	LinkDown,
7517 	LinkReq,
7518 	LinkReqEmg,
7519 	LinkUp,
7520 	LinkUpEmg,
7521     };
7522 
7523     /**
7524      * Periodical timer tick used to perform alignment and housekeeping
7525      * @param when Time to use as computing base for events and timeouts
7526      */
7527     virtual void timerTick(const Time& when);
7528 
client()7529     SS7M2UAClient* client() const
7530 	{ return static_cast<SS7M2UAClient*>(adaptation()); }
7531     virtual bool processMGMT(unsigned char msgType, const DataBlock& msg, int streamId);
7532     virtual bool processMAUP(unsigned char msgType, const DataBlock& msg, int streamId);
7533     void postRetrieve();
7534     SignallingTimer m_retrieve;
7535     int32_t m_iid;
7536     int m_linkState;
7537     bool m_rpo;
7538     bool m_longSeq;
7539 };
7540 
7541 /**
7542  * RFC3332 SS7 Layer 3 implementation over SCTP/IP.
7543  * M3UA is intended to be used as a Provider-User where real MTP3 runs on a
7544  *  Signalling Gateway and MTP users are located on an Application Server.
7545  * @short SIGTRAN MTP3 User Adaptation Layer
7546  */
7547 class YSIG_API SS7M3UA : public SS7Layer3, public SIGAdaptUser
7548 {
7549     YCLASS(SS7M3UA,SS7Layer3)
7550 };
7551 
7552 /**
7553  * Q.703 SS7 Layer 2 (Data Link) implementation on top of a hardware interface
7554  * @short SS7 Layer 2 implementation on top of a hardware interface
7555  */
7556 class YSIG_API SS7MTP2 : public SS7Layer2, public SignallingReceiver, public SignallingDumpable, public Mutex
7557 {
7558     YCLASS2(SS7MTP2,SS7Layer2,SignallingReceiver)
7559 public:
7560     /**
7561      * Types of error correction
7562      */
7563     enum ErrorCorrection {
7564 	Basic,       // retransmits only based on sequence numbers
7565 	Preventive,  // continuously retransmit unacknowledged packets
7566 	Adaptive,    // switch to using preventive retransmission dynamically
7567     };
7568 
7569     /**
7570      * Constructor
7571      * @param params Layer's parameters
7572      * @param status Initial status
7573      */
7574     SS7MTP2(const NamedList& params, unsigned int status = OutOfService);
7575 
7576     /**
7577      * Destructor
7578      */
7579     virtual ~SS7MTP2();
7580 
7581     /**
7582      * Configure and initialize MTP2 and its interface
7583      * @param config Optional configuration parameters override
7584      * @return True if MTP2 and the interface were initialized properly
7585      */
7586     virtual bool initialize(const NamedList* config);
7587 
7588     /**
7589      * Push a Message Signal Unit down the protocol stack
7590      * @param msu MSU data to transmit
7591      * @return True if message was successfully queued
7592      */
7593     virtual bool transmitMSU(const SS7MSU& msu);
7594 
7595     /**
7596      * Remove the MSUs waiting in the transmit queue and return them
7597      * @param sequence First sequence number to recover, flush earlier packets
7598      */
7599     virtual void recoverMSU(int sequence);
7600 
7601     /**
7602      * Retrieve the current link status indications
7603      * @return Link status indication bits
7604      */
7605     virtual unsigned int status() const;
7606 
7607     /**
7608      * Check if the link is aligned.
7609      * The link may not be operational, the other side may be still proving.
7610      * @return True if the link is aligned
7611      */
7612     virtual bool aligned() const;
7613 
7614     /**
7615      * Check if the link is aligned and operational
7616      * @return True if the link is operational
7617      */
7618     virtual bool operational() const;
7619 
7620     /**
7621      * Execute a control operation. Operations can change the link status or
7622      *  can query the aligned status.
7623      * @param oper Operation to execute
7624      * @param params Optional parameters for the operation
7625      * @return True if the command completed successfully, for query operations
7626      *  also indicates the data link is aligned and operational
7627      */
7628     virtual bool control(Operation oper, NamedList* params = 0);
7629 
7630     /**
7631      * Process a notification generated by the attached interface
7632      * @param event Notification event reported by the interface
7633      * @return True if notification was processed
7634      */
7635     virtual bool notify(SignallingInterface::Notification event);
7636 
7637 protected:
7638     /**
7639      * Remove all attachements. Disposes the memory
7640      */
destroyed()7641     virtual void destroyed()
7642     {
7643 	SS7Layer2::attach(0);
7644 	TelEngine::destruct(SignallingReceiver::attach(0));
7645 	SignallingComponent::destroyed();
7646     }
7647 
7648     /**
7649      * Periodical timer tick used to perform alignment and housekeeping
7650      * @param when Time to use as computing base for events and timeouts
7651      */
7652     virtual void timerTick(const Time& when);
7653 
7654     /**
7655      * Process a Signalling Packet received by the hardware interface
7656      * @return True if message was successfully processed
7657      */
7658     virtual bool receivedPacket(const DataBlock& packet);
7659 
7660     /**
7661      * Process a received Fill-In Signal Unit
7662      */
7663     virtual void processFISU();
7664 
7665     /**
7666      * Process a received Link Status Signal Unit
7667      * @param status Link status indications
7668      */
7669     virtual void processLSSU(unsigned int status);
7670 
7671     /**
7672      * Push a Link Status Signal Unit down the protocol stack
7673      * @param status Link status indications
7674      * @return True if message was successfully queued
7675      */
7676     bool transmitLSSU(unsigned int status);
7677 
7678     /**
7679      * Push a Link Status Signal Unit with the current status down the protocol stack
7680      * @return True if message was successfully queued
7681      */
transmitLSSU()7682     inline bool transmitLSSU()
7683 	{ return transmitLSSU(m_lStatus); }
7684 
7685     /**
7686      * Push a Fill-In Signal Unit down the protocol stack
7687      * @return True if message was successfully queued
7688      */
7689     bool transmitFISU();
7690 
7691     /**
7692      * Initiates alignment and proving procedure
7693      * @param emergency True if emergency alignment is desired
7694      */
7695     void startAlignment(bool emergency = false);
7696 
7697     /**
7698      * Abort an alignment procedure if link errors occur
7699      * @param retry Keep trying to align
7700      */
7701     void abortAlignment(bool retry = true);
7702 
7703     /**
7704      * Start the link proving period
7705      * @return True if proving period was started
7706      */
7707     bool startProving();
7708 
7709 private:
control(NamedList & params)7710     virtual bool control(NamedList& params)
7711 	{ return SignallingDumpable::control(params,this) || SS7Layer2::control(params); }
7712     void unqueueAck(unsigned char bsn);
7713     bool txPacket(const DataBlock& packet, bool repeat, SignallingInterface::PacketType type = SignallingInterface::Unknown);
7714     void setLocalStatus(unsigned int status);
7715     void setRemoteStatus(unsigned int status);
7716     // sent but yet unacknowledged packets
7717     ObjList m_queue;
7718     // data link status (alignment) - desired, local and remote
7719     unsigned int m_status, m_lStatus, m_rStatus;
7720     // various interval period end
7721     u_int64_t m_interval;
7722     // time when resending packets
7723     u_int64_t m_resend;
7724     // time when aborting resending packets
7725     u_int64_t m_abort;
7726     // time when need to transmit next FISU/LSSU
7727     u_int64_t m_fillTime;
7728     // remote congestion indicator
7729     bool m_congestion;
7730     // backward and forward sequence numbers
7731     unsigned char m_bsn, m_fsn;
7732     // backward and forward indicator bits
7733     bool m_bib, m_fib;
7734     // last forward sequence number we sent a retransmission request
7735     unsigned char m_lastFsn;
7736     // last received backward sequence number
7737     unsigned char m_lastBsn;
7738     // last received backward indicator bit
7739     bool m_lastBib;
7740     // count of errors
7741     unsigned int m_errors;
7742     // maximum accepted errors
7743     unsigned int m_maxErrors;
7744     // packet resend interval
7745     unsigned int m_resendMs;
7746     // packet resend abort interval
7747     unsigned int m_abortMs;
7748     // FISU/LSSU soft resend interval
7749     unsigned int m_fillIntervalMs;
7750     // fill link with end-to-end FISU/LSSU
7751     bool m_fillLink;
7752     // automatically align on resume
7753     bool m_autostart;
7754     // flush MSUs after aligning
7755     bool m_flushMsus;
7756 };
7757 
7758 /**
7759  * Q.704 SS7 Layer 3 (Network) implementation on top of SS7 Layer 2
7760  * @short SS7 Layer 3 implementation on top of Layer 2
7761  */
7762 class YSIG_API SS7MTP3 : public SS7Layer3, public SS7L2User, public SignallingDumpable, public Mutex
7763 {
7764     YCLASS(SS7MTP3,SS7Layer3)
7765 public:
7766     /**
7767      * Control primitives
7768      */
7769     enum Operation {
7770 	// take linkset out of service
7771 	Pause   = 0x100,
7772 	// start linkset operation
7773 	Resume  = 0x200,
7774 	// force a MTP restart procedure
7775 	Restart = 0x300,
7776 	// get operational status
7777 	Status  = 0x400,
7778     };
7779 
7780     /**
7781      * Constructor
7782      * @param params Layer's parameters
7783      */
7784     SS7MTP3(const NamedList& params);
7785 
7786     /**
7787      * Destructor
7788      */
7789     virtual ~SS7MTP3();
7790 
7791     /**
7792      * Configure and initialize the MTP3 and all its links
7793      * @param config Optional configuration parameters override
7794      * @return True if MTP3 and at least one link were initialized properly
7795      */
7796     virtual bool initialize(const NamedList* config);
7797 
7798     /**
7799      * Push a Message Signal Unit down the protocol stack
7800      * @param msu Message data, starting with Service Indicator Octet
7801      * @param label Routing label of the MSU used in routing
7802      * @param sls Signalling Link Selection, negative to choose best
7803      * @return Link the message was successfully queued to, negative for error
7804      */
7805     virtual int transmitMSU(const SS7MSU& msu, const SS7Label& label, int sls = -1);
7806 
7807     /**
7808      * Check if the network/linkset is fully operational
7809      * @param sls Signalling Link to check, negative to check if any is operational
7810      * @return True if the linkset is enabled and operational
7811      */
7812     virtual bool operational(int sls = -1) const;
7813 
7814     /**
7815      * Retrieve inhibition flags of a specific link
7816      * @param sls Signalling Link to check
7817      * @return Inhibitions of the specified link, zero if not inhibited
7818      */
7819     virtual int inhibited(int sls) const;
7820 
7821     /**
7822      * Set and clear inhibition flags on the links
7823      * @param sls Signalling Link to modify
7824      * @param setFlags Flag bits to set ORed together
7825      * @param clrFlags Flag bits to clear  ORed together (optional)
7826      * @return True if inhibition flags were set
7827      */
7828     virtual bool inhibit(int sls, int setFlags, int clrFlags = 0);
7829 
7830     /**
7831      * Get the current congestion level of a link
7832      * @param sls Signalling Link to check for congestion, -1 for maximum
7833      * @return Congestion level, 0 if not congested, 3 if maximum congestion
7834      */
7835     virtual unsigned int congestion(int sls);
7836 
7837     /**
7838      * Get the sequence number of the last MSU received on a link
7839      * @param sls Signalling Link to retrieve MSU number from
7840      * @return Last FSN received, negative if not available
7841      */
7842     virtual int getSequence(int sls) const;
7843 
7844     /**
7845      * Remove the MSUs waiting in the transmit queue and return them
7846      * @param sls Signalling Link to recover MSUs from
7847      * @param sequence First sequence number to recover, flush earlier packets
7848      */
7849     virtual void recoverMSU(int sls, int sequence);
7850 
7851     /**
7852      * Execute a control operation on the linkset
7853      * @param oper Operation to execute
7854      * @param params Optional parameters for the operation
7855      * @return True if the command completed successfully, for query operations
7856      *  also indicates the linkset is enabled and operational
7857      */
7858     virtual bool control(Operation oper, NamedList* params = 0);
7859 
7860     /**
7861      * Attach a SS7 Layer 2 (data link) to the network transport. Attach itself to the link
7862      * @param link Pointer to data link to attach
7863      */
7864     virtual void attach(SS7Layer2* link);
7865 
7866     /**
7867      * Detach a SS7 Layer 2 (data link) from the network transport. Remove the link's L2 user
7868      * @param link Pointer to data link to detach
7869      */
7870     virtual void detach(SS7Layer2* link);
7871 
7872     /**
7873      * Query or modify layer's settings or operational parameters
7874      * @param params The list of parameters to query or change
7875      * @return True if the control operation was executed
7876      */
7877     virtual bool control(NamedList& params);
7878 
7879     /**
7880      * Check if access to a specific Point Code is allowed from this network
7881      * @param type Destination point code type
7882      * @param packedPC The destination point code
7883      * @return True if access to the specified Point Code is allowed
7884      */
7885     virtual bool allowedTo(SS7PointCode::Type type, unsigned int packedPC) const;
7886 
7887     /**
7888      * Get the total number of links attached
7889      * @return Number of attached data links
7890      */
linksTotal()7891     inline unsigned int linksTotal() const
7892 	{ return m_total; }
7893 
7894     /**
7895      * Get the number of links that are checked by maintenance
7896      * @return Number of MTN checked data links
7897      */
linksChecked()7898     inline unsigned int linksChecked() const
7899 	{ return m_checked; }
7900 
7901     /**
7902      * Get the number of links that are currently operational
7903      * @return Number of operational data links
7904      */
linksActive()7905     inline unsigned int linksActive() const
7906 	{ return m_active; }
7907 
7908     /**
7909      * Get a list of the links held by this linkset
7910      * @return A list containing the links
7911      */
links()7912     inline const ObjList* links() const
7913 	{ return &m_links; }
7914 
7915 protected:
7916     /**
7917      * Detach all links and user. Destroys the object, disposes the memory
7918      */
7919     virtual void destroyed();
7920 
7921     /**
7922      * Periodical timer tick used to perform housekeeping and link checking
7923      * @param when Time to use as computing base for events and timeouts
7924      */
7925     virtual void timerTick(const Time& when);
7926 
7927     /**
7928      * Callback called from maintenance when valid SLTA or SLTM are received
7929      * @param sls Link that was checked by maintenance
7930      * @param remote True if remote checked the link, false if local success
7931      */
7932     virtual void linkChecked(int sls, bool remote);
7933 
7934     /**
7935      * Check if we should answer with SLTA to received SLTM in maintenance()
7936      * @return True to send a SLTA for each good received SLTM
7937      */
responder()7938     virtual bool responder() const
7939 	{ return !m_inhibit; }
7940 
7941     /**
7942      * Process a MSU received from the Layer 2 component
7943      * @param msu Message data, starting with Service Indicator Octet
7944      * @param link Data link that delivered the MSU
7945      * @param sls Signalling Link the MSU was received from
7946      * @return True if the MSU was processed
7947      */
7948     virtual bool receivedMSU(const SS7MSU& msu, SS7Layer2* link, int sls);
7949 
7950     /**
7951      * Process a MSU recovered from the Layer 2 component after failure
7952      * @param msu Message data, starting with Service Indicator Octet
7953      * @param link Data link from where the MSU was recovered
7954      * @param sls Signalling Link the MSU was recovered from
7955      * @return True if the MSU was processed
7956      */
7957     virtual bool recoveredMSU(const SS7MSU& msu, SS7Layer2* link, int sls);
7958 
7959     /**
7960      * Process a notification generated by the attached data link
7961      * @param link Data link that generated the notification
7962      * @return True if notification was processed
7963      */
7964     virtual void notify(SS7Layer2* link);
7965 
7966     /**
7967      * Count the total and active number of links
7968      * @return Number of active links
7969      */
7970     unsigned int countLinks();
7971 
7972 private:
7973     ObjList m_links;
7974     // total links in linkset
7975     unsigned int m_total;
7976     // checked links in linkset
7977     unsigned int m_checked;
7978     // currently active links
7979     unsigned int m_active;
7980     // SLS to SLC shift
7981     bool m_slcShift;
7982     // inhibited flag
7983     bool m_inhibit;
7984     // warn if all links are down
7985     bool m_warnDown;
7986     // check the links before placing them in service
7987     bool m_checklinks;
7988     // realign links that don't respond to test messages anymore
7989     bool m_forcealign;
7990     // maintenance check intervals (Q.707)
7991     u_int64_t m_checkT1;
7992     u_int64_t m_checkT2;
7993     // list of allowed point codes seen from this network
7994     unsigned int* m_allowed[YSS7_PCTYPE_COUNT];
7995 };
7996 
7997 /**
7998  * Decoded Signalling Network Management (SNM) User Part message
7999  * @short SNM signalling message
8000  */
8001 class YSIG_API SS7MsgSNM : public SignallingMessage
8002 {
8003 public:
8004     /**
8005      * SNM Message type as defined by Q.704 Table 1
8006      */
8007     enum Type {
8008 	Unknown = 0,
8009 	COO  = 0x11, // Changeover Order signal
8010 	ECO  = 0x12, // Emergency Changeover Order signal
8011 	RCT  = 0x13, // Route Set Congestion Test signal
8012 	TFP  = 0x14, // Transfer Prohibited signal
8013 	RST  = 0x15, // Route Set Test for prohibited destination
8014 	RSP  = RST,  // Route Set Test for prohibited destination (ANSI)
8015 	LIN  = 0x16, // Link Inhibit signal
8016 	TRA  = 0x17, // Traffic Restart Allowed signal
8017 	DLC  = 0x18, // Data Link Connection Order signal
8018 	UPU  = 0x1a, // User Part Unavailable signal
8019 	COA  = 0x21, // Changeover Acknowledgment signal
8020 	ECA  = 0x22, // Emergency Changeover Acknowledgment signal
8021 	TFC  = 0x23, // Transfer Controlled signal
8022 	TCP  = 0x24, // Transfer Cluster Prohibited
8023 	TFPA = TCP,  // Transfer Prohibited Acknowledgment (Yellow Book only)
8024 	RSR  = 0x25, // Route Set Test for prohibited destination (national use)
8025 	LUN  = 0x26, // Link Uninhibit signal
8026 	TRW  = 0x27, // Traffic Restart Waiting (ANSI only)
8027 	CSS  = 0x28, // Connection Successful signal
8028 	XCO  = 0x31, // Extended Changeover Order signal
8029 	TFR  = 0x34, // Transfer Restricted signal (national use)
8030 	RCP  = 0x35, // Route Set Test for cluster-prohibited
8031 	LIA  = 0x36, // Link Inhibit Acknowledgment signal
8032 	CNS  = 0x38, // Connection Not Successful signal
8033 	XCA  = 0x41, // Extended Changeover Acknowledgment signal
8034 	TCR  = 0x44, // Transfer Cluster Restricted signal (ANSI only)
8035 	RCR  = 0x45, // Route Set Test for cluster-restricted (ANSI only)
8036 	LUA  = 0x46, // Link Uninhibit Acknowledgment signal
8037 	CNP  = 0x48, // Connection Not Possible signal
8038 	CBD  = 0x51, // Changeback Declaration signal
8039 	TFA  = 0x54, // Transfer Allowed signal
8040 	LID  = 0x56, // Link Inhibit Denied signal
8041 	CBA  = 0x61, // Changeback Acknowledgment signal
8042 	TCA  = 0x64, // Transfer Cluster Allowed
8043 	TFAA = TCA,  // Transfer Allowed Acknowledgment (Yellow Book only)
8044 	LFU  = 0x66, // Link Forced Uninhibit signal
8045 	LLT  = 0x76, // Link Local Inhibit Test signal
8046 	LLI  = LLT,  // Link Local Inhibit Test signal (ANSI)
8047 	LRT  = 0x86, // Link Remote Inhibit Test signal
8048 	LRI  = LRT,  // Link Remote Inhibit Test signal (ANSI)
8049     };
8050 
8051     /**
8052      * SNM Message group (H0) as defined by Q.704 15.3
8053      */
8054     enum Group {
8055 	CHM = 0x01,  // Changeover and changeback
8056 	ECM = 0x02,  // Emergency changeover
8057 	FCM = 0x03,  // Transfer controlled and signalling route set congestion
8058 	TFM = 0x04,  // Transfer prohibited/allowed/restricted
8059 	RSM = 0x05,  // Signalling route/set/test
8060 	MIM = 0x06,  // Management inhibit
8061 	TRM = 0x07,  // Traffic restart allowed
8062 	DLM = 0x08,  // Signalling data/link/connection
8063 	UFC = 0x0a,  // User part flow control
8064     };
8065 
8066     /**
8067      * Constructor
8068      * @param type Message type
8069      */
8070     SS7MsgSNM(unsigned char type);
8071 
8072     /**
8073      * Get the type of this message
8074      * @return The type of this message
8075      */
type()8076     inline unsigned char type() const
8077 	{ return m_type; }
8078 
8079     /**
8080      * Get the group this message belongs to
8081      * @return This message's group
8082      */
group()8083     inline unsigned char group() const
8084 	{ return m_type & 0x0f; }
8085 
8086     /**
8087      * Fill a string with this message's parameters for debug purposes
8088      * @param dest The destination string
8089      * @param label The routing label
8090      * @param params True to add parameters
8091      */
8092     void toString(String& dest, const SS7Label& label, bool params) const;
8093 
8094     /**
8095      * Parse a received buffer and build a message from it
8096      * @param receiver The SS7 management entity that received the MSU
8097      * @param type Message type
8098      * @param pcType The point code type contained in received MSU's label
8099      * @param buf Buffer after message head
8100      * @param len Buffer length
8101      * @return Valid message pointer of 0 on failure
8102      */
8103     static SS7MsgSNM* parse(SS7Management* receiver, unsigned char type,
8104 	SS7PointCode::Type pcType,
8105 	const unsigned char* buf, unsigned int len);
8106 
8107     /**
8108      * Get the dictionary containing the names of the message type
8109      */
8110     static const TokenDict* names();
8111 
8112     /**
8113      * Convert a SNM message type to a C string
8114      * @param type Type of SNM message to look up
8115      * @param defvalue Default string to return
8116      * @return Name of the SNM message type
8117      */
8118     static inline const char* lookup(Type type, const char* defvalue = 0)
8119 	{ return TelEngine::lookup(type,names(),defvalue); }
8120 
8121     /**
8122      * Look up a SNM message name
8123      * @param name String name of the SNM message
8124      * @param defvalue Default type to return
8125      * @return Encoded type of the SNM message
8126      */
8127     static inline Type lookup(const char* name, Type defvalue = Unknown)
8128 	{ return static_cast<Type>(TelEngine::lookup(name,names(),defvalue)); }
8129 
8130 private:
8131     unsigned char m_type;
8132 };
8133 
8134 /**
8135  * Decoded Maintenance (MTN) User Part message
8136  * @short MTN signalling message
8137  */
8138 class YSIG_API SS7MsgMTN
8139 {
8140 public:
8141     /**
8142      * MTN Message type as defined by Q.707 5.4
8143      */
8144     enum Type {
8145 	Unknown = 0,
8146 	SLTM = 0x11, // Signalling Link Test Message
8147 	SLTA = 0x21, // Signalling Link Test Acknowledgment
8148     };
8149 
8150     static const TokenDict* names();
8151 
8152     /**
8153      * Convert a MTN message type to a C string
8154      * @param type Type of MTN message to look up
8155      * @param defvalue Default string to return
8156      * @return Name of the MTN message type
8157      */
8158     static inline const char* lookup(Type type, const char* defvalue = 0)
8159 	{ return TelEngine::lookup(type,names(),defvalue); }
8160 
8161     /**
8162      * Look up a MTN message name
8163      * @param name String name of the MTN message
8164      * @param defvalue Default type to return
8165      * @return Encoded type of the MTN message
8166      */
8167     static inline Type lookup(const char* name, Type defvalue = Unknown)
8168 	{ return static_cast<Type>(TelEngine::lookup(name,names(),defvalue)); }
8169 };
8170 
8171 /**
8172  * Decoded ISDN User Part message
8173  * @short ISUP signalling message
8174  */
8175 class YSIG_API SS7MsgISUP : public SignallingMessage
8176 {
YCLASS(SS7MsgISUP,SignallingMessage)8177     YCLASS(SS7MsgISUP,SignallingMessage)
8178     friend class SS7ISUPCall;
8179 public:
8180     /**
8181      * ISUP Message type as defined by Q.762 Table 2 and Q.763 Table 4
8182      */
8183     enum Type {
8184 	Unknown = 0,
8185 	IAM  = 0x01, // Initial Address Message
8186 	SAM  = 0x02, // Subsequent Address Message
8187 	INR  = 0x03, // Information Request (national use)
8188 	INF  = 0x04, // Information (national use)
8189 	COT  = 0x05, // Continuity
8190 	ACM  = 0x06, // Address Complete Message
8191 	CON  = 0x07, // Connect
8192 	FOT  = 0x08, // Forward Transfer
8193 	ANM  = 0x09, // Answer Message
8194 	REL  = 0x0c, // Release Request
8195 	SUS  = 0x0d, // Suspend
8196 	RES  = 0x0e, // Resume
8197 	RLC  = 0x10, // Release Complete
8198 	CCR  = 0x11, // Continuity Check Request
8199 	RSC  = 0x12, // Reset Circuit
8200 	BLK  = 0x13, // Blocking
8201 	UBL  = 0x14, // Unblocking
8202 	BLA  = 0x15, // Blocking Acknowledgement
8203 	UBA  = 0x16, // Unblocking Acknowledgement
8204 	GRS  = 0x17, // Circuit Group Reset
8205 	CGB  = 0x18, // Circuit Group Blocking
8206 	CGU  = 0x19, // Circuit Group Unblocking
8207 	CGA  = 0x1a, // Circuit Group Blocking Acknowledgement
8208 	CGBA = CGA,
8209 	CUA  = 0x1b, // Circuit Group Unblocking Acknowledgement
8210 	CMR  = 0x1c, // Call Modification Request (ANSI only)
8211 	CMC  = 0x1d, // Call Modification Completed (ANSI only)
8212 	CMRJ = 0x1e, // Call Modification Rejected (ANSI only)
8213 	FACR = 0x1f, // Facility Request
8214 	FAA  = 0x20, // Facility Accepted
8215 	FRJ  = 0x21, // Facility Reject
8216 	FAD  = 0x22, // Facility Deactivated (ANSI only)
8217 	FAI  = 0x23, // Facility Information (ANSI only)
8218 	LPA  = 0x24, // Loopback Acknowledgement (national use)
8219 	CSVR = 0x25, // CUG Selection and Validation Request (ANSI only)
8220 	CSVS = 0x26, // CUG Selection and Validation Response (ANSI only)
8221 	DRS  = 0x27, // Delayed Release (ANSI only)
8222 	PAM  = 0x28, // Pass Along Message (national use)
8223 	GRA  = 0x29, // Circuit Group Reset Acknowledgement
8224 	CQM  = 0x2a, // Circuit Group Query (national use)
8225 	CQR  = 0x2b, // Circuit Group Query Response (national use)
8226 	CPR  = 0x2c, // Call Progress
8227 	CPG  = CPR,
8228 	USR  = 0x2d, // User-to-User Information
8229 	UEC  = 0x2e, // Unequipped CIC (national use)
8230 	UCIC = UEC,
8231 	CNF  = 0x2f, // Confusion
8232 	OLM  = 0x30, // Overload Message (national use)
8233 	CRG  = 0x31, // Charge Information (national use and format, ITU only)
8234 	NRM  = 0x32, // Network Resource Management
8235 	FAC  = 0x33, // Facility (national use)
8236 	UPT  = 0x34, // User Part Test
8237 	UPA  = 0x35, // User Part Available
8238 	IDR  = 0x36, // Identification Request (ITU only)
8239 	IRS  = 0x37, // Identification Response (ITU only)
8240 	SGM  = 0x38, // Segmentation
8241 	LOP  = 0x40, // Loop Prevention
8242 	APM  = 0x41, // Application Transport
8243 	PRI  = 0x42, // Pre-Release Information
8244 	SDN  = 0x43, // Subsequent Directory Number (national use)
8245 	CRA  = 0xe9, // Circuit Reservation Acknowledgement (ANSI only)
8246 	CRM  = 0xea, // Circuit Reservation (ANSI only)
8247 	CVR  = 0xeb, // Circuit Validation Response (ANSI only)
8248 	CVT  = 0xec, // Circuit Validation Test (ANSI only)
8249 	EXM  = 0xed, // Exit Message (ANSI only)
8250 	// Dummy, used for various purposes
8251 	CtrlSave = 256, // control, save circuits
8252 	CtrlCicEvent,   // control, generate circuit events, debug only
8253     };
8254 
8255     /**
8256      * ISUP Message type as defined by Q.763 Table 5
8257      */
8258     enum Parameters {
8259 	EndOfParameters                = 0,
8260 	CallReference                  = 0x01,
8261 	TransmissionMediumRequirement  = 0x02,
8262 	AccessTransport                = 0x03,
8263 	CalledPartyNumber              = 0x04,
8264 	SubsequentNumber               = 0x05,
8265 	NatureOfConnectionIndicators   = 0x06,
8266 	ForwardCallIndicators          = 0x07,
8267 	OptionalForwardCallIndicators  = 0x08,
8268 	CallingPartyCategory           = 0x09,
8269 	CallingPartyNumber             = 0x0a,
8270 	RedirectingNumber              = 0x0b,
8271 	RedirectionNumber              = 0x0c,
8272 	ConnectionRequest              = 0x0d,
8273 	InformationRequestIndicators   = 0x0e,
8274 	InformationIndicators          = 0x0f,
8275 	ContinuityIndicators           = 0x10,
8276 	BackwardCallIndicators         = 0x11,
8277 	CauseIndicators                = 0x12,
8278 	RedirectionInformation         = 0x13,
8279 	GroupSupervisionTypeIndicator  = 0x15,
8280 	RangeAndStatus                 = 0x16,
8281 	CallModificationIndicators     = 0x17, // ANSI only
8282 	FacilityIndicator              = 0x18,
8283 	FacilityInformationIndicators  = 0x19, // ANSI only
8284 	CUG_InterlockCode              = 0x1a,
8285 	Index                          = 0x1b, // ANSI only
8286 	CUG_CheckResponseIndicators    = 0x1c, // ANSI only
8287 	UserServiceInformation         = 0x1d,
8288 	SignallingPointCode            = 0x1e,
8289 	UserToUserInformation          = 0x20,
8290 	ConnectedNumber                = 0x21,
8291 	SuspendResumeIndicators        = 0x22,
8292 	TransitNetworkSelection        = 0x23,
8293 	EventInformation               = 0x24,
8294 	CircuitAssignmentMap           = 0x25, // ANSI only
8295 	CircuitStateIndicator          = 0x26,
8296 	AutomaticCongestionLevel       = 0x27,
8297 	OriginalCalledNumber           = 0x28,
8298 	OptionalBackwardCallIndicators = 0x29,
8299 	UserToUserIndicators           = 0x2a,
8300 	OriginationISCPointCode        = 0x2b, // ITU only
8301 	GenericNotification            = 0x2c, // ITU only
8302 	CallHistoryInformation         = 0x2d, // ITU only
8303 	AccessDeliveryInformation      = 0x2e, // ITU only
8304 	NetworkSpecificFacilities      = 0x2f, // ITU only
8305 	UserServiceInformationPrime    = 0x30,
8306 	PropagationDelayCounter        = 0x31, // ITU only
8307 	RemoteOperations               = 0x32,
8308 	ServiceActivation              = 0x33,
8309 	UserTeleserviceInformation     = 0x34, // ITU only
8310 	TransmissionMediumUsed         = 0x35,
8311 	CallDiversionInformation       = 0x36, // ITU only
8312 	EchoControlInformation         = 0x37, // ITU only
8313 	MessageCompatInformation       = 0x38, // ITU only
8314 	ParameterCompatInformation     = 0x39, // ITU only
8315 	MLPP_Precedence                = 0x3a, // ITU name
8316 	Precedence                     = MLPP_Precedence, // ANSI name
8317 	MCID_RequestIndicator          = 0x3b, // ITU only
8318 	MCID_ResponseIndicator         = 0x3c, // ITU only
8319 	HopCounter                     = 0x3d,
8320 	TransMediumRequirementPrime    = 0x3e, // ITU only
8321 	LocationNumber                 = 0x3f, // ITU only
8322 	RedirectionNumberRestriction   = 0x40, // ITU only
8323 	FreephoneIndicators            = 0x41, // ITU only
8324 	GenericReference               = 0x42, // ITU only
8325 	CCSScallIndication             = 0x4b,
8326 	ForwardGVNS                    = 0x4c,
8327 	BackwardGVNS                   = 0x4d,
8328 	RedirectCapability             = 0x4e, // National use
8329 	CalledINNumber                 = 0x6f,
8330 	UID_ActionIndicators           = 0x74,
8331 	UID_CapabilityIndicators       = 0x75,
8332 	RedirectCounter                = 0x77, // National use
8333 	ApplicationTransport           = 0x78,
8334 	CCNRpossibleIndicator          = 0x7a,
8335 	PivotRoutingIndicators         = 0x7c,
8336 	CalledDirectoryNumber          = 0x7d, // National use
8337 	OriginalCalledINNumber         = 0x7f,
8338 	CallingGeodeticLocation        = 0x81,
8339 	HTR_Information                = 0x82,
8340 	NetworkRoutingNumber           = 0x84, // National use
8341 	QueryOnReleaseCapability       = 0x85, // Network option
8342 	PivotStatus                    = 0x86, // National use
8343 	PivotCounter                   = 0x87,
8344 	PivotRoutingForwardInformation = 0x88,
8345 	PivotRoutingBackInformation    = 0x89,
8346 	RedirectStatus                 = 0x8a, // National use
8347 	RedirectForwardInformation     = 0x8b, // National use
8348 	RedirectBackwardInformation    = 0x8c, // National use
8349 	NumberPortabilityInformation   = 0x8d, // Network option
8350 	GenericNumber                  = 0xc0, // ITU name
8351 	GenericAddress                 = GenericNumber, // ANSI name
8352 	GenericDigits                  = 0xc1,
8353 	OperatorServicesInformation    = 0xc2, // ANSI only
8354 	Egress                         = 0xc3, // ANSI only
8355 	Jurisdiction                   = 0xc4, // ANSI only
8356 	CarrierIdentification          = 0xc5, // ANSI only
8357 	BusinessGroup                  = 0xc6, // ANSI only
8358 	GenericName                    = 0xc7, // ANSI only
8359 	NotificationIndicator          = 0xe1, // ANSI only
8360 	TransactionRequest             = 0xe3, // ANSI only
8361 	CircuitGroupCharactIndicator   = 0xe5, // ANSI only
8362 	CircuitValidationRespIndicator = 0xe6, // ANSI only
8363 	OutgoingTrunkGroupNumber       = 0xe7, // ANSI only
8364 	CircuitIdentificationName      = 0xe8, // ANSI only
8365 	CommonLanguage                 = 0xe9, // ANSI only
8366 	OriginatingLineInformation     = 0xea, // ANSI only
8367 	ChargeNumber                   = 0xeb, // ANSI only
8368 	ServiceCodeIndicator           = 0xec, // ANSI only
8369 	SpecialProcessingRequest       = 0xed, // ANSI only
8370 	CarrierSelectionInformation    = 0xee, // ANSI only
8371 	NetworkTransport               = 0xef, // ANSI only
8372 	NationalForwardCallIndicatorsLinkByLink = 0xf4, // UK-ISUP
8373 	NationalInformationIndicators           = 0xf5, // UK-ISUP
8374 	NationalInformationRequestIndicators    = 0xf6, // UK-ISUP
8375 	CalledSubscribersTerminatingFacilMarks  = 0xf7, // UK-ISUP
8376 	CallingSubscribersOriginatingFacilMarks = 0xf8, // UK-ISUP
8377 	CallingSubscribersBasicServiceMarks     = 0xf9, // UK-ISUP
8378 	CalledSubscribersBasicServiceMarks      = 0xfa, // UK-ISUP
8379 	PartialCLI                              = 0xfb, // UK-ISUP
8380 	LastDivertingLineIdentity               = 0xfc, // UK-ISUP
8381 	PresentationNumber                      = 0xfd, // UK-ISUP
8382 	NationalForwardCallIndicators           = 0xfe, // UK-ISUP
8383     };
8384 
8385     /**
8386      * Constructor
8387      * @param type Type of ISUP message as enumeration
8388      * @param cic Source/destination Circuit Identification Code
8389      */
SS7MsgISUP(Type type,unsigned int cic)8390     inline SS7MsgISUP(Type type, unsigned int cic)
8391 	: SignallingMessage(lookup(type,"Unknown")), m_type(type), m_cic(cic)
8392 	{ }
8393 
8394     /**
8395      * Destructor
8396      */
~SS7MsgISUP()8397     virtual ~SS7MsgISUP()
8398 	{ }
8399 
8400     /**
8401      * Get the type of this message
8402      * @return The type of this message as enumeration
8403      */
type()8404     inline Type type() const
8405 	{ return m_type; }
8406 
8407     /**
8408      * Get the source/destination Circuit Identification Code of this message
8409      * @return The source/destination Circuit Identification Code of this message
8410      */
cic()8411     inline unsigned int cic() const
8412 	{ return m_cic; }
8413 
8414     /**
8415      * Fill a string with this message's parameters for debug purposes
8416      * @param dest The destination string
8417      * @param label The routing label
8418      * @param params True to add parameters
8419      * @param raw Optional raw message data to be added to destination
8420      * @param rawLen Raw data length
8421      */
8422     void toString(String& dest, const SS7Label& label, bool params,
8423 	const void* raw = 0, unsigned int rawLen = 0) const;
8424 
8425     /**
8426      * Get the dictionary with the message names
8427      * @return Pointer to the dictionary with the message names
8428      */
8429     static const TokenDict* names();
8430 
8431     /**
8432      * Convert an ISUP message type to a C string
8433      * @param type Type of ISUP message to look up
8434      * @param defvalue Default string to return
8435      * @return Name of the ISUP message type
8436      */
8437     static inline const char* lookup(Type type, const char* defvalue = 0)
8438 	{ return TelEngine::lookup(type,names(),defvalue); }
8439 
8440     /**
8441      * Look up an ISUP message name
8442      * @param name String name of the ISUP message
8443      * @param defvalue Default type to return
8444      * @return Encoded type of the ISUP message
8445      */
8446     static inline Type lookup(const char* name, Type defvalue = Unknown)
8447 	{ return static_cast<Type>(TelEngine::lookup(name,names(),defvalue)); }
8448 
8449 private:
8450     Type m_type;                         // Message type
8451     unsigned int m_cic;                  // Source/destination Circuit Identification Code
8452 };
8453 
8454 /**
8455  * Implementation of SS7 SNM User Part (Management) - Q.704
8456  * @short SS7 SNM implementation
8457  */
8458 class YSIG_API SS7Management : public SS7Layer4, public Mutex
8459 {
8460     YCLASS(SS7Management,SS7Layer4)
8461 public:
8462     /**
8463      * Constructor
8464      */
8465     SS7Management(const NamedList& params, unsigned char sio = SS7MSU::SNM|SS7MSU::National);
8466 
8467 protected:
8468     /**
8469      * Process a MSU received from a Layer 3 component
8470      * @param msu Message data, starting with Service Indicator Octet
8471      * @param label Routing label of the received MSU
8472      * @param network Network layer that delivered the MSU
8473      * @param sls Signalling Link the MSU was received from
8474      * @return Result of MSU processing
8475      */
8476     virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
8477 
8478     /**
8479      * Set and clear inhibition flags on a link of a router attached network
8480      * @param link Signalling Link to modify identified by a routing label
8481      * @param setFlags Flag bits to set ORed together
8482      * @param clrFlags Flag bits to clear  ORed together (optional)
8483      * @return True if inhibition flags were set
8484      */
8485     bool inhibit(const SS7Label& link, int setFlags, int clrFlags = 0);
8486 
8487     /**
8488      * Check inhibition flags on a link of a router attached network
8489      * @param link Signalling Link to check identified by a routing label
8490      * @param flags Flag bits to check ORed together
8491      * @return True if any of the specified inhibition flags are set
8492      */
8493     bool inhibited(const SS7Label& link, int flags);
8494 
8495     /**
8496      * Recover MSUs from a link
8497      * @param link Signalling Link to recover identified by a routing label
8498      * @param sequence Starting sequence number to recover
8499      */
8500     void recover(const SS7Label& link, int sequence);
8501 
8502     /**
8503      * Process a notification generated by the attached network layer
8504      * @param link Network or linkset that generated the notification
8505      * @param sls Signallink Link that generated the notification, negative if none
8506      * @return True if notification was processed
8507      */
8508     virtual void notify(SS7Layer3* link, int sls);
8509 
8510     /**
8511      * Query or modify the management settings or operational parameters
8512      * @param params The list of parameters to query or change
8513      * @return True if the control operation was executed
8514      */
8515     virtual bool control(NamedList& params);
8516 
8517     /**
8518      * Method called periodically by the engine to retransmit messages
8519      * @param when Time to use as computing base for timers
8520      */
8521     virtual void timerTick(const Time& when);
8522 
8523 private:
8524     bool postpone(SS7MSU* msu, const SS7Label& label, int txSls,
8525 	u_int64_t interval, u_int64_t global = 0, bool force = false, const Time& when = Time());
8526     bool timeout(const SS7MSU& msu, const SS7Label& label, int txSls, bool final);
8527     bool timeout(SignallingMessageTimer& timer, bool final);
8528     SignallingMessageTimerList m_pending;
8529     bool m_changeMsgs;
8530     bool m_changeSets;
8531     bool m_neighbours;
8532 };
8533 
8534 /**
8535  * Implementation of SS7 MTP Test User Part - Q.782 2.3
8536  * @short SS7 MTP Test Traffic implementation
8537  */
8538 class YSIG_API SS7Testing : public SS7Layer4, public Mutex
8539 {
YCLASS(SS7Testing,SS7Layer4)8540     YCLASS(SS7Testing,SS7Layer4)
8541 public:
8542     /**
8543      * Constructor
8544      */
8545     inline SS7Testing(const NamedList& params, unsigned char sio = SS7MSU::MTP_T|SS7MSU::National)
8546 	: SignallingComponent(params.safe("SS7Testing"),&params,"ss7-test"),
8547 	  SS7Layer4(sio,&params),
8548 	  Mutex(true,"SS7Testing"),
8549 	  m_timer(0), m_exp(0), m_seq(0), m_len(16), m_sharing(false)
8550 	{ }
8551 
8552     /**
8553      * Configure and initialize the user part
8554      * @param config Configuration parameters
8555      * @return True if the component was initialized properly
8556      */
8557     virtual bool initialize(const NamedList* config);
8558 
8559     /**
8560      * Query or modify the test part settings or operational parameters
8561      * @param params The list of parameters to query or change
8562      * @return True if the control operation was executed
8563      */
8564     virtual bool control(NamedList& params);
8565 
8566 protected:
8567     /**
8568      * Process a MSU received from a Layer 3 component
8569      * @param msu Message data, starting with Service Indicator Octet
8570      * @param label Routing label of the received MSU
8571      * @param network Network layer that delivered the MSU
8572      * @param sls Signalling Link the MSU was received from
8573      * @return Result of MSU processing
8574      */
8575     virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
8576 
8577     /**
8578      * Process a notification generated by the attached network layer
8579      * @param link Network or linkset that generated the notification
8580      * @param sls Signallink Link that generated the notification, negative if none
8581      * @return True if notification was processed
8582      */
8583     virtual void notify(SS7Layer3* link, int sls);
8584 
8585     /**
8586      * Method called periodically by the engine to emit new messages
8587      * @param when Time to use as computing base for timers
8588      */
8589     virtual void timerTick(const Time& when);
8590 
8591 private:
8592     bool sendTraffic();
8593     void setParams(const NamedList& params, bool setSeq = false);
8594     SignallingTimer m_timer;
8595     SS7Label m_lbl;
8596     u_int32_t m_exp;
8597     u_int32_t m_seq;
8598     u_int16_t m_len;
8599     bool m_sharing;
8600 };
8601 
8602 /**
8603  * A signalling call using SS7 ISUP protocol
8604  * @short An SS7 ISUP call
8605  */
8606 class YSIG_API SS7ISUPCall : public SignallingCall
8607 {
8608     friend class SS7ISUP;
8609 public:
8610     /**
8611      * Call state enumerators
8612      */
8613     enum State {
8614 	// NOTE: Keep the order of state values: the code relies on it
8615 	Null      = 0,                   // No message exchanged
8616 	Testing   = 1,                   // IAM but waiting for continuity check
8617 	Setup     = 2,                   // IAM (initial address)
8618 	Accepted  = 3,                   // ACM (address complete)
8619 	Ringing   = 4,                   // CPM (call progress)
8620 	Answered  = 5,                   // ANM (answer)
8621 	Releasing = 6,                   // REL (release)
8622 	Released  = 7                    // Call released, no message or events allowed
8623     };
8624 
8625     /**
8626      * Destructor.
8627      * Complete call release. Releas circuit. Remove itself from controller's list
8628      */
8629     virtual ~SS7ISUPCall();
8630 
8631     /**
8632      * Get the call state
8633      * @return The call state as enumeration
8634      */
state()8635     inline State state() const
8636 	{ return m_state; }
8637 
8638     /**
8639      * Check if the call is a not test one in early state
8640      * @return True if this a non test call in early state
8641      */
earlyState()8642     inline bool earlyState() const
8643 	{ return m_state <= Setup && !m_testCall; }
8644 
8645     /**
8646      * Get the call's circuit range
8647      * @return The call's circuit range
8648      */
cicRange()8649     inline const String& cicRange() const
8650 	{ return m_cicRange; }
8651 
8652     /**
8653      * Get the call id (the code of the circuit reserved for this call)
8654      * @return The call id
8655      */
id()8656     inline unsigned int id() const
8657 	{ return m_circuit ? m_circuit->code() : 0; }
8658 
8659     /**
8660      * Get an event from this call
8661      * This method is thread safe
8662      * @param when The current time
8663      * @return SignallingEvent pointer or 0 if no events
8664      */
8665     virtual SignallingEvent* getEvent(const Time& when);
8666 
8667     /**
8668      * Send an event to this call
8669      * @param event The event to send
8670      * @return True if the operation succedded
8671      */
8672     virtual bool sendEvent(SignallingEvent* event);
8673 
8674     /**
8675      * Set termination flag. Set termination reason if not already set
8676      * @param gracefully True to send RLC on termination, false to destroy the call without notification
8677      * @param reason Termination reason
8678      * @param diagnostic Optional diagnostic data to be sent with termination reason
8679      * @param location Optional release location
8680      */
8681     inline void setTerminate(bool gracefully, const char* reason = 0,
8682 	const char* diagnostic = 0, const char* location = 0)
8683     {
8684 	Lock lock(this);
8685 	m_terminate = true;
8686 	m_gracefully = gracefully;
8687 	setReason(reason,0,diagnostic,location);
8688     }
8689 
8690     /**
8691      * Get a pointer to this object or other data
8692      * @param name Object name
8693      * @return The requested pointer or 0 if not exists
8694      */
8695     virtual void* getObject(const String& name) const;
8696 
8697 protected:
8698     /**
8699      * Constructor
8700      * @param controller The call controller
8701      * @param cic The reserved circuit
8702      * @param local The local point code used to create the routing label for sent messages
8703      * @param remote The remote point code used to create the routing label for sent messages
8704      * @param outgoing Call direction
8705      * @param sls Optional link for the routing label
8706      * @param range Optional range used to re-allocate a circuit for this call if necessary
8707      * @param testCall True if this is a test call
8708      */
8709     SS7ISUPCall(SS7ISUP* controller, SignallingCircuit* cic,
8710 	const SS7PointCode& local, const SS7PointCode& remote, bool outgoing,
8711 	int sls = -1, const char* range = 0, bool testCall = false);
8712 
8713     /**
8714      * Release call. Stop timers. Send a RLC (Release Complete) message if it should terminate gracefully
8715      * Decrease the object's referrence count and generate a Release event if not final
8716      * This method is thread safe
8717      * @param final True if called from destructor
8718      * @param msg Received message with parameters if any
8719      * @param reason Optional release reason
8720      * @param timeout True if this is method is called due to T5 timer expiry
8721      * @return SignallingEvent pointer or 0
8722      */
8723     SignallingEvent* releaseComplete(bool final, SS7MsgISUP* msg = 0, const char* reason = 0,
8724 	bool timeout = false);
8725 
8726     /**
8727      * Check if the call's circuit can be replaced at this time
8728      * @return True if the circuit can be replaced
8729      */
8730     bool canReplaceCircuit();
8731 
8732     /**
8733      * Replace the circuit reserved for this call. Release the already reserved circuit.
8734      * Retransmit the initial IAM request on success.
8735      * On failure set the termination flag and release the new circuit if valid.
8736      * If false is returned, the call is prepared to return a Release event.
8737      * This method is thread safe
8738      * @param circuit The new circuit reserved for this call
8739      * @param msg Optional message to send before IAM (it will be consumed)
8740      * @return False if the state is greater then Setup, the call is not outgoing or the new circuit is 0
8741      */
8742     bool replaceCircuit(SignallingCircuit* circuit, SS7MsgISUP* msg = 0);
8743 
8744     /**
8745      * Stop waiting for a SGM (Segmentation) message when another message is received by the controller.
8746      * This method is thread safe
8747      * @param discard True to discard (destruct) the segment waiting message if any
8748      */
8749     void stopWaitSegment(bool discard);
8750 
8751 private:
8752     // Initialize/set IAM message parameters
8753     // @param msg Valid ISUP message
8754     // @param outgoing Message direction: true for outgoing
8755     // @param sigMsg Valid signalling message with parameters if outgoing
8756     bool copyParamIAM(SS7MsgISUP* msg, bool outgoing = false, SignallingMessage* sigMsg = 0);
8757     // If already releasing, set termination flag. Otherwise, send REL (Release) message
8758     // Set m_lastEvent if event is 0 (the method is called internally)
8759     // @param event Event with the parameters. 0 if release is started on some timeout
8760     // @param msg Received message to put in release event
8761     // @return Generated release event if any
8762     SignallingEvent* release(SignallingEvent* event = 0, SS7MsgISUP* msg = 0);
8763     // Set termination reason from message or parameter
8764     void setReason(const char* reason, SignallingMessage* msg, const char* diagnostic = 0,
8765 	const char* location = 0);
8766     // Accept send/receive messages in current state based on call direction
8767     bool validMsgState(bool send, SS7MsgISUP::Type type, bool hasBkwCallInd = false);
8768     // Connect the reserved circuit. Return false if it fails. Return true if this call is a signalling only one
8769     bool connectCircuit(const char* special = 0);
8770     // Transmit the IAM message. Start IAM timer if not started
8771     bool transmitIAM();
8772     // Transmit SAM digits
8773     bool transmitSAM(const char* extra = 0);
8774     // (Re)transmit REL. Create and populate message if needed. Remember sls
8775     bool transmitREL(const NamedList* params = 0);
8776     // Check if the circuit needs continuity testing
8777     bool needsTesting(const SS7MsgISUP* msg);
8778     // Stop waiting for a SGM (Segmentation) message. Copy parameters to the pending segmented message if sgm is valid.
8779     // Change call state and set m_lastEvent
8780     // @param sgm Optional received SGM message with parameters to be added to the pending segmented message
8781     // @param timeout True if waiting timer timed out. Ignored if sgm is non null
8782     // @return m_lastEvent
8783     SignallingEvent* processSegmented(SS7MsgISUP* sgm = 0, bool timeout = false);
8784     // Transmit message. Set routing label's link if not already set
8785     inline bool transmitMessage(SS7MsgISUP* msg);
8786     // Get the ISUP call controller
8787     inline SS7ISUP* isup() const;
8788     // Set overlapped flag. Output a debug message
8789     void setOverlapped(bool on, bool numberComplete = true);
8790 
8791     State m_state;                       // Call state
8792     bool m_testCall;                     // Test only call
8793     SignallingCircuit* m_circuit;        // Circuit reserved for this call
8794     String m_cicRange;                   // The range used to re(alloc) a circuit
8795     SS7Label m_label;                    // The routing label for this call
8796     bool m_terminate;                    // Termination flag
8797     bool m_gracefully;                   // Terminate gracefully: send RLC
8798     bool m_circuitChanged;               // Circuit change flag
8799     bool m_circuitTesting;               // The circuit is tested for continuity
8800     bool m_inbandAvailable;              // Inband data is available
8801     int m_replaceCounter;                // Circuit replace counter
8802     String m_format;                     // Data format used by the circuit
8803     String m_reason;                     // Termination reason
8804     String m_diagnostic;                 // Termination diagnostic
8805     String m_location;                   // Termination location
8806     SS7MsgISUP* m_iamMsg;                // Message with the call parameters for outgoing calls
8807     SS7MsgISUP* m_sgmMsg;                // Pending received message with segmentation flag set
8808     SS7MsgISUP* m_relMsg;                // Release message preserved for retransmissions
8809     // Overlapped
8810     String m_samDigits;                  // SAM digits
8811     unsigned int m_sentSamDigits;        // The number of sent SAM digits
8812     // Timers
8813     SignallingTimer m_relTimer;          // Send release
8814     SignallingTimer m_iamTimer;          // Send initial address
8815     SignallingTimer m_sgmRecvTimer;      // Receive segmented message
8816     SignallingTimer m_contTimer;         // Continuity timer
8817     SignallingTimer m_anmTimer;          // T9 ACM -> ANM timer
8818 };
8819 
8820 /**
8821  * Implementation of SS7 ISDN User Part
8822  * @short SS7 ISUP implementation
8823  */
8824 class YSIG_API SS7ISUP : public SignallingCallControl, public SS7Layer4
8825 {
YCLASS(SS7ISUP,SS7Layer4)8826     YCLASS(SS7ISUP,SS7Layer4)
8827     friend class SS7ISUPCall;
8828 public:
8829     /**
8830      * Special SLS values
8831      */
8832     enum {
8833 	SlsAuto    = -1,
8834 	SlsLatest  = -2,
8835 	SlsCircuit = -3,
8836 	SlsDefault = -4
8837     };
8838 
8839     enum ChargeProcess {
8840 	Confusion,
8841 	Ignore,
8842 	Raw,
8843 	Parsed
8844     };
8845 
8846     /**
8847      * Constructor
8848      * @param params Call controller's parameters
8849      * @param sio The default Service Information Octet
8850      */
8851     SS7ISUP(const NamedList& params, unsigned char sio = SS7MSU::ISUP|SS7MSU::National);
8852 
8853     /**
8854      * Destructor
8855      */
8856     virtual ~SS7ISUP();
8857 
8858     /**
8859      * Configure and initialize the call controller and user part
8860      * @param config Optional configuration parameters override
8861      * @return True if ISUP was initialized properly
8862      */
8863     virtual bool initialize(const NamedList* config);
8864 
8865     /**
8866      * Get the controller's status as text
8867      * @return Controller status name
8868      */
8869     virtual const char* statusName() const;
8870 
8871     /**
8872      * Attach a SS7 network or router to this service. Detach itself from the old one
8873      * @param network Pointer to network or router to attach
8874      */
8875     virtual void attach(SS7Layer3* network);
8876 
8877     /**
8878      * Get the length of the Circuit Identification Code for this user part
8879      * @return Length of the CIC field in octets
8880      */
cicLen()8881     unsigned int cicLen() const
8882 	{ return m_cicLen; }
8883 
8884     /**
8885      * Get the default data format
8886      * @return The default data format
8887      */
format()8888     const String& format() const
8889 	{ return m_format; }
8890 
8891     /**
8892      * Check if the message parser of this controller should ignore unknown digits encoding
8893      * @return True if unknown digits are ignored
8894      */
ignoreUnknownAddrSignals()8895     inline bool ignoreUnknownAddrSignals() const
8896 	{ return m_ignoreUnkDigits; }
8897 
8898     /**
8899      * Append a point code to the list of point codes serviced by this controller
8900      *  if not already there. Set default point code if requested.
8901      * If the list is empty, the default point code is set to the first point code added
8902      * @param pc The point code to append
8903      * @param def True if this point code is the default for outgoing calls
8904      * @return False if the point code is invalid for this call controller type. If true is returned, don't reuse the pointer
8905      */
8906     bool setPointCode(SS7PointCode* pc, bool def);
8907 
8908     /**
8909      * Append all point codes from a parameter list, use "pointcode" and
8910      *  "defaultpointcode" parameters
8911      * @param params List of parameters to take point codes from
8912      * @return Count of point codes added
8913      */
8914     unsigned int setPointCode(const NamedList& params);
8915 
8916     /**
8917      * Check if the given point code is serviced by this controller
8918      * @param pc The point code to check
8919      * @return SS7PointCode pointer or 0 if not found
8920      */
8921     SS7PointCode* hasPointCode(const SS7PointCode& pc);
8922 
8923     /**
8924      * Check if this controller should handle a remote point code
8925      * @param pc The remote point code to check
8926      * @return True if pc matches the remote or there is no remote set
8927      */
handlesRemotePC(const SS7PointCode & pc)8928     inline bool handlesRemotePC(const SS7PointCode& pc) const
8929 	{ return !m_remotePoint || (pc == *m_remotePoint); }
8930 
8931     /**
8932      * Set a routing label to be used for outgoing messages
8933      * @param label Routing label to set
8934      * @param opc Originating point code
8935      * @param dpc Destination point code
8936      * @param sls Signalling Link Selection
8937      */
8938     inline void setLabel(SS7Label& label, const SS7PointCode& opc, const SS7PointCode& dpc,
8939 	unsigned char sls = 255)
8940 	{ label.assign(m_type,dpc,opc,sls); }
8941 
8942     /**
8943      * Set debug data of this call controller
8944      * @param printMsg Enable/disable message printing on output
8945      * @param extendedDebug Enable/disable hex data dump if print messages is enabled
8946      */
setDebug(bool printMsg,bool extendedDebug)8947     inline void setDebug(bool printMsg, bool extendedDebug)
8948 	{ m_extendedDebug = ((m_printMsg = printMsg) && extendedDebug); }
8949 
8950     /**
8951      * Create a new MSU populated with type, routing label and space for fixed part
8952      * @param type Type of ISUP message
8953      * @param ssf Subservice Field
8954      * @param label Routing label for the new MSU
8955      * @param cic Circuit Identification Code
8956      * @param params Optional parameter list
8957      * @return Pointer to the new MSU or NULL if an error occured
8958      */
8959     virtual SS7MSU* createMSU(SS7MsgISUP::Type type, unsigned char ssf,
8960 	const SS7Label& label, unsigned int cic, const NamedList* params = 0) const;
8961 
8962     /**
8963      * Create an outgoing call. Send a NewCall event with the given msg parameter
8964      * This method is thread safe
8965      * @param msg Call parameters
8966      * @param reason Failure reason if any
8967      * @return Referenced SignallingCall pointer on success or 0 on failure
8968      */
8969     virtual SignallingCall* call(SignallingMessage* msg, String& reason);
8970 
8971     /**
8972      * Converts an ISUP message to a Message Signal Unit and push it down the protocol stack.
8973      * The given message is consumed
8974      * @param msg The message to send
8975      * @param label The routing label for the message
8976      * @param recvLbl True if the given label is from a received message. If true, a new routing
8977      *  label will be created from the received one
8978      * @param sls Signalling Link to use for the new routing label. Ignored if recvLbl is false
8979      * @return Link the message was successfully queued to, negative for error
8980      */
8981     int transmitMessage(SS7MsgISUP* msg, const SS7Label& label, bool recvLbl, int sls = SlsDefault);
8982 
8983     /**
8984      * Cleanup calls
8985      * This method is thread safe
8986      * @param reason Cleanup reason
8987      */
8988     virtual void cleanup(const char* reason = "net-out-of-order");
8989 
8990     /**
8991      * Query or modify ISUP's settings or operational parameters
8992      * @param params The list of parameters to query or change
8993      * @return True if the control operation was executed
8994      */
8995     virtual bool control(NamedList& params);
8996 
8997     /**
8998      * Decode an ISUP message buffer to a list of parameters
8999      * @param msg Destination list of parameters
9000      * @param msgType The message type
9001      * @param pcType The point code type (message version)
9002      * @param paramPtr Pointer to the Parameter area (just after the message type)
9003      * @param paramLen Length of the Parameter area
9004      * @return True if the mesage was successfully parsed
9005      */
9006     bool decodeMessage(NamedList& msg, SS7MsgISUP::Type msgType, SS7PointCode::Type pcType,
9007 	const unsigned char* paramPtr, unsigned int paramLen);
9008 
9009     /**
9010      * Encode an ISUP list of parameters to a buffer.
9011      * The input list may contain a 'message-prefix' parameter to override this controller's prefix
9012      * @param buf Destination buffer
9013      * @param msgType The message type
9014      * @param pcType The point code type (message version)
9015      * @param params Message list of parameters
9016      * @param cic Optional cic to be added before mesage
9017      * @return True if the mesage was successfully encoded
9018      */
9019     bool encodeMessage(DataBlock& buf, SS7MsgISUP::Type msgType, SS7PointCode::Type pcType,
9020 	const NamedList& params, unsigned int* cic = 0);
9021 
9022     /**
9023      * Process parameter compatibility lists.
9024      * Terminate an existing call if a non emtpy release call parameter(s) list is found.
9025      * Send CNF if non emtpy cnf parameter(s) list is found
9026      * @param list Message parameter list
9027      * @param cic The circuit code
9028      * @param callReleased Optional pointer to boolean value to be set if a call was released
9029      * @return True if any parameter compatibility was handled
9030      */
9031     bool processParamCompat(const NamedList& list, unsigned int cic, bool* callReleased = 0);
9032 
9033     /**
9034      * Obtain the way that charge message should be processed
9035      * @return The way that charge message should be processed
9036      */
getChargeProcessType()9037     inline ChargeProcess getChargeProcessType() const
9038 	{ return m_chargeProcessType; }
9039 
9040 protected:
9041     /**
9042      * Remove all links with other layers. Disposes the memory
9043      */
9044     virtual void destroyed();
9045 
9046     /**
9047      * Send CGU if not already done. Check timeouts
9048      * @param when Time to use as computing base for timeouts
9049      */
9050     virtual void timerTick(const Time& when);
9051 
9052     /**
9053      * Process a notification generated by the attached network layer
9054      * @param link Network or linkset that generated the notification
9055      * @param sls Signalling Link that generated the notification, negative if none
9056      */
9057     virtual void notify(SS7Layer3* link, int sls);
9058 
9059     /**
9060      * Create a new MSU populated with type, routing label and space for fixed part
9061      * @param type Type of ISUP message
9062      * @param sio Service Information Octet
9063      * @param label Routing label for the new MSU
9064      * @param cic Circuit Identification Code
9065      * @param params Parameter list
9066      * @return Pointer to the new MSU or NULL if an error occured
9067      */
9068     SS7MSU* buildMSU(SS7MsgISUP::Type type, unsigned char sio,
9069 	const SS7Label& label, unsigned int cic, const NamedList* params) const;
9070 
9071     /**
9072      * Process a MSU received from a Layer 3 component
9073      * @param msu Message data, starting with Service Indicator Octet
9074      * @param label Routing label of the received MSU
9075      * @param network Network layer that delivered the MSU
9076      * @param sls Signalling Link the MSU was received from
9077      * @return Result of MSU processing
9078      */
9079     virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
9080 
9081     /**
9082      * Process a MSU received from a Layer 3 component
9083      * @param type Type of ISUP message
9084      * @param cic Circuit Identification Code
9085      * @param paramPtr Pointer to the Parameter area
9086      * @param paramLen Length of the Parameter area
9087      * @param label Routing label of the received MSU
9088      * @param network Network layer that delivered the MSU
9089      * @param sls Signalling Link the MSU was received from
9090      * @return True if the MSU was processed
9091      */
9092     virtual bool processMSU(SS7MsgISUP::Type type, unsigned int cic,
9093         const unsigned char* paramPtr, unsigned int paramLen,
9094 	const SS7Label& label, SS7Layer3* network, int sls);
9095 
9096     /**
9097      * Notification for receiving User Part Unavailable
9098      * @param type Type of Point Code
9099      * @param node Node on which the User Part is unavailable
9100      * @param part User Part (service) reported unavailable
9101      * @param cause Unavailability cause - Q.704 15.17.5
9102      * @param label Routing label of the UPU message
9103      * @param sls Signaling link the UPU was received on
9104      */
9105     virtual void receivedUPU(SS7PointCode::Type type, const SS7PointCode node,
9106 	SS7MSU::Services part, unsigned char cause, const SS7Label& label, int sls);
9107 
9108     /**
9109      * Process an event received from a non-reserved circuit
9110      * @param event The event, will be consumed and zeroed
9111      * @param call Optional signalling call whose circuit generated the event
9112      * @return Signalling event pointer or 0
9113      */
9114     virtual SignallingEvent* processCircuitEvent(SignallingCircuitEvent*& event,
9115 	SignallingCall* call = 0);
9116 
9117     /**
9118      * Initiate circuit reset. The circuit must be already reserved
9119      * This method is thread safe
9120      * @param cic The circuit to reset. Its referrence counter will be decreased and
9121      *  the pointer will be zeroed
9122      * @param timer Ellapsed timer
9123      * @return True if the circuit reset was initiated
9124      */
9125     bool startCircuitReset(SignallingCircuit*& cic, const String& timer);
9126 
9127     /**
9128      * Length of the Circuit Identification Code in octets
9129      */
9130     unsigned int m_cicLen;
9131 
9132 private:
9133     // Process a received message that should be processed by a call
9134     // @param msg The received message
9135     // @param label The routing label of the received message
9136     // @param sls Signalling Link the message was received from
9137     void processCallMsg(SS7MsgISUP* msg, const SS7Label& label, int sls);
9138     // Process a received message that should be processed by this call controller
9139     // @param msg The received message
9140     // @param label The routing label of the received message
9141     // @param sls Signalling Link the message was received from
9142     void processControllerMsg(SS7MsgISUP* msg, const SS7Label& label, int sls);
9143     // Replace a call's circuit if checkCall is true
9144     // Clear lock flags of the circuit. Release currently reseting circuit if the code match
9145     // Return false if the given circuit doesn't exist
9146     bool resetCircuit(unsigned int cic, bool remote, bool checkCall);
9147     // Block/unblock a circuit side (local or remote)
9148     // Return false if the given circuit doesn't exist
9149     bool blockCircuit(unsigned int cic, bool block, bool remote, bool hwFail,
9150 	bool changed, bool changedState, bool resetLocking = false);
9151     // Find a call by its circuit identification code
9152     // This method is not thread safe
9153     SS7ISUPCall* findCall(unsigned int cic);
9154     // Find a call by its circuit identification code
9155     // This method is thread safe
findCall(unsigned int cic,RefPointer<SS7ISUPCall> & call)9156     inline void findCall(unsigned int cic, RefPointer<SS7ISUPCall>& call) {
9157 	    Lock mylock(this);
9158 	    call = findCall(cic);
9159 	}
9160     // Encode a raw message
9161     SS7MSU* encodeRawMessage(SS7MsgISUP::Type type, unsigned char sio,
9162 	const SS7Label& label, unsigned int cic, const String& param) const;
9163     // Send blocking/unblocking messages.
9164     // Restart the re-check timer if there is any (un)lockable, not sent cic
9165     // Return false if no request was sent
9166     bool sendLocalLock(const Time& when = Time());
9167     // Fill label from local/remote point codes
9168     // This method is thread safe
9169     // Return a true if local and remote point codes are valid
9170     bool setLabel(SS7Label& label, unsigned int cic);
9171     // Retrieve a pending message
9172     SignallingMessageTimer* findPendingMessage(SS7MsgISUP::Type type, unsigned int cic,
9173 	bool remove = false);
9174     // Retrieve a pending message with given parameter
9175     SignallingMessageTimer* findPendingMessage(SS7MsgISUP::Type type, unsigned int cic,
9176 	const String& param, const String& value, bool remove = false);
9177     // Transmit a list of messages. Return true if at least 1 message was sent
9178     bool transmitMessages(ObjList& list);
9179     // Handle circuit(s) (un)block command
9180     bool handleCicBlockCommand(const NamedList& p, bool block);
9181     // Handle remote circuit(s) (un)block command
9182     bool handleCicBlockRemoteCommand(const NamedList& p, unsigned int* cics,
9183 	unsigned int count, bool block);
9184     // Handle circuit(s) event generation command
9185     bool handleCicEventCommand(const NamedList& p);
9186     // Try to start single circuit (un)blocking. Set a pending operation on success
9187     // @param force True to ignore resetting/(un)blocking flags of the circuit
9188     // Return built message to be sent on success
9189     SS7MsgISUP* buildCicBlock(SignallingCircuit* cic, bool block, bool force = false);
9190     // Replace circuit for outgoing calls in Setup state
9191     // Send REL/RSC before repeat attempt
9192     void replaceCircuit(unsigned int cic, const String& map, bool rel = true);
9193     // Handle circuit hw-fail block
9194     // Replace cics for outgoing calls. Terminate incoming
9195     void cicHwBlocked(unsigned int cic, const String& map);
9196 
9197     SS7PointCode::Type m_type;           // Point code type of this call controller
9198     ObjList m_pointCodes;                // Point codes serviced by this call controller
9199     SS7PointCode* m_defPoint;            // Default point code for outgoing calls
9200     SS7PointCode* m_remotePoint;         // Default remote point code for outgoing calls and maintenance
9201     unsigned char m_sls;                 // Last known valid SLS
9202     bool m_earlyAcm;                     // Accept progress/ringing in early ACM
9203     bool m_inn;                          // Routing to internal network number flag
9204     int m_defaultSls;                    // Default SLS to use in outbound calls
9205     unsigned int m_maxCalledDigits;      // Maximum digits allowed in Called Number in IAM
9206     String m_numPlan;                    // Numbering plan
9207     String m_numType;                    // Number type
9208     String m_numPresentation;            // Number presentation
9209     String m_numScreening;               // Number screening
9210     String m_callerCat;                  // Caller party category
9211     String m_format;                     // Default format
9212     String m_continuity;                 // Continuity test type
9213     bool m_confirmCCR;                   // Send LPA in response to CCR
9214     bool m_dropOnUnknown;                // Drop call in early state on unknown message
9215     bool m_ignoreGRSSingle;              // Ignore (drop) GRS with range 0 (1 circuit affected)
9216     bool m_ignoreCGBSingle;              // Ignore (drop) CGB with range 0 (1 circuit in map)
9217     bool m_ignoreCGUSingle;              // Ignore (drop) CGU with range 0 (1 circuit in map)
9218     bool m_duplicateCGB;                 // Send duplicate CGB messages (ANSI)
9219     bool m_ignoreUnkDigits;              // Check if the message parser should ignore unknown digits encoding
9220     bool m_l3LinkUp;                     // Flag indicating the availability of a Layer3 data link
9221     ChargeProcess m_chargeProcessType;   // Indicates the way that charge message should be processed
9222     u_int64_t m_t1Interval;              // Q.764 T1 timer interval
9223     u_int64_t m_t5Interval;              // Q.764 T5 timer interval
9224     u_int64_t m_t7Interval;              // Q.764 T7 timer interval
9225     u_int64_t m_t9Interval;              // Q.764 T9 AMM/CON recv timer interval
9226     u_int64_t m_t12Interval;             // Q.764 T12 BLK timer interval
9227     u_int64_t m_t13Interval;             // Q.764 T13 BLK global timer interval
9228     u_int64_t m_t14Interval;             // Q.764 T14 UBL timer interval
9229     u_int64_t m_t15Interval;             // Q.764 T15 UBL global timer interval
9230     u_int64_t m_t16Interval;             // Q.764 T16 RSC timer interval
9231     u_int64_t m_t17Interval;             // Q.764 T17 timer interval
9232     u_int64_t m_t18Interval;             // Q.764 T18 CGB timer interval
9233     u_int64_t m_t19Interval;             // Q.764 T19 CGB global timer interval
9234     u_int64_t m_t20Interval;             // Q.764 T20 CGU timer interval
9235     u_int64_t m_t21Interval;             // Q.764 T21 CGU global timer interval
9236     u_int64_t m_t27Interval;             // Q.764 T27 Reset after Cont. Check failure
9237     u_int64_t m_t34Interval;             // Q.764 T34 Segmentation receive timout
9238     SignallingMessageTimerList m_pending;// Pending messages (RSC ...)
9239     // Remote User Part test
9240     SignallingTimer m_uptTimer;          // Timer for UPT
9241     bool m_userPartAvail;                // Flag indicating the remote User Part availability
9242     SS7MsgISUP::Type m_uptMessage;       // Message used, may not be always UPT
9243     unsigned int m_uptCicCode;           // The circuit code sent with UPT
9244     int m_cicWarnLevel;                  // Wrong CIC warn level
9245     int m_replaceCounter;                // Circuit replace counter
9246     // Circuit reset
9247     SignallingTimer m_rscTimer;          // RSC message or idle timeout
9248     SignallingCircuit* m_rscCic;         // Circuit currently beeing reset
9249     u_int32_t m_rscInterval;             // Saved reset interval
9250     u_int32_t m_rscSpeedup;              // Circuits left for speedup
9251     // Blocking/unblocking circuits
9252     SignallingTimer m_lockTimer;         // Timer used to re-check local lock
9253     bool m_lockGroup;                    // Allow sending requests for a group
9254     // Debug flags
9255     bool m_printMsg;                     // Print messages to output
9256     bool m_extendedDebug;                // Extended debug flag
9257 };
9258 
9259 /**
9260  * Implementation of SS7 Bearer Independent Call Control User Part
9261  * @short SS7 BICC implementation
9262  */
9263 class YSIG_API SS7BICC : public SS7ISUP
9264 {
9265     YCLASS(SS7BICC,SS7ISUP)
9266 public:
9267     /**
9268      * Constructor
9269      * @param params Call controller's parameters
9270      * @param sio The default Service Information Octet
9271      */
9272     SS7BICC(const NamedList& params, unsigned char sio = SS7MSU::BICC|SS7MSU::National);
9273 
9274     /**
9275      * Destructor
9276      * Terminate all calls
9277      */
9278     virtual ~SS7BICC();
9279 
9280 protected:
9281     /**
9282      * Process a MSU received from a Layer 3 component
9283      * @param msu Message data, starting with Service Indicator Octet
9284      * @param label Routing label of the received MSU
9285      * @param network Network layer that delivered the MSU
9286      * @param sls Signalling Link the MSU was received from
9287      * @return Result of MSU processing
9288      */
9289     virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
9290 };
9291 
9292 /**
9293  * Implementation of SS7 Telephone User Part
9294  * @short SS7 TUP implementation
9295  */
9296 class YSIG_API SS7TUP : public SignallingCallControl, public SS7Layer4
9297 {
9298 public:
9299     /**
9300      * Constructor
9301      * @param params Call controller's parameters
9302      * @param sif The default Service Information Field
9303      */
9304     SS7TUP(const NamedList& params, unsigned char sif = SS7MSU::TUP);
9305 
9306     /**
9307      * Destructor
9308      * Terminate all calls
9309      */
9310     virtual ~SS7TUP();
9311 };
9312 
9313 /**
9314  * An interface to a SS7 SCCP Management
9315  * @short Abstract SS7 SCCP Management
9316  */
9317 
9318 class YSIG_API SCCPManagement : public SignallingComponent , public Mutex
9319 {
9320     friend class SS7SCCP;
9321     friend class SccpLocalSubsystem; // Local Broadcast
9322     YCLASS(SCCPManagement,SignallingComponent)
9323 public:
9324     enum MsgType {
9325 	SSA = 0x01,  // Subsystem-allowed
9326 	SSP = 0x02,  // Subsystem-prohibited
9327 	SST = 0x03,  // Subsystem-status-test
9328 	SOR = 0x04,  // Subsystem-out-of-service-request
9329 	SOG = 0x05,  // Subsystem-out-of-service-grant
9330 	SSC = 0x06,  // SCCP/Subsystem-congested      (ITU  only)
9331 	SBR = 0xfd,  // Subsystem-backup-routing      (ANSI only)
9332 	SNR = 0xfe,  // Subsystem-normal-routing      (ANSI only)
9333 	SRT = 0xff   // Subsystem-routing-status-test (ANSI only)
9334     };
9335 
9336     enum LocalBroadcast {
9337 	UserOutOfService,
9338 	UserInService,
9339 	PCInaccessible,         // Signalling Point Inaccessible
9340 	PCAccessible,           // Signalling Point Accessible
9341 	SccpRemoteInaccessible,
9342 	SccpRemoteAccessible,
9343 	PCCongested,           // Signalling Point Congested
9344 	SubsystemStatus        // Request send by sccp management to find if a ssn is available
9345     };
9346 
9347     enum SccpStates {
9348 	Allowed = SS7Route::Allowed,
9349 	Prohibited = SS7Route::Prohibited,
9350 	Unknown = SS7Route::Unknown,
9351 	WaitForGrant,
9352 	IgnoreTests
9353     };
9354 
9355     /**
9356      * Constructor
9357      */
9358     SCCPManagement(const NamedList& params, SS7PointCode::Type type);
9359 
9360     /**
9361      * Destructor
9362      */
9363     virtual ~SCCPManagement();
9364 
9365     /**
9366      * Initialize this sccp management
9367      */
9368     virtual bool initialize(const NamedList* config);
9369 
9370     /**
9371      * Process a management message received from sccp
9372      * @param message The message to process
9373      * @return True if the message was processed successfully
9374      */
9375     virtual bool processMessage(SS7MsgSCCP* message);
9376 
9377     /**
9378      * Attach a ss7 sccp to this management
9379      * @param sccp The ss7 sccp to attach
9380      */
9381     void attach(SS7SCCP* sccp);
9382 
9383     /**
9384      * Process a notification from MTP about a pointcode status
9385      * @param link The affected link
9386      * @param operational True if the layer3 is operational
9387      */
9388     virtual void pointcodeStatus(SS7Layer3* link, bool operational);
9389 
9390     /**
9391      * Process a notification from router about a route state change
9392      * @param type The Point Code type
9393      * @param node The remote pointcode
9394      * @param state The route state
9395      */
9396     virtual void routeStatus(SS7PointCode::Type type, const SS7PointCode& node, SS7Route::State state);
9397 
9398     /**
9399      * Notification from sccp about local subsystems status
9400      * @param type The type of notification
9401      * @param params The notification parameters
9402      */
9403     virtual void notify(SCCP::Type type, NamedList& params);
9404 
9405     /**
9406      * Method called by SCCP to inform management that no route was found for the message
9407      * @param msg The SCCP message that failed to be routed
9408      */
9409     virtual void routeFailure(SS7MsgSCCP* msg);
9410 
9411     /**
9412      * Method called by sccp when a sccp message hasn't been processed by any user
9413      * @param msg The message
9414      * @param label The mtp routing label
9415      */
9416     virtual void subsystemFailure(SS7MsgSCCP* msg, const SS7Label& label);
9417 
9418     /**
9419      * Notification from layer3 about a remote sccp unavailability
9420      * @param pointcode The poincode of the unavailable sccp
9421      * @param cause Unavailability cause
9422      */
9423     virtual void sccpUnavailable(const SS7PointCode& pointcode, unsigned char cause);
9424 
9425     /**
9426      * Helper method used to obtain a string statistic about the messages received for unknown subsystems
9427      * @param dest The string where the statistics will be stored
9428      * @param extended True to print an extended statistic ( the number of messages received for unknown subsystem)
9429      */
9430     void subsystemsStatus(String& dest,bool extended = true);
9431 
9432     /**
9433      * Helper method used to obtain information about the messages that failed to be routed
9434      * @param dest The destination string
9435      * @param extended True to print the GTT failures
9436      */
9437     void routeStatus(String& dest,bool extended = false);
9438 
9439     /**
9440      * Helper method used to notify the concerned signalling points about a subsystem status
9441      * @param msg The message type to broadcast
9442      * @param ssn Local affected ssn
9443      * @param smi Local subsystem multiplicity indicator
9444      */
9445     virtual void notifyConcerned(MsgType msg, unsigned char ssn, int smi);
9446 
9447     /**
9448      * Obtain broadcast type dict table
9449      * @return Pointer to broadcast type dict table
9450      */
9451     static const TokenDict* broadcastType();
9452 
9453     /**
9454      * Helper method used to inform Global Title Translator to update translation tables
9455      * @param rsccp The remote SCCP witch status has been changed
9456      * @param ssn The remote SCCP subsystem witch status has been changed
9457      */
9458     virtual void updateTables(SccpRemote* rsccp, SccpSubsystem* ssn = 0);
9459 
9460     /**
9461      * Print a sccp management message
9462      * @param dest The destination string
9463      * @param type The sccp management message type
9464      * @param params List of sccp management message parameters
9465      */
9466     virtual void printMessage(String& dest, MsgType type, const NamedList& params);
9467 
9468     /**
9469      * Obtain a sccp management state name
9470      * @param state The sccp management enum state
9471      * @return The state name if found or 0
9472      */
stateName(SCCPManagement::SccpStates state)9473     static const char* stateName(SCCPManagement::SccpStates state)
9474 	{ return lookup(state,s_states); }
9475 protected:
9476 
9477     /**
9478      * Method called periodically by engine to check for timeouts
9479      * @param when Time to use as computing base for events and timeouts
9480      * Reimplemented from SignallingComponent
9481      */
9482     virtual void timerTick(const Time& when);
9483 
sccp()9484     inline SS7SCCP* sccp()
9485 	{ return m_sccp; }
9486 
9487     ObjList m_remoteSccp;
9488     ObjList m_statusTest;
9489     ObjList m_localSubsystems;
9490     ObjList m_concerned;
9491     SS7PointCode::Type m_pcType;
9492 
9493     /**
9494      * Obtain the subsystem status test time interval
9495      * @return Subsystem status test duration
9496      */
getTestTimeout()9497     inline u_int32_t getTestTimeout()
9498 	{ return m_testTimeout; }
9499 
9500     /**
9501      * Broadcast a management message to local attached sccp users
9502      * @param type The broadcast type
9503      * @param params List of parameters
9504      * @return True if at least one user has processed the message
9505      */
9506     bool managementMessage(SCCP::Type type, NamedList& params);
9507 
9508     /**
9509      * Obtain a local subsystem
9510      * @param ssn The local subsystem ssn
9511      * @return Pointer to local subsystem if found, 0 otherwise
9512      */
9513     SccpLocalSubsystem* getLocalSubsystem(unsigned char ssn);
9514 
9515     /**
9516      * Obtain a remote SCCP
9517      * @param pointcode The remote sccp pointcode
9518      * @return The remote SCCP with the matching pointcode or 0 if not found
9519      */
9520     SccpRemote* getRemoteSccp(int pointcode);
9521 
9522     /**
9523      * Encode a sccp management message and send it to remote address
9524      * @param msgType The SCCP management message type
9525      * @param params List of message parameters
9526      * @return True if the message was successfully send
9527      */
9528     virtual bool sendMessage(SCCPManagement::MsgType msgType, const NamedList& params) = 0;
9529 
9530     /**
9531      * Stop subsystem status tests for a remote location
9532      * @param remoteSccp The remote sccp
9533      * @param rSubsystem The remote subsystem. Can be 0 to stop all tests for the remote sccp
9534      * @param less Stop all sst except this
9535      */
9536     virtual void stopSst(SccpRemote* remoteSccp, SccpSubsystem* rSubsystem = 0, SccpSubsystem* less = 0);
9537 
9538     /**
9539      * Stop all subsystem status tests
9540      */
stopSSTs()9541     inline void stopSSTs()
9542 	{ Lock lock(this); m_statusTest.clear(); }
9543 
9544     /**
9545      * Start a new subsystem status test
9546      * @param remoteSccp The remote sccp
9547      * @param rSubsystem The remote subsystem
9548      */
9549     virtual void startSst(SccpRemote* remoteSccp, SccpSubsystem* rSubsystem);
9550 
9551     /**
9552      * Notification from sccp that mtp has finished restarting
9553      */
9554     void mtpEndRestart();
9555 
9556     /**
9557      * Send a local sccp broadcast
9558      * @param type The broadcast message type
9559      * @param pointcode The affected pointcode. -1 if it should not be included
9560      * @param sps The signalling point status.  -1 if it should not be included
9561      * @param rss The remote sccp status. -1 if it should not be included
9562      * @param rl The restriction level. -1 if it should not be included
9563      * @param ssn The affected ssn. -1 if it should not be included
9564      * @param ss The subsystem status. -1 if it should not be included
9565      */
9566     void localBroadcast(SCCP::Type type, int pointcode, int sps, int rss = -1,
9567 	    int rl = -1, int ssn = -1, int ss = -1);
9568 
9569     /**
9570      * Helper method. Send subsystem status test
9571      * Note: Management mutex must not be locked. Thread safe
9572      * @param remote The remote sccp
9573      * @param sub The remote subsystem
9574      */
9575     bool sendSST(SccpRemote* remote, SccpSubsystem* sub);
9576 
9577     /**
9578      * Process a sccp management message
9579      * @param msgType The sccp management message type
9580      * @param ssn The affected subsystem
9581      * @param smi The subsystem multiplicity indicator
9582      * @param params The message params
9583      * @return True if the message was handled
9584      */
9585     bool handleMessage(int msgType, unsigned char ssn, unsigned char smi, NamedList& params);
9586 
9587     /**
9588      * Process remote sccp state
9589      * @param rsccp The remote sccp witch state has changed
9590      * @param newState The new state of the remote sccp
9591      */
manageSccpRemoteStatus(SccpRemote * rsccp,SS7Route::State newState)9592     virtual void manageSccpRemoteStatus(SccpRemote* rsccp, SS7Route::State newState)
9593 	{ }
9594 
9595     /**
9596      * Helper method used to check if we should print sccp management messages
9597      * @return True if we should print messages
9598      */
printMessagess()9599     inline bool printMessagess()
9600 	{ return m_printMessages; }
9601 
9602     /**
9603      * Helper method that handles coordinate request
9604      * @param ssn Local subsystem that wish to go out of service
9605      * @param smi Subsystem multiplicity indicator
9606      * @param params List of parameters
9607      */
9608     void handleCoordinateChanged(unsigned char ssn, int smi, const NamedList& params);
9609 
9610     /**
9611      * Handle a subsystem out of service grant message
9612      * @param ssn Remote subsystem ssn
9613      * @param pointcode Remote subsystem pointcode
9614      * Note! Lock management mutex before calling this method
9615      */
9616     void handleSog(unsigned char ssn, int pointcode);
9617 
9618     /**
9619      * Process the status of subsystems
9620      * @param subsystem The subsystem who's status has changed
9621      * @param allowed True if the subsystem status is Allowed false for Prohibited
9622      * @param remote The remote sccp pointcode where the subsystem is located
9623      * @param smi Subsystem Multiplicity Indicator
9624      */
handleSubsystemStatus(SccpSubsystem * subsystem,bool allowed,SccpRemote * remote,int smi)9625     virtual void handleSubsystemStatus(SccpSubsystem* subsystem, bool allowed, SccpRemote* remote, int smi)
9626 	{ }
9627 
9628     /**
9629      * Ontain the coordinate changed time interval
9630      * @return The coordinate time interval in ms
9631      */
getCoordTimeout()9632     inline u_int32_t getCoordTimeout()
9633 	{ return m_coordTimeout; }
9634 
9635     /**
9636      * Obtain ignore status tests time interval
9637      * @return ignore status tests time interval in ms
9638      */
getIgnoreTestsInterval()9639     inline u_int32_t getIgnoreTestsInterval()
9640 	{ return m_ignoreStatusTestsInterval; }
9641 private:
9642     // Helper method to fill broadcast param list
9643     void putValue(NamedList& params,int val,const char* name, bool dict = false);
9644 
9645     SS7SCCP* m_sccp;
9646     NamedList m_unknownSubsystems;
9647     unsigned int m_subsystemFailure;    // Counter used in status to inform about the total number of packets received for a unknown ssn
9648     unsigned int m_routeFailure;
9649     u_int32_t m_testTimeout;
9650     u_int32_t m_coordTimeout;
9651     u_int32_t m_ignoreStatusTestsInterval;
9652     bool m_autoAppend;
9653     bool m_printMessages;
9654     static const TokenDict s_broadcastType[];
9655     static const TokenDict s_states[];
9656 };
9657 
9658 class YSIG_API SS7MsgSCCP : public SignallingMessage
9659 {
9660     YCLASS(SS7MsgSCCP,SignallingMessage)
9661 public:
9662     /**
9663      * SCCP Message type
9664      */
9665     enum Type {
9666 	Unknown = 0,
9667 	CR     = 0x01, // Connection request
9668 	CC     = 0x02, // Connection confirm
9669 	CREF   = 0x03, // Connection refused
9670 	RLSD   = 0x04, // Released
9671 	RLC    = 0x05, // Release complete
9672 	DT1    = 0x06, // Data form 1
9673 	DT2    = 0x07, // Data form 2
9674 	AK     = 0x08, // Data acknowledgement
9675 	UDT    = 0x09, // Unitdata
9676 	UDTS   = 0x0a, // Unitdata service
9677 	ED     = 0x0b, // Expedited data
9678 	EA     = 0x0c, // Expedited data acknowledgement
9679 	RSR    = 0x0d, // Reset request
9680 	RSC    = 0x0e, // Reset confirmation
9681 	ERR    = 0x0f, // Protocol data unit error
9682 	IT     = 0x10, // Inactivity test
9683 	XUDT   = 0x11, // Extended unitdata
9684 	XUDTS  = 0x12, // Extended unitdata service
9685 	LUDT   = 0x13, // Long unitdata
9686 	LUDTS  = 0x14, // Long unitdata service
9687     };
9688 
9689     enum Parameters {
9690 	EndOfParameters                = 0,
9691 	DestinationLocalReference      = 0x01,
9692 	SourceLocalReference           = 0x02,
9693 	CalledPartyAddress             = 0x03,
9694 	CallingPartyAddress            = 0x04,
9695 	ProtocolClass                  = 0x05,
9696 	Segmenting                     = 0x06,
9697 	ReceiveSequenceNumber          = 0x07,
9698 	Sequencing                     = 0x08,
9699 	Credit                         = 0x09,
9700 	ReleaseCause                   = 0x0a,
9701 	ReturnCause                    = 0x0b,
9702 	ResetCause                     = 0x0c,
9703 	ErrorCause                     = 0x0d,
9704 	RefusalCause                   = 0x0e,
9705 	Data                           = 0x0f,
9706 	Segmentation                   = 0x10,
9707 	HopCounter                     = 0x11,
9708 	Importance                     = 0x12, // ITU only
9709 	LongData                       = 0x13,
9710 	MessageTypeInterworking        = 0xf8, // ANSI only
9711 	INS                            = 0xf9, // ANSI only
9712 	ISNI                           = 0xfa, // ANSI only
9713     };
9714 
9715     /**
9716      * Constructor
9717      * @param type Type of SCCP message as enumeration
9718      */
SS7MsgSCCP(Type type)9719     inline SS7MsgSCCP(Type type)
9720 	: SignallingMessage(lookup(type,"Unknown")), m_type(type), m_data(0)
9721 	{ }
9722 
9723     /**
9724      * Destructor
9725      * NOTE: The SCCP message does not own the data pointer
9726      * In destructor the data pointer should be valid if data was set from decode message
9727      * In any other cases the pointer should be 0
9728      * NOTE: The data is not destroyed!! Only removed from data object and after the data object is destroyed
9729      */
9730     virtual ~SS7MsgSCCP();
9731 
9732     /**
9733      * Get the type of this message
9734      * @return The type of this message as enumeration
9735      */
type()9736     inline Type type() const
9737 	{ return m_type; }
9738 
9739     /**
9740      * Helper method to change the message type
9741      * @param type The new message type
9742      */
updateType(Type type)9743     inline void updateType(Type type)
9744 	{ m_type = type; params().assign(lookup(type,"Unknown")); }
9745 
9746     /**
9747      * Utility method to verify if this message is a long unit data
9748      * @return True if this message is a long unit data
9749      */
isLongDataMessage()9750     inline bool isLongDataMessage() const
9751 	{ return m_type == LUDT || m_type == LUDTS; }
9752 
9753     /**
9754      * Utility method to verify if this message can be a UDT message
9755      * A SCCP message can be an UDT message if it not contains HopCounter parameter
9756      * or other optional parameters
9757      * @return True if this message can be a UDT message
9758      */
canBeUDT()9759     inline bool canBeUDT() const
9760 	{ return !(params().getParam(YSTRING("Importance")) ||
9761 		    params().getParam(YSTRING("HopCounter"))); }
9762 
9763     /**
9764      * Fill a string with this message's parameters for debug purposes
9765      * @param dest The destination string
9766      * @param label The routing label
9767      * @param params True to add parameters
9768      * @param raw Optional raw message data to be added to destination
9769      * @param rawLen Raw data length
9770      */
9771     void toString(String& dest, const SS7Label& label, bool params,
9772 	const void* raw = 0, unsigned int rawLen = 0) const;
9773 
9774     /**
9775      * Get the dictionary with the message names
9776      * @return Pointer to the dictionary with the message names
9777      */
9778     static const TokenDict* names();
9779 
9780     /**
9781      * Convert an SCCP message type to a C string
9782      * @param type Type of SCCP message to look up
9783      * @param defvalue Default string to return
9784      * @return Name of the SCCP message type
9785      */
9786     static inline const char* lookup(Type type, const char* defvalue = 0)
9787 	{ return TelEngine::lookup(type,names(),defvalue); }
9788 
9789     /**
9790      * Look up an SCCP message name
9791      * @param name String name of the SCCP message
9792      * @param defvalue Default type to return
9793      * @return Encoded type of the SCCP message
9794      */
9795     static inline Type lookup(const char* name, Type defvalue = Unknown)
9796 	{ return static_cast<Type>(TelEngine::lookup(name,names(),defvalue)); }
9797 
9798     /**
9799      * Set data for this message
9800      * @param data the data
9801      */
setData(DataBlock * data)9802     inline void setData(DataBlock* data)
9803 	{ m_data = data; }
9804 
9805     /**
9806      * Remove the data from this message
9807      */
removeData()9808     inline void removeData()
9809 	{ m_data = 0; }
9810 
9811     /**
9812      * Obtain the data associated with this message
9813      * @return The data
9814      */
getData()9815     inline DataBlock* getData()
9816 	{ return m_data; }
9817 
9818     /**
9819      * Extract the data associated with this message
9820      * @return The data
9821      */
extractData()9822     inline DataBlock* extractData()
9823 	{
9824 	    DataBlock* data = m_data;
9825 	    m_data = 0;
9826 	    return data;
9827 	}
9828 
9829 private:
9830     Type m_type;                         // Message type
9831     DataBlock* m_data;                   // Message data NOTE: The message never owns the data
9832 };
9833 
9834 class YSIG_API SS7MsgSccpReassemble : public SS7MsgSCCP
9835 {
9836     YCLASS(SS7MsgSccpReassemble,SignallingMessage)
9837 public:
9838     enum Return {
9839 	Rejected,
9840 	Accepted,
9841 	Error,
9842 	Finished,
9843     };
9844     /**
9845      * Constructor
9846      * @param msg The first message segment
9847      * @param label The MTP routing label
9848      * @param timeToLive The time internal in milliseconds that we wait to reassemble the message
9849      */
9850     SS7MsgSccpReassemble(SS7MsgSCCP* msg, const SS7Label& label, unsigned int timeToLive);
9851 
9852     /**
9853      * Destructor
9854      */
9855     virtual ~SS7MsgSccpReassemble();
9856 
9857     /**
9858      * Helper method used to check if the given message is part of this reassembling process
9859      * @param msg The message to verify
9860      * @param label The SS7 routing label
9861      * @return True if msg is a part of this reassembling process
9862      */
9863     bool canProcess(const SS7MsgSCCP* msg, const SS7Label& label);
9864 
9865     /**
9866      * Append a sccp message segment to the main message
9867      * @param msg The message segment
9868      * @param label The SS7 routing label
9869      * @return One of the Return enum options
9870      */
9871     Return appendSegment(SS7MsgSCCP* msg, const SS7Label& label);
9872 
9873     /**
9874      * Check if this reassemble process has expired
9875      * @return True if this reassemble process has expired
9876      */
timeout()9877     inline bool timeout()
9878 	{ return m_timeout > 0 ? Time::msecNow() > m_timeout : false; }
9879 
9880     /**
9881      * Helper method to verify if all segments have arrived
9882      * @return True if all segments arrived
9883      */
haveAllSegments()9884     inline bool haveAllSegments()
9885 	{ return m_remainingSegments == 0; }
9886 private:
9887     SS7Label m_label;
9888     NamedList m_callingPartyAddress;
9889     u_int32_t m_segmentationLocalReference;
9890     u_int64_t m_timeout;
9891     unsigned char m_remainingSegments;
9892     unsigned int m_firstSgmDataLen;
9893 };
9894 
9895 class YSIG_API SccpSubsystem : public RefObject
9896 {
9897     YCLASS(SccpSubsystem,RefObject);
9898 public:
9899     /**
9900      * Constructor
9901      * @param ssn The subsystem number alocated to this subsystem
9902      * @param state The subsystem initial state
9903      * @param smi The subsystem multiplicity indicator
9904      */
9905     inline SccpSubsystem(int ssn, SCCPManagement::SccpStates state = SCCPManagement::Allowed, unsigned char smi = 0)
m_ssn(ssn)9906 	: m_ssn(ssn), m_smi(smi), m_state(state)
9907 	{ }
9908 
~SccpSubsystem()9909     virtual ~SccpSubsystem()
9910 	{ }
9911 
9912     /**
9913      * Obtain subsystem number
9914      * @return The subsystem number
9915      */
getSSN()9916     inline unsigned char getSSN()
9917 	{ return m_ssn; }
9918 
9919     /**
9920      * Obtain the state of this subsystem
9921      * @return This subsystem state
9922      */
getState()9923     inline SCCPManagement::SccpStates getState()
9924 	{ return m_state; }
9925 
9926     /**
9927      * Set the state of this subsystem
9928      * @param state The new state
9929      */
setState(SCCPManagement::SccpStates state)9930     inline void setState(SCCPManagement::SccpStates state)
9931 	{ m_state = state; }
9932 
9933     /**
9934      * Obtain the subsystem multiplicity indicator of this sccp subsystem
9935      * @return The subsystem multiplicity indicator
9936      */
getSmi()9937     inline unsigned char getSmi()
9938 	{ return m_smi; }
9939 
9940     /**
9941      * Dump this sccp subsystem status
9942      * @param dest Destination string
9943      */
dump(String & dest)9944     void dump(String& dest)
9945 	{
9946 	    dest << "Subsystem: " << m_ssn << " , smi: " << m_smi;
9947 	    dest << ", state: " << SCCPManagement::stateName(m_state) << " ";
9948 	}
9949 private:
9950     unsigned char m_ssn;
9951     unsigned char m_smi;
9952     SCCPManagement::SccpStates m_state;
9953 };
9954 
9955 class YSIG_API RemoteBackupSubsystem : public GenObject
9956 {
9957     YCLASS(RemoteBackupSubsystem,GenObject);
9958 public:
9959 
9960     /**
9961      * Constructor
9962      * @param ssn Remote subsystem number
9963      * @param pointcode Remote pointcode
9964      * @param wfg True if we are expecting SOG from this remote subsystem
9965      */
9966     RemoteBackupSubsystem(unsigned char ssn, int pointcode, bool wfg = false)
m_ssn(ssn)9967 	: m_ssn(ssn), m_pointcode(pointcode), m_waitForGrant(wfg)
9968 	{ }
9969 
~RemoteBackupSubsystem()9970     virtual ~RemoteBackupSubsystem()
9971 	{ }
9972 
9973     /**
9974      * Helper method used to verify if a remore subsystem match this one
9975      * @param ssn Remote subsystem number
9976      * @param pointcode Remote pointcode
9977      * @return True if pointcode and ssn match
9978      */
equals(unsigned char ssn,int pointcode)9979     inline bool equals(unsigned char ssn, int pointcode)
9980 	{ return m_pointcode == pointcode && m_ssn == ssn; }
9981 
9982     /**
9983      * Helper method to reset wait for grant flag
9984      */
permisionGranted()9985     inline void permisionGranted()
9986 	{ m_waitForGrant = false; }
9987 
9988     /**
9989      * Check if we are steel waiting to receive SOG
9990      * @return True if SOG message has arrived from the remote subsystem
9991      */
waitingForGrant()9992     inline bool waitingForGrant()
9993 	{ return m_waitForGrant; }
9994 
9995 private:
9996     unsigned char m_ssn;
9997     int m_pointcode;
9998     bool m_waitForGrant;
9999 };
10000 
10001 class YSIG_API SccpLocalSubsystem : public RefObject, public Mutex
10002 {
10003     YCLASS(SccpLocalSubsystem,RefObject);
10004 public:
10005     /**
10006      * Constructor
10007      * @param ssn The subsystem number
10008      * @param coordInterval The time interval for coordinate changed timer
10009      * @param istInterval The time interval for ignore status test timer
10010      * @param smi Subsystem multiplicity indicator
10011      */
10012     SccpLocalSubsystem(unsigned char ssn, u_int64_t coordInterval, u_int64_t istInterval, unsigned char smi = 0);
10013 
10014     /**
10015      * Destructor
10016      */
10017     virtual ~SccpLocalSubsystem();
10018 
10019     /**
10020      * Obtain the subsystem number number of this sccp subsystem
10021      * @return The ssn associated with this subsystem
10022      */
getSSN()10023     inline unsigned char getSSN()
10024 	{ return m_ssn; }
10025 
10026     /**
10027      * Set a new state of this SCCP subsystem
10028      * @param newState Thew new state to set
10029      */
setState(SCCPManagement::SccpStates newState)10030     inline void setState(SCCPManagement::SccpStates newState)
10031 	{ m_state = newState; }
10032 
10033     /**
10034      * Obtain the state associated with this sccp subsystem
10035      * @return The state of this SCCP subsystem
10036      */
getState()10037     inline SCCPManagement::SccpStates getState()
10038 	{ return m_state; }
10039 
10040     /**
10041      * Start coordinate change timer
10042      */
startCoord()10043     inline void startCoord()
10044 	{ m_coordTimer.start(); }
10045 
10046     /**
10047      * Check if this subsystem should ignore SST (Subsystem status test)
10048      */
ignoreTests()10049     inline bool ignoreTests()
10050 	{ return m_ignoreTestsTimer.started(); }
10051 
10052     /**
10053      * Inform this subsystem if should ignore subsystem status tests
10054      * @param ignore True to ignore subsystem status tests
10055      */
10056     void setIgnoreTests(bool ignore);
10057 
10058     /**
10059      * Check if coordinate change timer has timed out
10060      * @return True if coordinate change timer has timed out
10061      */
10062     bool timeout();
10063 
10064     /**
10065      * Handle coord timer timeout
10066      * @param mgm Pointer to sccp management who owns this sccp local subsystem
10067      */
10068     void manageTimeout(SCCPManagement* mgm);
10069 
10070     /**
10071      * Stop coordinate change timer
10072      */
stopCoordTimer()10073     inline void stopCoordTimer()
10074 	{ m_coordTimer.stop(); }
10075 
10076     /**
10077      * Obtain the subsystem multiplicity indicator of this subsystem
10078      * @return The Subsystem multiplicity indicator
10079      */
getSmi()10080     inline unsigned char getSmi()
10081 	{ return m_smi; }
10082 
10083     /**
10084      * Dump this sccp subsystem status
10085      * @param dest Destination string
10086      */
10087     void dump(String& dest);
10088 
10089     /**
10090      * Process a subsystem out of service grant message
10091      * @param ssn The remote ssn
10092      * @param pointcode The remote pointcode
10093      * @return True if the message was procesed
10094      */
10095     bool receivedSOG(unsigned char ssn, int pointcode);
10096 
10097     /**
10098      * Helper method used to reset timers
10099      */
resetTimers()10100     inline void resetTimers()
10101 	{ m_coordTimer.stop(); m_ignoreTestsTimer.stop(); }
10102     /**
10103      * Clear remote backup subsystems
10104      */
clearBackups()10105     inline void clearBackups()
10106 	{
10107 	    Lock lock(this);
10108 	    m_backups.clear();
10109 	}
10110 
10111     /**
10112      * Append new backup subsystem
10113      * @param backup The backup subsystem to append
10114      */
appendBackup(RemoteBackupSubsystem * backup)10115     inline void appendBackup(RemoteBackupSubsystem* backup)
10116 	{
10117 	    Lock lock(this);
10118 	    m_backups.append(backup);
10119 	}
10120 private:
10121     unsigned char m_ssn;
10122     unsigned char m_smi;
10123     SCCPManagement::SccpStates m_state;
10124     SignallingTimer m_coordTimer;
10125     SignallingTimer m_ignoreTestsTimer;
10126     ObjList m_backups;
10127     bool m_receivedAll;
10128 };
10129 
10130 /**
10131  * Helper class to keep a remote sccp
10132  */
10133 class YSIG_API SccpRemote : public RefObject, public Mutex
10134 {
10135     YCLASS(SccpRemote,RefObject);
10136 public:
10137     /**
10138      * Constructor
10139      * @param pcType The pointcode type
10140      */
10141     SccpRemote(SS7PointCode::Type pcType);
10142 
10143     /**
10144      * Constructor.
10145      * Construncot an Remote sccp from given pointcode and pointcode type
10146      * @param pointcode Integer value assigned to remote pointcode.
10147      * @param pcType Remote pointcode type
10148      */
10149     SccpRemote(unsigned int pointcode, SS7PointCode::Type pcType);
10150 
10151     /**
10152      * Destructor
10153      */
10154     virtual ~SccpRemote();
10155 
10156     /**
10157      * Initialize the pointcode and subsystems list from a string
10158      * @param params String containing the pointcode and the subsystems list
10159      * @return False if the pointcode from the string is not valid
10160      * Usage
10161      */
10162     bool initialize(const String& params);
10163 
10164     /**
10165      * Obtain the state of this remote SCCP
10166      * @return Remote SCCP state
10167      */
getState()10168     inline SCCPManagement::SccpStates getState()
10169 	{ return m_state; }
10170 
10171     /**
10172      * Find a subsystem stored in remote subsystems list
10173      * @param ssn The subsystem number of the remote subsystem
10174      * @return Pointer to the Subsystem or 0 if it was not found
10175      */
10176     SccpSubsystem* getSubsystem(int ssn);
10177 
10178     /**
10179      * Set remote SCCP state
10180      * @param state The new state of the remote SCCP
10181      */
10182     void setState(SCCPManagement::SccpStates state);
10183 
10184     /**
10185      * Obtain the PointCode of the remote SCCP
10186      * @return The pointcode of the remote SCCP
10187      */
getPointCode()10188     inline const SS7PointCode& getPointCode()
10189 	{ return m_pointcode; }
10190 
10191     /**
10192      * Obtain the pointcode as an integer
10193      * @return The packed pointcode representation
10194      */
getPackedPointcode()10195     inline int getPackedPointcode()
10196 	{ return m_pointcode.pack(m_pointcodeType); }
10197 
10198     /**
10199      * Obtain a string representation of the remote pointcode type
10200      * @return String representation of remote pointcode type
10201      */
getPointCodeType()10202     inline const char* getPointCodeType()
10203 	{ return SS7PointCode::lookup(m_pointcodeType); }
10204 
10205     /**
10206      * Dump this sccp status an all it's subsystems
10207      * @param dest Destination string
10208      * @param extended True to append the subsystems status
10209      */
10210     void dump(String& dest, bool extended = false);
10211 
10212     /**
10213      * Helper method to change a subsystem state
10214      * @param ssn The subsystem ssn
10215      * @param newState The subsystem new state
10216      * @return False if the subsystem state is the same
10217      */
10218     bool changeSubsystemState(int ssn,SCCPManagement::SccpStates newState);
10219 
10220     /**
10221      * Helper method to obtain remote sccp's subsystems list
10222      * @return The subsystems list
10223      */
getSubsystems()10224     inline ObjList& getSubsystems()
10225 	{ return m_subsystems; }
10226 
10227     /**
10228      * Helper method to set congestion level
10229      * @param cl The new congestion level
10230      */
setCongestion(unsigned int cl)10231     inline void setCongestion(unsigned int cl)
10232 	{ m_congestionLevel = cl; }
10233 
10234     /**
10235      * Helper method to reset congestion level
10236      */
resetCongestion()10237     inline void resetCongestion()
10238 	{ m_congestionLevel = 0; }
10239 
10240     /**
10241      * Helper method to obtain the congestion level
10242      * @return The congestion level
10243      */
getCongestion()10244     inline unsigned int getCongestion()
10245 	{ return m_congestionLevel; }
10246 private:
10247     SS7PointCode m_pointcode;
10248     SS7PointCode::Type m_pointcodeType;
10249     ObjList m_subsystems;
10250     SCCPManagement::SccpStates m_state;
10251     unsigned int m_congestionLevel;
10252 };
10253 
10254 class YSIG_API SS7AnsiSccpManagement : public SCCPManagement
10255 {
YCLASS(SS7AnsiSccpManagement,SCCPManagement)10256     YCLASS(SS7AnsiSccpManagement,SCCPManagement)
10257 public:
10258 
10259     /**
10260      * Constructor
10261      */
10262     inline SS7AnsiSccpManagement(const NamedList& params)
10263 	: SCCPManagement(params,SS7PointCode::ANSI)
10264 	{ }
10265 
10266     virtual ~SS7AnsiSccpManagement();
10267 
10268     /**
10269      * Process a management message received from sccp
10270      * @param message The message to process
10271      * @return True if the message was processed successfully
10272      */
10273     virtual bool processMessage(SS7MsgSCCP* message);
10274 
10275     /**
10276      * Encode a sccp management message and send it to remote address
10277      * @param msgType The SCCP management message type
10278      * @param params List of message parameters
10279      * @return True if the message was successfully send
10280      */
10281     virtual bool sendMessage(SCCPManagement::MsgType msgType, const NamedList& params);
10282 
10283     /**
10284      * Handle notifications received from remote concerned sccp's
10285      * @param rsccp Remote SCCP pointcode
10286      * @param newState The new state of the remote SCCP
10287      */
10288     virtual void manageSccpRemoteStatus(SccpRemote* rsccp, SS7Route::State newState);
10289 
10290     /**
10291      * Process the status of subsystems
10292      * @param subsystem The subsystem who's status has changed
10293      * @param allowed True if the subsystem status is Allowed false for Prohibited
10294      * @param remote The remote sccp pointcode where the subsystem is located
10295      * @param smi Subsystem Multiplicity Indicator
10296      */
10297     virtual void handleSubsystemStatus(SccpSubsystem* subsystem, bool allowed, SccpRemote* remote, int smi);
10298 
10299     /**
10300      * Handle a SCCP Management message
10301      * @param msgType The message type
10302      * @param params List of message parameters
10303      * @return True if the message was handled
10304      */
10305     bool handleMessage(int msgType, NamedList& params);
10306 };
10307 
10308 class YSIG_API SS7ItuSccpManagement : public SCCPManagement
10309 {
10310     YCLASS(SS7ItuSccpManagement,SCCPManagement)
10311 public:
10312 
10313     /**
10314      * Constructor
10315      */
10316     SS7ItuSccpManagement(const NamedList& params);
10317 
10318     /**
10319      * Destructor
10320      */
~SS7ItuSccpManagement()10321     virtual ~SS7ItuSccpManagement()
10322 	{ }
10323 
10324     /**
10325      * Process a management message received from sccp
10326      * @param message The message to process
10327      * @return True if the message was processed successfully
10328      */
10329     virtual bool processMessage(SS7MsgSCCP* message);
10330 
10331     /**
10332      * Encode and send a SCCP ITU management message
10333      * @param msgType The type of sccp management message
10334      * @param params List of parameters
10335      * @return True if the message was successfully sent
10336      */
10337     virtual bool sendMessage(MsgType msgType, const NamedList& params);
10338 
10339     /**
10340      * Handle notifications received from remote concerned sccp's
10341      * @param rsccp Remote SCCP pointcode
10342      * @param newState The new state of the remote SCCP
10343      */
10344     virtual void manageSccpRemoteStatus(SccpRemote* rsccp, SS7Route::State newState);
10345 
10346     /**
10347      * Handle a SCCP Management message
10348      * @param msgType The message type
10349      * @param params List of message parameters
10350      * @return True if the message was handled
10351      */
10352     bool handleMessage(int msgType, NamedList& params);
10353 
10354     /**
10355      * Process the status of subsystems
10356      * @param subsystem The subsystem who's status has changed
10357      * @param allowed True if the subsystem status is Allowed false for Prohibited
10358      * @param remote The remote sccp pointcode where the subsystem is located
10359      * @param smi Subsystem Multiplicity Indicator
10360      */
10361     virtual void handleSubsystemStatus(SccpSubsystem* subsystem, bool allowed, SccpRemote* remote, int smi);
10362 
10363 };
10364 
10365 /**
10366  * Helper class to memorize SCCP data segments
10367  */
10368 class SS7SCCPDataSegment : public GenObject
10369 {
YCLASS(SS7SCCPDataSegment,GenObject)10370     YCLASS(SS7SCCPDataSegment,GenObject)
10371 public:
10372     /**
10373      * Constructor
10374      * @param index The index in the original DataBlock where this segment starts
10375      * @param length The length of this segment
10376      */
10377     inline SS7SCCPDataSegment(unsigned int index, unsigned int length)
10378 	: m_length(length), m_index(index)
10379 	{}
10380 
10381     /**
10382      * Destructor
10383      */
~SS7SCCPDataSegment()10384     virtual ~SS7SCCPDataSegment()
10385 	{}
10386 
10387     /**
10388      * Assignees to a DataBlock this segment's data
10389      * @param temp The destination DataBlock segment
10390      * @param orig The original DataBlock where this segment is located
10391      */
fillSegment(DataBlock & temp,const DataBlock & orig)10392     inline void fillSegment(DataBlock& temp, const DataBlock& orig)
10393 	{ temp.assign(orig.data(m_index,m_length),m_length,false); }
10394 
10395 private:
10396     unsigned int m_length;
10397     unsigned int m_index;
10398 };
10399 
10400 /**
10401  * Implementation of SS7 Signalling Connection Control Part
10402  * @short SS7 SCCP implementation
10403  */
10404 class YSIG_API SS7SCCP : public SS7Layer4, public SCCP, public Mutex
10405 {
YCLASS(SS7SCCP,SCCP)10406     YCLASS(SS7SCCP,SCCP)
10407     friend class SCCPManagement;
10408 public:
10409     enum ReturnCauses {
10410 	NoTranslationAddressNature         = 0x00,
10411 	NoTranslationSpecificAddress       = 0x01,
10412 	SubsystemCongestion                = 0x02,
10413 	SubsystemFailure                   = 0x03,
10414 	UnequippedUser                     = 0x04,
10415 	MtpFailure                         = 0x05,
10416 	NetworkCongestion                  = 0x06,
10417 	Unqualified                        = 0x07,
10418 	ErrorInMessageTransport            = 0x08,
10419 	ErrorInLocalProcessing             = 0x09,
10420 	DestinationCanNotPerformReassembly = 0x0a,
10421 	SccpFailure                        = 0x0b,
10422 	HopCounterViolation                = 0x0c,
10423 	SegmentationNotSupported           = 0x0d,
10424 	SegmentationFailure                = 0x0e,
10425 	// ANSI only
10426 	MessageChangeFailure               = 0xf7,
10427 	InvalidINSRoutingRequest           = 0xf8,
10428 	InvalidISNIRoutingRequest          = 0xf9,
10429 	UnauthorizedMessage                = 0xfa,
10430 	MessageIncompatibility             = 0xfb,
10431 	NotSupportedISNIRouting            = 0xfc,
10432 	RedundantISNIConstrainedRouting    = 0xfd,
10433 	ISNIIdentificationFailed           = 0xfe,
10434     };
10435 
10436     enum Control {
10437 	Status                    = 0x01,
10438 	FullStatus                = 0x02,
10439 	EnableExtendedMonitoring  = 0x03,
10440 	DisableExtendedMonitoring = 0x04,
10441 	EnablePrintMsg            = 0x05,
10442 	DisablePrintMsg           = 0x06,
10443     };
10444     /**
10445      * Constructor
10446      */
10447      SS7SCCP(const NamedList& config);
10448 
10449     /**
10450       * Destructor
10451       */
10452      ~SS7SCCP();
10453 
10454     /**
10455      * Configure and initialize the Signalling connection control part
10456      * @param config Optional configuration parameters override
10457      * @return True if SCCP was initialized properly
10458      */
10459     virtual bool initialize(const NamedList* config);
10460 
10461     /**
10462      * Attach a SS7 network or router to this service. Detach itself from the old one
10463      * @param network Pointer to network or router to attach
10464      */
10465     virtual void attach(SS7Layer3* network);
10466 
10467     /**
10468      * Converts an SCCP message to a Message Signal Unit and push it down the protocol stack.
10469      * The given message is consumed
10470      * @param msg The message to send
10471      * @param local True if the message is local initiated
10472      * @return Link the message was successfully queued to, negative for error
10473      */
10474     int transmitMessage(SS7MsgSCCP* msg, bool local = false);
10475 
10476     /**
10477       * Receive management information from attached users.
10478       * @param type The type of management message
10479       * @param params List of parameters (Affected subsystem [M])
10480       * @return True if the notification was processed
10481       */
10482      virtual bool managementStatus(Type type, NamedList& params);
10483 
10484     /**
10485      * Send a message
10486      * Reimplemented from SCCP
10487      * @param data Data to be transported trough SCCP protocol
10488      * @param params SCCP parameters
10489      */
10490     virtual int sendMessage(DataBlock& data, const NamedList& params);
10491 
10492     /**
10493      * Process a MSU received from the Layer 3 component
10494      * @param msu Message data, starting with Service Indicator Octet
10495      * @param label Routing label of the received MSU
10496      * @param network Network layer that delivered the MSU
10497      * @param sls Signalling Link the MSU was received from
10498      * @return Result of MSU processing
10499      */
10500     virtual HandledMSU receivedMSU(const SS7MSU& msu, const SS7Label& label, SS7Layer3* network, int sls);
10501 
10502     /**
10503      * Notification for receiving User Part Unavailable
10504      * @param type Type of Point Code
10505      * @param node Node on which the User Part is unavailable
10506      * @param part User Part (service) reported unavailable
10507      * @param cause Unavailability cause - Q.704 15.17.5
10508      * @param label Routing label of the UPU message
10509      * @param sls Signaling link the UPU was received on
10510      */
10511     virtual void receivedUPU(SS7PointCode::Type type, const SS7PointCode node,
10512 	SS7MSU::Services part, unsigned char cause, const SS7Label& label, int sls);
10513 
10514     virtual bool control(NamedList& params);
10515 
10516     /**
10517      * Message changeover procedure for segmentation purpose
10518      * @param origMsg The original message
10519      * @param label MTP3 routing label
10520      * @param local True if the origMsg is local initiated
10521      * @return Negative value if the message failed to be sent
10522      */
10523     int segmentMessage(SS7MsgSCCP* origMsg, const SS7Label& label, bool local);
10524 
10525     /**
10526      * Helper method to know if we use ITU or ANSI
10527      */
ITU()10528      inline const bool ITU() const
10529 	{ return m_type == SS7PointCode::ITU; }
10530 
10531     /**
10532      * Check if GT digit parser of should ignore unknown digits encoding
10533      * @return True if unknown digits are ignored
10534      */
ignoreUnknownAddrSignals()10535     inline bool ignoreUnknownAddrSignals() const
10536 	{ return m_ignoreUnkDigits; }
10537 
10538     /**
10539      * Process a notification generated by the attached network layer
10540      * @param link Network or linkset that generated the notification
10541      * @param sls Signalling Link that generated the notification, negative if none
10542      */
10543     virtual void notify(SS7Layer3* link, int sls);
10544 
10545     /**
10546      * Process route status changed notifications
10547      * @param type Type of Point Code
10548      * @param node Destination node witch communication status has changed
10549      * @param state The new route state
10550      */
10551     virtual void routeStatusChanged(SS7PointCode::Type type, const SS7PointCode& node, SS7Route::State state);
10552     /**
10553      * Obtain the number of messages send by this SCCP instance
10554      * @return The number of messages send
10555      */
messagesSend()10556     inline unsigned int messagesSend()
10557 	{ return m_totalSent; }
10558 
10559     /**
10560      * Obtain the number of messages received by this SCCP instance
10561      * @return The number of messsages received
10562      */
messagesReceived()10563     inline unsigned int messagesReceived()
10564 	{ return m_totalReceived; }
10565 
10566     /**
10567      * Obtain the number of errors found by this SCCP instance
10568      * @return The number of errors found
10569      */
errors()10570     inline unsigned int errors()
10571 	{ return m_errors; }
10572 
10573     /**
10574      * Obtain the number of GT translations made by this SCCP instance
10575      * @return The number of translations made
10576      */
translations()10577     inline unsigned int translations()
10578 	{ return m_totalGTTranslations; }
10579 
10580     /**
10581      * Obtain the local SCCP point code
10582      * @return Pointer to local point code or 0 if no pointcode was configured
10583      */
getLocalPointCode()10584     inline const SS7PointCode* getLocalPointCode() const
10585 	{ return m_localPointCode; }
10586 
10587     /**
10588      * Obtain local pointcode type
10589      * @return Local pointcode type
10590      */
getLocalPointCodeType()10591      inline SS7PointCode::Type getLocalPointCodeType()
10592 	{ return m_type; }
10593 
10594     /**
10595      * Helper method to obtain the packed pointcode
10596      * @return Packed pointcode or 0 if local pointcode is not set
10597      */
getPackedPointCode()10598     inline int getPackedPointCode()
10599 	{ return m_localPointCode ? m_localPointCode->pack(m_type) : 0; }
10600 
10601     /**
10602      * Helper method to check if attached layer 3 is up
10603      * @return True if attached layer3 is up
10604      */
isLayer3Up()10605     inline bool isLayer3Up()
10606 	{ return m_layer3Up; }
10607 protected:
10608 
10609     /**
10610      * This method is called to clean up and destroy the object after the
10611      *  reference counter becomes zero
10612      */
10613     virtual void  destroyed();
10614 
10615     /**
10616      * Helper method to check if this sccp needs extended monitoring
10617      * @return True if extended monitoring is needed
10618      */
extendedMonitoring()10619     inline bool extendedMonitoring()
10620 	{ return m_extendedMonitoring; }
10621 
10622     /**
10623      * Method called periodically to check for timeouts
10624      * Reimplemented from SignallingComponent
10625      */
10626     virtual void timerTick(const Time& when);
10627 
10628     /**
10629      * Reassemble a message segment
10630      * @param segment The message segment
10631      * @param label The MTP routing label
10632      * @param msg Pointer to fill with the SS7MsgSccpReassemble who processed the message
10633      * @return SS7MsgSccpReassemble::Return enum value
10634      */
10635     SS7MsgSccpReassemble::Return reassembleSegment(SS7MsgSCCP* segment, const SS7Label& label, SS7MsgSCCP*& msg);
10636 
10637     /**
10638      * Check if this sccp is an endpoint
10639      * @return True if this sccp is an endpoint
10640      */
isEndpoint()10641     virtual bool isEndpoint()
10642 	{ return m_endpoint; }
10643 
10644     /**
10645      * Route a SCCP Message to other SCCP component.
10646      * @param msg The sccp message.
10647      * @return -1 if the message failed to be routed
10648      */
10649     int routeLocal(SS7MsgSCCP* msg);
10650 private:
10651     // Helper method to calculate sccp address length
10652     unsigned int getAddressLength(const NamedList& params, const String& prefix);
10653     // Helper method used to ajust HopCounter and Importance parameters
10654     void ajustMessageParams(NamedList& params, SS7MsgSCCP::Type type);
10655     // Obtain maximum data length for a UDT, XUDT and LUDT message
10656     void getMaxDataLen(const SS7MsgSCCP* msg, const SS7Label& label,
10657 	    unsigned int& udtLength, unsigned int& xudtLength, unsigned int& ludtLength);
10658     // Helper method to obtain data segments
10659     // NOTE The list must be destroyed
10660     ObjList* getDataSegments(unsigned int dataLength, unsigned int maxSegmentSize);
10661     // Helper method to print a SCCP message
10662     void printMessage(const SS7MSU* msu, const SS7MsgSCCP* msg, const SS7Label& label);
10663     // Helper method used to extract the pointcode from Calling/Called party address.
10664     // Also will call GT translate if there is no pointcode in called party address
10665     int getPointCode(SS7MsgSCCP* msg, const String& prefix, const char* pCode, bool translate);
10666     // Transmit a SCCP message
10667     int sendSCCPMessage(SS7MsgSCCP* sccpMsg,int dpc,int opc, bool local);
10668     // Helper method used to verify if the message is a connectionless data message
isSCLCMessage(int msgType)10669     inline bool isSCLCMessage(int msgType)
10670 	{ return msgType == SS7MsgSCCP::UDT || msgType == SS7MsgSCCP::XUDT || msgType == SS7MsgSCCP::LUDT; }
10671     // Helper method used to verify if the message is a connectionless service message
isSCLCSMessage(int msgType)10672     inline bool isSCLCSMessage(int msgType)
10673 	{ return msgType == SS7MsgSCCP::UDTS || msgType == SS7MsgSCCP::XUDTS || msgType == SS7MsgSCCP::LUDTS; }
10674     bool isSCOCMsg(int msgType);
10675 
10676     bool fillLabelAndReason(String& dest, const SS7Label& label,const SS7MsgSCCP* msg);
unknownPointCodeType()10677     inline bool unknownPointCodeType()
10678 	{ return m_type != SS7PointCode::ITU && m_type != SS7PointCode::ANSI && m_type != SS7PointCode::ANSI8; }
10679     // Helper method used to verify if th importance level is in standard range
10680     int checkImportanceLevel(int msgType,int initialImportance);
10681     // Helper method used to verify if the optional parameters present in message are declared in standards
10682     void checkSCLCOptParams(SS7MsgSCCP* msg);
10683     // Helper method used to monitor service messages
10684     void archiveMessage(SS7MsgSCCP* msg);
10685     // Helper method used to dump service messages and error codes status
10686     void dumpArchive(String& msg, bool extended);
10687 
10688     bool processMSU(SS7MsgSCCP::Type type, const unsigned char* paramPtr,
10689 	    unsigned int paramLen, const SS7Label& label, SS7Layer3* network, int sls);
10690 
10691     bool decodeMessage(SS7MsgSCCP* msg, SS7PointCode::Type pcType,
10692 	    const unsigned char* paramPtr, unsigned int paramLen);
10693 
10694     void returnMessage(SS7MsgSCCP* message, int error);
10695 
10696     static void switchAddresses(const NamedList& source, NamedList& dest);
10697     // Helper method to dump sccp status
10698     void printStatus(bool extended);
10699     void setNetworkUp(bool operational);
10700 
10701     SS7MSU* buildMSU(SS7MsgSCCP* msg, const SS7Label& label, bool checkLength = true) const;
10702     bool routeSCLCMessage(SS7MsgSCCP*& msg, const SS7Label& label);
10703     // Member data
10704     SS7PointCode::Type m_type;           // Point code type of this SCCP
10705     SS7PointCode* m_localPointCode;      // Local point code
10706     SCCPManagement* m_management;        // SCCP management
10707     ObjList m_reassembleList;            // List of sccp messages that are waiting to be reassembled
10708     u_int8_t m_hopCounter;               // Hop counter value
10709     NamedList m_msgReturnStatus;         // List with message return statistics
10710     u_int32_t m_segTimeout;              // Time in milliseconds for segmentation timeout
10711     bool m_ignoreUnkDigits;              // Check if GT digit parser of should ignore unknown digits encoding
10712     bool m_layer3Up;                     // Flag used to verify if the network is operational
10713     unsigned int m_maxUdtLength;         // The maximum length of data packet transported in a UDT message
10714     u_int32_t m_totalSent;               // Counter of the total number of SCCP messages sent
10715     u_int32_t m_totalReceived;           // The number of incoming sccp messages
10716     u_int32_t m_errors;                  // Counter of the number of messages that failed to be delivered
10717     u_int32_t m_totalGTTranslations;     // The number of GT translations made
10718     u_int32_t m_gttFailed;               // Number of global title that failed to be translated
10719     bool m_extendedMonitoring;           // Flag used to check if the monitoring is normal or extended
10720     const char* m_mgmName;               // The name of the sccp management section from ysigchan.conf
10721     // Debug flags
10722     bool m_printMsg;                     // Print messages to output
10723     bool m_extendedDebug;                // Extended debug flag
10724     bool m_endpoint;                     // Flag used to force message processing if the message have a ssn
10725 };
10726 
10727 /**
10728  * RFC3868 SS7 SCCP implementation over SCTP/IP
10729  * SUA is intended to be used as a Provider-User where real SCCP runs on a
10730  *  Signalling Gateway and SCCP users are located on an Application Server.
10731  * @short SIGTRAN SCCP User Adaptation Layer
10732  */
10733 class YSIG_API SS7SUA : public SIGAdaptUser, public SCCP
10734 {
10735 };
10736 
10737 /**
10738  * A TCAP message wrapper, encapsulates the data received from SCCP
10739  * @short TCAP message wrapper
10740  */
10741 class YSIG_API SS7TCAPMessage : public GenObject
10742 {
10743 public:
10744     /**
10745      * Constructor
10746      * @param params NamedList reference containing information from the SCCP level
10747      * @param data DataBlock representing the TCAP payload
10748      * @param notice Flag if this is a notification, true if it is, false if it's a message
10749      */
10750     inline SS7TCAPMessage(NamedList& params, DataBlock& data, bool notice = false)
m_msgParams(params)10751 	: m_msgParams(params), m_msgData(data), m_notice(notice)
10752 	{}
10753 
10754     /**
10755      * Get the SCCP parameters
10756      * @return NamedList reference containing information from the SCCP level
10757      */
msgParams()10758     inline NamedList& msgParams()
10759 	{ return m_msgParams; }
10760 
10761     /**
10762      * Get the TCAP message data
10763      * @return DataBlock representing the encoded TCAP message
10764      */
msgData()10765     inline DataBlock& msgData()
10766 	{ return m_msgData; }
10767 
10768     /**
10769      * Is this message a notice or a normal message?
10770      * @return True if message is a notice, false otherwise
10771      */
isNotice()10772     inline bool& isNotice()
10773 	{ return m_notice; }
10774 
10775 private:
10776     NamedList m_msgParams;
10777     DataBlock m_msgData;
10778     bool m_notice;
10779 };
10780 
10781 /**
10782  * Implementation of SS7 Transactional Capabilities Application Part
10783  * @short SS7 TCAP implementation
10784  */
10785 class YSIG_API SS7TCAP : public SCCPUser
10786 {
10787     YCLASS(SS7TCAP,SCCPUser)
10788 public:
10789     /**
10790      * TCAP implementation variant
10791      */
10792     enum TCAPType {
10793 	UnknownTCAP,
10794 	ITUTCAP,
10795 	ANSITCAP,
10796     };
10797 
10798     /**
10799      * Component handling primitives between TCAP and TCAP user (TC-user)
10800      */
10801     enum TCAPUserCompActions {
10802 	TC_Invoke         = 1,        // ITU-T Invoke primitive, ANSI InvokeLast - Request/Indication
10803 	TC_ResultLast     = 2,        // ITU-T & ANSI ResultLast primitive - Request/Indication
10804 	TC_U_Error        = 3,        // ITU-T & ANSI ReturnError primitive - Request/Indication
10805 	TC_U_Reject       = 4,        // ITU-T & ANSI Reject primitive - Request/Indication, TC-user rejected the component
10806 	TC_R_Reject       = 5,        // ITU-T & ANSI Reject primitive - Indication, Remote TC-user rejected the component
10807 	TC_L_Reject       = 6,        // ITU-T & ANSI Reject primitive - Indication, local Component Sublayer rejected the component
10808 	TC_InvokeNotLast  = 7,        // ANSI InvokeNotLast primitive - Request/Indication
10809 	TC_ResultNotLast  = 8,        // ITU-T & ANSI ResultNotLast primitive - Request/Indication
10810 	TC_L_Cancel       = 9,        // Local Cancel primitive - Indication, inform TC-user that an operation has timed out
10811 	TC_U_Cancel       = 10,       // User Cancel primitive - Request, TC-user request cancellation of an operation
10812 	TC_TimerReset     = 11,       // Timer Reset - Indication, allow TC-user to refresh an operation timer
10813     };
10814 
10815     /**
10816      * TCAP message primitives
10817      */
10818     enum TCAPUserTransActions {
10819 	TC_Unknown         = 0,
10820 	TC_Unidirectional  = 1,          // ITU-T & ANSI - Request/Indication, request Unidirectional message
10821 	TC_Begin,                   // ITU-T - Request/Indication, begin a dialogue
10822 	TC_QueryWithPerm,           // ANSI - Request/Indication, begin a dialogue with permission to end it
10823 	TC_QueryWithoutPerm,        // ANSI - Request/Indication, begin a dialogue without permission to end it
10824 	TC_Continue,                // ITU-T - Request/Indication, continue a dialogue
10825 	TC_ConversationWithPerm,    // ANSI - Request/Indication, continue a dialogue with permission
10826 	TC_ConversationWithoutPerm, // ANSI - Request/Indication, continue a dialogue without permission
10827 	TC_End,                     // ITU-T -Request/Indication, end a dialogue
10828 	TC_Response,                // ANSI - Request/Indication, end a dialogue
10829 	TC_U_Abort,                 // ITU-T & ANSI - Request/Indication, abort a dialogue per user's request
10830 	TC_P_Abort,                 // ITU-T & ANSI - Indication, notify the abort of a dialogue because of a protocol error
10831 	TC_Notice,                  // ITU-T & ANSI - Indication, notify the TC-user that the network was unable to provide the requested service
10832     };
10833 
10834     /**
10835      * Component Operation Classes
10836      */
10837     enum TCAPComponentOperationClass {
10838 	SuccessOrFailureReport    = 1,
10839 	FailureOnlyReport         = 2,
10840 	SuccessOnlyReport         = 3,
10841 	NoReport                  = 4,
10842     };
10843 
10844     /**
10845      * Type of message counters
10846      */
10847     enum TCAPCounter {
10848 	IncomingMsgs,
10849 	OutgoingMsgs,
10850 	DiscardedMsgs,
10851 	NormalMsgs,
10852 	AbnormalMsgs,
10853     };
10854 
10855     /**
10856      * Constructor
10857      * @param params Parameters for building this TCAP
10858      */
10859     SS7TCAP(const NamedList& params);
10860 
10861     /**
10862      * Destructor
10863      */
10864     virtual ~SS7TCAP();
10865 
10866     /**
10867      * Configure and initialize the component and any subcomponents it may have
10868      * @param config Optional configuration parameters override
10869      * @return True if the component was initialized properly
10870      */
10871     virtual bool initialize(const NamedList* config);
10872 
10873     /**
10874      * Send a message to SCCP for transport, inherited from SCCPUser
10875      * @param data User data
10876      * @param params SCCP parameters
10877      */
10878     virtual bool sendData(DataBlock& data, NamedList& params);
10879 
10880     /**
10881      * Notification from SCCP that a message has arrived, inherited from SCCPUser
10882      * @param data Received user data
10883      * @param params SCCP parameters
10884      * @return True if this user has processed the message, false otherwise
10885      */
10886     virtual HandledMSU receivedData(DataBlock& data, NamedList& params);
10887 
10888     /**
10889      * Notification from SCCP that a message failed to arrive to its destination, inherited from SCCPUser
10890      * @param data User data sent.
10891      * @param params SCCP parameters
10892      * Note! The data may not contain the full message block previously sent (in case of SCCP segmentation),
10893      * but it must always must contain the first segment
10894      */
10895     virtual HandledMSU notifyData(DataBlock& data, NamedList& params);
10896 
10897     /**
10898      * Notification from SCCP layer about management status
10899      * @param type Type of management notification
10900      * @param params Notification params
10901      */
10902     bool managementNotify(SCCP::Type type, NamedList& params);
10903 
10904     /**
10905      * Attach a SS7 TCAP user
10906      * @param user Pointer to the TCAP user to attach
10907      */
10908     void attach(TCAPUser* user);
10909 
10910     /**
10911      * Detach a SS7 TCAP user
10912      * @param user TCAP user to detach
10913      */
10914     void detach(TCAPUser* user);
10915 
10916     /**
10917      * A TCAP user made a request
10918      * @param requestParams NamedList containing all the necessary data for the TCAP request
10919      * @return A SS7TCAPError reporting the status of the request
10920      */
10921     virtual SS7TCAPError userRequest(NamedList& requestParams);
10922 
10923     /**
10924      * Process received SCCP data
10925      * @param sccpData A TCAP message received from SCCP to process
10926      * @return A code specifying if this message was handled
10927      */
10928     virtual HandledMSU processSCCPData(SS7TCAPMessage* sccpData);
10929 
10930     /**
10931      * Report which TCAP implementation is in use
10932      */
tcapType()10933     inline TCAPType tcapType()
10934 	{ return m_tcapType; }
10935 
10936     /**
10937      * Set TCAP version
10938      * @param type TCAP version
10939      */
setTCAPType(TCAPType type)10940     inline void setTCAPType(TCAPType type)
10941 	{ m_tcapType = type; }
10942 
10943     /**
10944      * Enqueue data received from SCCP as a TCAP message, kept in a processing queue
10945      * @param msg A SS7TCAPMessage pointer containing all data received from SSCP
10946      */
10947     virtual void enqueue(SS7TCAPMessage* msg);
10948 
10949     /**
10950      * Dequeue a TCAP message when ready to process it
10951      * @return A SS7TCAPMessage pointer dequeued from the queue
10952      */
10953     virtual SS7TCAPMessage* dequeue();
10954 
10955     /**
10956      * Get a new transaction ID
10957      * @return A transaction ID
10958      */
10959     virtual const String allocTransactionID();
10960 
10961     /**
10962      * Get a new transaction ID
10963      * @param str String into which to put the id
10964      */
10965     void allocTransactionID(String& str);
10966 
10967     /**
10968      * Dictionary for TCAP versions
10969      */
10970     static const TokenDict s_tcapVersion[];
10971 
10972     /**
10973      * Dictionary for component primitives
10974      */
10975     static const TokenDict s_compPrimitives[];
10976 
10977     /**
10978      * Dictionary for transaction primitives
10979      */
10980     static const TokenDict s_transPrimitives[];
10981 
10982     /**
10983      * Dictionary for component opearation classes
10984      */
10985     static const TokenDict s_compOperClasses[];
10986 
10987     /**
10988      * Build a transaction
10989      * @param type Type with which to build the transactions
10990      * @param transactID ID for the transaction
10991      * @param params Parameters for building the transaction
10992      * @param initLocal True if built by user, false if by remote end
10993      * @return A transaction
10994      */
10995     virtual SS7TCAPTransaction* buildTransaction(SS7TCAP::TCAPUserTransActions type, const String& transactID, NamedList& params,
10996 	bool initLocal = true) = 0;
10997 
10998     /**
10999      * Find the transaction with the given id
11000      * @param tid Searched local id
11001      * @return A pointer to the transaction or null if not found
11002      */
11003     SS7TCAPTransaction* getTransaction(const String& tid);
11004 
11005     /**
11006      * Remove transaction
11007      * @param tr The transaction to remove
11008      */
11009     void removeTransaction(SS7TCAPTransaction* tr);
11010 
11011     /**
11012      * Method called periodically to do processing and timeout checks
11013      * @param when Time to use as computing base for events and timeouts
11014      */
11015     virtual void timerTick(const Time& when);
11016 
11017     /**
11018      * Send to TCAP users a decode message
11019      * @param params Message in NamedList form
11020      * @return True if the message was handled by a user, false otherwise
11021      */
11022     virtual bool sendToUser(NamedList& params);
11023 
11024     /**
11025      * Build SCCP data
11026      * @param params NamedList containing the parameters to be given to SCCP
11027      * @param tr Transaction for which to build SCCP data
11028      */
11029     virtual void buildSCCPData(NamedList& params, SS7TCAPTransaction* tr);
11030 
11031     /**
11032      * Status of TCAP
11033      * @param status NamedList to fill with status information
11034      */
11035     virtual void status(NamedList& status);
11036 
11037     /**
11038      * Status of TCAP users
11039      * @param status NamedList to fill with user status information
11040      */
11041     virtual void userStatus(NamedList& status);
11042 
11043     /**
11044      * Handle an decoding error
11045      * @param error The encoutered error
11046      * @param params TCAP message parameters which where successfully decoded until the error was encoutered
11047      * @param data Data block containing the rest of the message
11048      * @param tr Transaction to which this message belongs to
11049      * @return Status if the error was handled or not
11050      */
11051     virtual HandledMSU handleError(SS7TCAPError& error, NamedList& params, DataBlock& data, SS7TCAPTransaction* tr = 0);
11052 
11053     /**
11054      * Update the SCCP Management state for this SSN when requested by a user
11055      * @param user The TCAP user which changed its state
11056      * @param status The state of the TCAP user
11057      * @param params Additional parameters to be transmitted to the SCPP
11058      */
11059     virtual void updateUserStatus(TCAPUser* user, SCCPManagement::LocalBroadcast status, NamedList& params);
11060 
11061     /**
11062      * Increment one of the status counters
11063      * @param counterType The type of the counter to increment
11064      */
incCounter(TCAPCounter counterType)11065     inline void incCounter(TCAPCounter counterType)
11066     {
11067 	switch (counterType) {
11068 	    case IncomingMsgs:
11069 		m_recvMsgs++;
11070 		break;
11071 	    case OutgoingMsgs:
11072 		m_sentMsgs++;
11073 		break;
11074 	    case DiscardedMsgs:
11075 		m_discardMsgs++;
11076 		break;
11077 	    case NormalMsgs:
11078 		m_normalMsgs++;
11079 		break;
11080 	    case AbnormalMsgs:
11081 		m_abnormalMsgs++;
11082 		break;
11083 	    default:
11084 		break;
11085 	}
11086     }
11087 
11088     /**
11089      * Retrieve one of the status counters
11090      * @param counterType The type of the counter to increment
11091      * @return The value of the counter
11092      */
count(TCAPCounter counterType)11093     inline unsigned int count(TCAPCounter counterType)
11094     {
11095 	switch (counterType) {
11096 	    case IncomingMsgs:
11097 		return m_recvMsgs;
11098 	    case OutgoingMsgs:
11099 		return m_sentMsgs;
11100 	    case DiscardedMsgs:
11101 		return m_discardMsgs;
11102 	    case NormalMsgs:
11103 		return m_normalMsgs;
11104 	    case AbnormalMsgs:
11105 		return m_abnormalMsgs;
11106 	    default:
11107 		break;
11108 	}
11109 	return 0;
11110     }
11111 
11112     /**
11113      * Get the type of transaction in string form
11114      * @param tr Type of transaction
11115      * @return A string containing the string form of that type of transaction
11116      */
lookupTransaction(int tr)11117     static inline const char* lookupTransaction(int tr)
11118 	{ return lookup(tr,s_transPrimitives,"Unknown"); }
11119 
11120     /**
11121      * Get the type of transaction from string form
11122      * @param tr Type of transaction in string form
11123      * @return The type of transaction
11124      */
lookupTransaction(const char * tr)11125     static inline int lookupTransaction(const char* tr)
11126 	{ return lookup(tr,s_transPrimitives,TC_Unknown); }
11127 
11128     /**
11129      * Get the type of component in string form
11130      * @param comp Type of component
11131      * @return A string containing the string form of that type of component
11132      */
lookupComponent(int comp)11133     static inline const char* lookupComponent(int comp)
11134 	{ return lookup(comp,s_compPrimitives,"Unknown"); }
11135 
11136     /**
11137      * Get the type of component from string form
11138      * @param comp Type of component
11139      * @return The type of component
11140      */
lookupComponent(const char * comp)11141     static inline int lookupComponent(const char* comp)
11142 	{ return lookup(comp,s_compPrimitives,TC_Unknown); }
11143 
11144 protected:
11145     virtual SS7TCAPError decodeTransactionPart(NamedList& params, DataBlock& data) = 0;
11146     virtual void encodeTransactionPart(NamedList& params, DataBlock& data) = 0;
11147     bool sendSCCPNotify(NamedList& params);
11148     // list of TCAP users attached to this TCAP instance
11149     ObjList m_users;
11150     Mutex m_usersMtx;
11151 
11152     // list of messages received from sublayer, waiting to be processed
11153     ObjList m_inQueue;
11154     Mutex m_inQueueMtx;
11155 
11156     unsigned int m_SSN;
11157     unsigned int m_defaultRemoteSSN;
11158     unsigned int m_defaultHopCounter;
11159     SS7PointCode m_defaultRemotePC;
11160     SS7PointCode::Type m_remoteTypePC;
11161     u_int64_t m_trTimeout;
11162 
11163     // list of current TCAP transactions
11164     Mutex m_transactionsMtx;
11165     ObjList m_transactions;
11166     // type of TCAP
11167     TCAPType m_tcapType;
11168 
11169     // counter for allocating transaction IDs
11170     u_int32_t m_idsPool;
11171 
11172     // counters
11173     unsigned int m_recvMsgs;
11174     unsigned int m_sentMsgs;
11175     unsigned int m_discardMsgs;
11176     unsigned int m_normalMsgs;
11177     unsigned int m_abnormalMsgs;
11178 
11179     // Subsystem Status
11180     SCCPManagement::LocalBroadcast m_ssnStatus;
11181 };
11182 
11183 class YSIG_API SS7TCAPError
11184 {
11185 public:
11186     enum ErrorType {
11187 	// P-AbortCause TransactionProblems
11188 	Transact_UnrecognizedPackageType,     // named after the ANSI specification, equivalent to ITU-T UnrecongnizedMessageType P-AbortCause
11189 	Transact_IncorrectTransactionPortion, // <==> ITU-T incorrectTrasactionPortion P-AbortCause
11190 	Transact_BadlyStructuredTransaction,  // <==> ITU-T badlyFormattedTransactionPortion P-AbortCause
11191 	Transact_UnassignedTransactionID,
11192 	Transact_PermissionToReleaseProblem,  // HANDLING NOT DEFINED
11193 	Transact_ResourceUnavailable,         // <==> ITU-T resourceLimitation P-AbortCause
11194 
11195 	// P-AbortCause DialogProblem
11196 	Dialog_UnrecognizedDialoguePortionID, // ANSI only
11197 	Dialog_BadlyStructuredDialoguePortion,// ANSI only
11198 	Dialog_MissingDialoguePortion,        // ANSI only
11199 	Dialog_InconsistentDialoguePortion,   // ANSI only
11200 	Dialog_Abnormal,                      // ITU only, indication only
11201 
11202 	// GeneralProblem
11203 	General_UnrecognizedComponentType,   // named after the ANSI specification, equivalent to ITU-T UnrecognizedComponent General Problem
11204 	General_IncorrectComponentPortion,   // ANSI specification, equivalent to ITU-T MistypedComponent General Problem
11205 	General_BadlyStructuredCompPortion,  // ANSI specification, equivalent to ITU-T BadlyStructuredComponent General Problem
11206 	General_IncorrectComponentCoding,    // ANSI specification, no ITU-T equivalent
11207 
11208 	// InvokeProblem
11209 	Invoke_DuplicateInvokeID,           // ANSI & ITU-T specification
11210 	Invoke_UnrecognizedOperationCode,   // ANSI specification, equivalent to ITU-T UnrecognizedOperation Invoke Problem
11211 	Invoke_IncorrectParameter,          // ANSI specification, equivalent to ITU-T MistypedParameter Invoke Problem
11212 	Invoke_UnrecognizedCorrelationID,   // ANSI specification, equivalent to ITU-T UnrecognizedLinkedID Invoke Problem
11213 	Invoke_ResourceLimitation,          // ITU-T only
11214 	Invoke_InitiatingRelease,           // ITU-T only
11215 	Invoke_LinkedResponseUnexpected,    // ITU-T only
11216 	Invoke_UnexpectedLinkedOperation,   // ITU-T only
11217 
11218 	// ReturnResult
11219 	Result_UnrecognizedInvokeID,        // ITU-T only
11220 	Result_UnrecognisedCorrelationID,   // ANSI only
11221 	Result_UnexpectedReturnResult,      // ANSI specification, equivalent to ITU-T ReturnResultUnexpected Result Problem
11222 	Result_IncorrectParameter,          // ANSI specification, equivalent to ITU-T MistypedParameter Result Problem
11223 
11224 	// ReturnError
11225 	Error_UnrecognizedInvokeID,        // ITU-T only
11226 	Error_UnrecognisedCorrelationID,   // ANSI only
11227 	Error_UnexpectedReturnError,       // ANSI only
11228 	Error_UnrecognisedError,           // ANSI & ITU-T
11229 	Error_UnexpectedError,             // ANSI & ITU-T
11230 	Error_IncorrectParameter,          // ANSI specification, equivalent to ITU-T MistypedParameter Return Error Problem
11231 
11232 	Discard,
11233 	NoError,
11234     };
11235 
11236     /**
11237      * Constructor
11238      * @param tcapType TCAP specification user for this error
11239      */
11240     SS7TCAPError(SS7TCAP::TCAPType tcapType);
11241 
11242     /**
11243      * Constructor
11244      * @param tcapType TCAP specification used for this error
11245      * @param error The error
11246      */
11247     SS7TCAPError(SS7TCAP::TCAPType tcapType, ErrorType error);
11248 
11249     /**
11250      * Destructor
11251      */
11252     ~SS7TCAPError();
11253 
11254     /**
11255      * Get the error
11256      * @return The TCAP error
11257      */
error()11258     inline ErrorType error()
11259 	{ return m_error; }
11260 
11261     /**
11262      * Set the error
11263      * @param error Error to set
11264      */
setError(ErrorType error)11265     inline void setError(ErrorType error)
11266 	{ m_error = error; }
11267 
11268     /**
11269      * Error name
11270      * @return The error name
11271      */
11272     const String errorName();
11273 
11274     /**
11275      * The full value of the error
11276      * @return 2 byte integer containing the full code of the error
11277      */
11278     u_int16_t errorCode();
11279 
11280     /**
11281      * Obtain abstract TCAP error from TCAP protocol defined error value
11282      * @param tcapType Type of TCAP for which the error is searched
11283      * @param code TCAP protocol error value
11284      * @return The type of the error
11285      */
11286     static int errorFromCode(SS7TCAP::TCAPType tcapType, u_int16_t code);
11287 
11288     /**
11289      * Obtain TCAP specific error value from abstract TCAP error
11290      * @param tcapType Type of TCAP for which the error is searched
11291      * @param err Abstrat TCAP error
11292      * @return The error value as defined by the TCAP protocol
11293      */
11294     static u_int16_t codeFromError(SS7TCAP::TCAPType tcapType, int err);
11295 
11296     /**
11297      * Dictionary for error types
11298      */
11299     static const TokenDict s_errorTypes[];
11300 
11301 private:
11302     SS7TCAP::TCAPType m_tcapType;
11303     ErrorType m_error;
11304 };
11305 
11306 /**
11307  * Implementation of SS7 Transactional Capabilities Application Part Transaction
11308  * @short SS7 TCAP transaction implementation
11309  */
11310 class YSIG_API SS7TCAPTransaction : public RefObject, public Mutex
11311 {
11312 public:
11313     enum TransactionState {
11314 	Idle                      = 0,
11315 	PackageSent               = 1,
11316 	PackageReceived           = 2,
11317 	Active                    = 3,
11318     };
11319 
11320     enum TransactionTransmit {
11321 	NoTransmit       = 0,
11322 	PendingTransmit  = 256,
11323 	Transmitted      = 521,
11324     };
11325 
11326     /**
11327      * Constructor
11328      * @param tcap TCAP holding this transaction
11329      * @param type Initiating type for transaction
11330      * @param transactID Transaction ID
11331      * @param params Decoded TCAP parameters for building the transaction
11332      * @param timeout Transaction timeout
11333      * @param initLocal True if the transaction was initiated locally, false if not
11334      */
11335     SS7TCAPTransaction(SS7TCAP* tcap, SS7TCAP::TCAPUserTransActions type, const String& transactID, NamedList& params,
11336 	u_int64_t timeout, bool initLocal = true);
11337 
11338     /**
11339      * Destructor
11340      */
11341     ~SS7TCAPTransaction();
11342 
11343     /**
11344      * Process transaction data and fill the NamedList with the decoded data
11345      * @param params NamedList to fill with decoded data
11346      * @param data Data to decode
11347      * @return A TCAP error encountered whilst decoding
11348      */
11349     virtual SS7TCAPError handleData(NamedList& params, DataBlock& data) = 0;
11350 
11351     /**
11352      * An update request for this transaction
11353      * @param type The type of transaction to which this transaction should be updated
11354      * @param params Update parameter
11355      * @param updateByUser True if the update is made by the local user, false if it's made by the remote end
11356      * @return A TCAP Error
11357      */
11358     virtual SS7TCAPError update(SS7TCAP::TCAPUserTransActions type, NamedList& params, bool updateByUser = true) = 0;
11359 
11360     /**
11361      * Handle TCAP relevant dialog data
11362      * @param params NamedList containing (if present) dialog information
11363      * @param byUser True if the dialog information is provided by the local user, false otherwise
11364      * @return A report error
11365      */
11366     virtual SS7TCAPError handleDialogPortion(NamedList& params,bool byUser = true) = 0;
11367 
11368     /**
11369      * Build a Reject component in answer to an encoutered error during decoding of the component portion
11370      * @param error The encountered error
11371      * @param params Decoded TCAP message parameters
11372      * @param data DataBlock containing the rest of the coded TCAP message
11373      * @return A report error
11374      */
11375     virtual SS7TCAPError buildComponentError(SS7TCAPError& error, NamedList& params, DataBlock& data);
11376 
11377     /**
11378      * Update components
11379      * @param params NamedList reference containing the update information
11380      * @param updateByUser Flag if the update was issued by local user or by remote
11381      * @return A report error
11382      */
11383     virtual SS7TCAPError handleComponents(NamedList& params, bool updateByUser = true);
11384 
11385     /**
11386      * Request encoding for the components of this transaction
11387      * @param params Components parameters to encode
11388      * @param data DataBlock reference in which to insert the encoded components
11389      */
11390     virtual void requestComponents(NamedList& params, DataBlock& data);
11391 
11392     /**
11393      * Fill the NamedList with transaction portion parameters
11394      * @param params NamedList reference to fill with transaction portion parameters
11395      */
11396     virtual void transactionData(NamedList& params);
11397 
11398     /**
11399      * Request content for this transaction
11400      * @param params List of parameters of this tranaction
11401      * @param data Data block to fill with encoded content
11402      */
11403     virtual void requestContent(NamedList& params, DataBlock& data) = 0;
11404 
11405     /**
11406      * Check components for timeouts
11407      */
11408     virtual void checkComponents();
11409 
11410     /**
11411      * Set the current type of transaction primitive
11412      * @param type The transaction primitive to be set
11413      */
setTransactionType(SS7TCAP::TCAPUserTransActions type)11414     inline void setTransactionType(SS7TCAP::TCAPUserTransActions type)
11415 	{ Lock l(this); m_type = type; }
11416 
11417     /**
11418      * Retrieve the current type of primitive that is set for this transaction
11419      * @return The transaction primitive type
11420      */
transactionType()11421     inline SS7TCAP::TCAPUserTransActions transactionType()
11422 	{ return m_type; }
11423 
11424     /**
11425      * Set the state of this transaction, trigger a transmission pending state
11426      * @param state The state to set for the transaction
11427      */
setState(TransactionState state)11428     inline void setState(TransactionState state)
11429     {
11430 	Lock l(this);
11431 	m_state = state;
11432 	// changing state automatically triggers a change in transmission state (except for Idle)
11433 	if (state != Idle)
11434 	    m_transmit = PendingTransmit;
11435     }
11436 
11437     /**
11438      * Retrieve the state of this transaction
11439      * @return The state of this transaction
11440      */
transactionState()11441     inline TransactionState transactionState()
11442 	{ return m_state; }
11443 
11444     /**
11445      * Set the transmission state for this transaction
11446      * @param state The transmission state to be set
11447      */
11448     void setTransmitState(TransactionTransmit state);
11449 
11450     /**
11451      * The transmission state for this transaction
11452      * @return The current transmission state
11453      */
transmitState()11454     inline TransactionTransmit transmitState()
11455 	{ return m_transmit; }
11456 
11457     /**
11458      * The TCAP to which this transaction belongs
11459      * @return A pointer to the TCAP component
11460      */
tcap()11461     inline SS7TCAP* tcap()
11462 	{ return m_tcap; }
11463 
11464     /**
11465      * Get the ID of the transaction so it can be used for list searches
11466      * @return A reference to the ID
11467      */
toString()11468     const String& toString() const
11469 	{ return m_localID; }
11470 
11471     /**
11472      * Set the TCAP username to which this transaction belongs
11473      * @param name The name of the user to set
11474      */
setUserName(const String & name)11475     inline void setUserName(const String& name)
11476 	{ m_userName = name; }
11477 
11478     /**
11479      * Return the name of the TCAP user to which this transaction belongs
11480      * @return The name of the user
11481      */
userName()11482     const String& userName()
11483 	{ return m_userName; }
11484 
11485     /**
11486      * Check if a basic end was set for this transaction
11487      * @return True if basic end was specified by the user, false if prearranged end was specified
11488      */
basicEnd()11489     inline bool basicEnd()
11490 	{ return m_basicEnd; }
11491 
11492     /**
11493      * Add SCCP Addressing information
11494      * @param fillParams NamedList to fill with addressing information
11495      * @param local True if the information is for the user, otherwise
11496      */
11497     void addSCCPAddressing(NamedList& fillParams, bool local);
11498 
11499     /**
11500      * Check if the flag to end this transaction immediately was set
11501      * @return True if the end flag was set, false otherwise
11502      */
endNow()11503     inline bool endNow()
11504 	{ return m_endNow; }
11505 
11506     /**
11507      * Set the flag to end this transaction immediately
11508      * @param endNow Boolean value to set to the end flag
11509      */
endNow(bool endNow)11510     inline void endNow(bool endNow)
11511 	{ m_endNow = endNow; }
11512 
11513     /**
11514      * Check if the transaction has timed out
11515      * @return True if the transaction timed out, false otherwise
11516      */
timedOut()11517     inline bool timedOut()
11518 	{ return m_timeout.timeout(); }
11519 
11520     /**
11521      * Find a component with given id
11522      * @param id Id of component to find
11523      * @return The component with given id or null
11524      */
11525     SS7TCAPComponent* findComponent(const String& id);
11526 
11527     /**
11528      * Update the state of this transaction to end the transaction
11529      */
11530     virtual void updateToEnd();
11531 
11532     /**
11533      * Update transaction state
11534      * @param byUser True if update is requested by user, false if by remote
11535      */
11536     virtual void updateState(bool byUser = true) = 0;
11537 
11538     /**
11539      * Set information in case of abnormal dialog detection
11540      * @param params List of parameters where to set the abnormal dialog information
11541      */
11542     virtual void abnormalDialogInfo(NamedList& params);
11543 
11544     /**
11545      * @param params NamedList reference to fill with the decoded dialog information
11546      * @param data DataBlock reference from which to decode the dialog information
11547      * @return A TCAP error encountered whilst decoding
11548      */
11549     virtual SS7TCAPError decodeDialogPortion(NamedList& params, DataBlock& data) = 0;
11550 
11551     /**
11552      * @param params NamedList reference from which to take the dialog information to encode
11553      * @param data DataBlock reference into which to put the encoded dialog information
11554      */
11555     virtual void encodeDialogPortion(NamedList& params, DataBlock& data) = 0;
11556 
11557     /**
11558      * @param params NamedList reference to fill with the decoded component information
11559      * @param data DataBlock reference from which to decode the component information
11560      * @return A TCAP error encountered whilst decoding
11561      */
11562     virtual SS7TCAPError decodeComponents(NamedList& params, DataBlock& data) = 0;
11563 
11564     /**
11565      * @param params NamedList reference from which to take the component information to encode
11566      * @param data DataBlock reference into which to put the encoded component information
11567      */
11568     virtual void encodeComponents(NamedList& params, DataBlock& data) = 0;
11569 
11570 protected:
11571     SS7TCAP* m_tcap;
11572     SS7TCAP::TCAPType m_tcapType;
11573     String m_userName;
11574     String m_localID;
11575     String m_remoteID;
11576     SS7TCAP::TCAPUserTransActions m_type;
11577     TransactionState m_state;
11578     TransactionTransmit m_transmit;
11579 
11580     ObjList m_components;
11581 
11582     NamedList m_localSCCPAddr;
11583     NamedList m_remoteSCCPAddr;
11584 
11585     bool m_basicEnd; // basic or prearranged end (specified by user when sending a Response)
11586     bool m_endNow; // delete immediately after sending
11587     SignallingTimer m_timeout;
11588 };
11589 
11590 /**
11591  * Implementation of SS7 Transactional Capabilities Application Part Component
11592  * @short SS7 TCAP component implementation
11593  */
11594 class YSIG_API SS7TCAPComponent : public GenObject
11595 {
11596 public:
11597     /**
11598      * Component state
11599      */
11600     enum TCAPComponentState {
11601 	Idle,
11602 	OperationPending,
11603 	OperationSent,
11604 	WaitForReject,
11605     };
11606 
11607     /**
11608      * Constructor
11609      * @param type TCAP type for which to build this component
11610      * @param trans TCAP transaction to which this component belongs to
11611      * @param params Parameters for building component
11612      * @param index Index in the list of parameters
11613      */
11614     SS7TCAPComponent(SS7TCAP::TCAPType type, SS7TCAPTransaction* trans, NamedList& params, unsigned int index);
11615 
11616     /**
11617      * Destructor
11618      */
11619     virtual ~SS7TCAPComponent();
11620 
11621     /**
11622      * Update this component's data
11623      * @param params Update parameters
11624      * @param index Index of parameters in the list for the update of this component
11625      */
11626     virtual void update(NamedList& params, unsigned int index);
11627 
11628     /**
11629      * Put the information of the component in a NamedList
11630      * @param index Index for build parameter names
11631      * @param fillIn NamedList to fill with this component's information
11632      */
11633     virtual void fill(unsigned int index, NamedList& fillIn);
11634 
11635     /**
11636      * Build a TCAP Component from a NamedList
11637      * @param type TCAP type of component
11638      * @param tr The transaction to which this component should belong
11639      * @param params Parameters for building the component
11640      * @param index Index in the list of parameters
11641      * @return A pointer to the built SS7TCAPComponent or nil if not all required parameters are present
11642      */
11643     static SS7TCAPComponent* componentFromNamedList(SS7TCAP::TCAPType type, SS7TCAPTransaction* tr, NamedList& params, unsigned int index);
11644 
11645     /**
11646      * Set the transaction to which this component belongs to
11647      * @param transact TCAP transaction
11648      */
11649     void setTransaction(SS7TCAPTransaction* transact);
11650 
11651     /**
11652      * Returns the transaction to which this component belongs to.
11653      */
11654     SS7TCAPTransaction* transaction();
11655 
11656     /**
11657      * Set the type for this component
11658      * @param type The type of the component
11659      */
setType(SS7TCAP::TCAPUserCompActions type)11660     inline void setType(SS7TCAP::TCAPUserCompActions type)
11661 	{ m_type = type; }
11662 
11663     /**
11664      * Get the type of the component
11665      */
type()11666     inline SS7TCAP::TCAPUserCompActions type()
11667 	{ return m_type; }
11668 
11669     /**
11670      * Set the Invoke ID for this component
11671      * @param invokeID The invoke ID to assign
11672      */
setInvokeID(String invokeID)11673     virtual void setInvokeID(String invokeID)
11674 	{ m_id = invokeID; }
11675 
11676     /**
11677      * String representation of this component's Invoke ID
11678      * @return String representation of Invoke ID
11679      */
toString()11680     virtual const String&  toString () const
11681 	{ return m_id; }
11682 
11683     /**
11684      * String representation of this component's Correlation ID
11685      * @return String representation of Correlation ID
11686      */
correlationID()11687     virtual const String&  correlationID() const
11688 	{ return m_corrID; }
11689 
11690     /**
11691      * Check if the component has timed out
11692      * @return True if the component timed out, false otherwise
11693      */
timedOut()11694     inline bool timedOut()
11695 	{ return m_opTimer.timeout(); }
11696 
11697     /**
11698      * Set component state
11699      * @param state The state to be set
11700      */
11701     void setState(TCAPComponentState state);
11702 
11703     /**
11704      * Obtain the component state
11705      * @return The component state
11706      */
state()11707     inline TCAPComponentState state()
11708 	{ return m_state; }
11709 
11710     /**
11711      * Reset invocation timer on user request
11712      * @param params List of parameters
11713      * @param index Index of this component's parameters in the list
11714      */
11715     void resetTimer(NamedList& params, unsigned int index);
11716 
11717     /**
11718      * Retrieve operation class for this component
11719      * @return The class of the operation
11720      */
operationClass()11721     SS7TCAP::TCAPComponentOperationClass operationClass()
11722 	{ return m_opClass; }
11723 
11724     /**
11725      * Dictionary for component states
11726      */
11727     static const TokenDict s_compStates[];
11728 
11729 private:
11730     SS7TCAPTransaction* m_transact;
11731     SS7TCAP::TCAPUserCompActions m_type;
11732     TCAPComponentState m_state;
11733     String m_id;
11734     String m_corrID;
11735     String m_opCode;
11736     String m_opType;
11737     SS7TCAP::TCAPComponentOperationClass m_opClass;
11738     SignallingTimer m_opTimer;
11739     SS7TCAPError m_error;
11740 };
11741 
11742 /**
11743  * Implementation of SS7 Transactional Capabilities Application Part - specification ANSI
11744  * @short ANSI SS7 TCAP implementation
11745  */
11746 class YSIG_API SS7TCAPANSI : virtual public SS7TCAP
11747 {
11748     YCLASS(SS7TCAPANSI,SS7TCAP)
11749 public:
11750     enum TCAPTags {
11751 	TransactionIDTag    = 0xc7,
11752 	PCauseTag           = 0xd7,
11753 	UserAbortPTag       = 0xd8 , // Primitive
11754 	UserAbortCTag       = 0xf8,  // Constructor
11755     };
11756 
11757     enum TCAPDialogTags {
11758 	DialogPortionTag         = 0xf9,
11759 	ProtocolVersionTag       = 0xda,
11760 	IntApplicationContextTag = 0xdb,
11761 	OIDApplicationContextTag = 0xdc,
11762 	UserInformationTag       = 0xfd,
11763 	IntSecurityContextTag    = 0x80,
11764 	OIDSecurityContextTag    = 0x81,
11765 	ConfidentialityTag       = 0xa2,
11766     };
11767 
11768     enum UserInfoTags {
11769 	DirectReferenceTag       = 0x06,
11770 	DataDescriptorTag        = 0x07,
11771 	ExternalTag              = 0x28,
11772 	SingleASNTypePEncTag     = 0x80, // Primitive Single-ASN1-Type-Encoding
11773 	SingleASNTypeCEncTag     = 0xa0, // Constructor Single-ASN1-Type-Encoding
11774 	OctetAlignEncTag         = 0x81,
11775 	ArbitraryEncTag          = 0x82,
11776     };
11777 
11778     enum ConfidentialityTags {
11779 	IntConfidentialContextTag    = 0x80,
11780 	OIDConfidentialContextTag    = 0x81,
11781     };
11782 
11783     enum TCAPComponentTags {
11784 	ComponentPortionTag  = 0xe8,
11785 	ComponentsIDsTag     = 0xcf,
11786 	OperationNationalTag = 0xd0,
11787 	OperationPrivateTag  = 0xd1,
11788 	ErrorNationalTag     = 0xd3,
11789 	ErrorPrivateTag      = 0xd4,
11790 	ProblemCodeTag       = 0xd5,
11791 	ParameterSetTag      = 0xf2,
11792 	ParameterSeqTag      = 0x30,
11793     };
11794 
11795     /**
11796      * Constructor
11797      * @param params NamedList containing parameters for building TCAP
11798      */
11799     SS7TCAPANSI(const NamedList& params);
11800 
11801     /**
11802      * Destructor
11803      */
11804     ~SS7TCAPANSI();
11805 
11806     /**
11807      * Build a transaction
11808      * @param type Type with which to build the transactions
11809      * @param transactID ID for the transaction
11810      * @param params Parameters for building the transaction
11811      * @param initLocal True if built by user, false if by remote end
11812      * @return A transaction
11813      */
11814     virtual SS7TCAPTransaction* buildTransaction(SS7TCAP::TCAPUserTransActions type, const String& transactID, NamedList& params,
11815 	bool initLocal = true);
11816 
11817 private:
11818     SS7TCAPError decodeTransactionPart(NamedList& params, DataBlock& data);
11819     void encodeTransactionPart(NamedList& params, DataBlock& data);
11820 };
11821 
11822 /**
11823  * Implementation of SS7 Transactional Capabilities Application Part Transaction - specification ANSI
11824  * @short ANSI SS7 TCAP transaction implementation
11825  */
11826 class YSIG_API SS7TCAPTransactionANSI : public SS7TCAPTransaction
11827 {
11828 public:
11829     enum TCAPANSIComponentType {
11830 	CompUnknown         = 0x0,
11831 	Local               = 0x1,
11832 	InvokeLast          = 0xe9,
11833 	ReturnResultLast    = 0xea,
11834 	ReturnError         = 0xeb,
11835 	Reject              = 0xec,
11836 	InvokeNotLast       = 0xed,
11837 	ReturnResultNotLast = 0xee,
11838     };
11839 
11840     enum ANSITransactionType {
11841 	Unknown                         = 0x0,
11842 	Unidirectional                  = 0xe1,
11843 	QueryWithPermission             = 0xe2,
11844 	QueryWithoutPermission          = 0xe3,
11845 	Response                        = 0xe4,
11846 	ConversationWithPermission      = 0xe5,
11847 	ConversationWithoutPermission   = 0xe6,
11848 	Abort                           = 0xf6,
11849     };
11850 
11851     /**
11852      * Constructor
11853      * @param tcap TCAP holding this transaction
11854      * @param type Initiating type for transaction
11855      * @param transactID Transaction ID
11856      * @param params Decoded TCAP parameters for building the transaction
11857      * @param timeout Transaction timeout
11858      * @param initLocal True if the transaction was initiated locally, false if not
11859      */
11860     SS7TCAPTransactionANSI(SS7TCAP* tcap, SS7TCAP::TCAPUserTransActions type, const String& transactID, NamedList& params,
11861 	u_int64_t timeout, bool initLocal = true);
11862 
11863     /**
11864      * Destructor
11865      */
11866     ~SS7TCAPTransactionANSI();
11867 
11868     /**
11869      * Process transaction data and fill the NamedList with the decoded data
11870      * @param params NamedList to fill with decoded data
11871      * @param data Data to decode
11872      * @return A TCAP error encountered whilst decoding
11873      */
11874     virtual SS7TCAPError handleData(NamedList& params, DataBlock& data);
11875 
11876     /**
11877      * An update request for this transaction
11878      * @param type The type of transaction to which this transaction should be updated
11879      * @param params Update parameter
11880      * @param updateByUser True if the update is made by the local user, false if it's made by the remote end
11881      * @return A TCAP Error
11882      */
11883     virtual SS7TCAPError update(SS7TCAP::TCAPUserTransActions type, NamedList& params, bool updateByUser = true);
11884 
11885     /**
11886      * Handle TCAP relevant dialog data
11887      * @param params NamedList containing (if present) dialog information
11888      * @param byUser True if the dialog information is provided by the local user, false otherwise
11889      * @return A report error
11890      */
11891     virtual SS7TCAPError handleDialogPortion(NamedList& params, bool byUser = true);
11892 
11893     /**
11894      * Encode P-Abort information
11895      * @param tr The transaction on which the abort was signalled
11896      * @param params NamedList reference from which to get the P-Abort information
11897      * @param data DataBlock reference in which to insert the encoded P-Abort information
11898      */
11899     static void encodePAbort(SS7TCAPTransaction* tr, NamedList& params, DataBlock& data);
11900 
11901     /**
11902      * Decode P-Abort TCAP message portion
11903      * @param tr The transaction on which the abort was signalled
11904      * @param params NamedList reference to fill with the decoded P-Abort information
11905      * @param data DataBlock reference from which to decode P-Abort information
11906      */
11907     static SS7TCAPError decodePAbort(SS7TCAPTransaction* tr, NamedList& params, DataBlock& data);
11908 
11909     /**
11910      * Update the state of this transaction to end the transaction
11911      */
11912     virtual void updateToEnd();
11913 
11914     /**
11915      * Update transaction state
11916      * @param byUser True if update is requested by user, false if by remote
11917      */
11918     virtual void updateState(bool byUser);
11919 
11920     /**
11921      * Request content for this transaction
11922      * @param params List of parameters of this tranaction
11923      * @param data Data block to fill with encoded content
11924      */
11925     virtual void requestContent(NamedList& params, DataBlock& data);
11926 
11927     /**
11928      * Dictionary keeping string versions of transaction types
11929      */
11930     static const TokenDict s_ansiTransactTypes[];
11931 
11932 private:
11933     SS7TCAPError decodeDialogPortion(NamedList& params, DataBlock& data);
11934     void encodeDialogPortion(NamedList& params, DataBlock& data);
11935     SS7TCAPError decodeComponents(NamedList& params, DataBlock& data);
11936     void encodeComponents(NamedList& params, DataBlock& data);
11937 
11938     SS7TCAP::TCAPUserTransActions m_prevType;
11939 };
11940 
11941 /**
11942  * Implementation of SS7 Transactional Capabilities Application Part - specification ITU-T
11943  * @short ITU-T SS7 TCAP implementation
11944  */
11945 class YSIG_API SS7TCAPITU : virtual public SS7TCAP
11946 {
11947     YCLASS(SS7TCAPITU,SS7TCAP)
11948 public:
11949     enum TCAPTags {
11950 	OriginatingIDTag    = 0x48,
11951 	DestinationIDTag    = 0x49,
11952 	PCauseTag           = 0x4a,
11953     };
11954 
11955     enum TCAPDialogTags {
11956 	DialogPortionTag         = 0x6b,
11957 	ProtocolVersionTag       = 0x80,
11958 	ApplicationContextTag    = 0xa1,
11959 	UserInformationTag       = 0xbe,
11960     };
11961 
11962     enum UserInfoTags {
11963 	DirectReferenceTag       = 0x06,
11964 	DataDescriptorTag        = 0x07,
11965 	ExternalTag              = 0x28,
11966 	SingleASNTypePEncTag     = 0x80, // Primitive Single-ASN1-Type-Encoding
11967 	SingleASNTypeCEncTag     = 0xa0, // Constructor Single-ASN1-Type-Encoding
11968 	OctetAlignEncTag         = 0x81,
11969 	ArbitraryEncTag          = 0x82,
11970     };
11971 
11972     enum TCAPComponentTags {
11973 	ComponentPortionTag  = 0x6c,
11974 	LocalTag             = 0x02,
11975 	LinkedIDTag          = 0x80,
11976 	GlobalTag            = 0x06,
11977 	ParameterSeqTag      = 0x30,
11978 	ParameterSetTag      = 0x31,
11979     };
11980 
11981     /**
11982      * Constructor
11983      * @param params Parameters to build ITU TCAP
11984      */
11985     SS7TCAPITU(const NamedList& params);
11986 
11987     /**
11988      * Destructor
11989      */
11990     ~SS7TCAPITU();
11991 
11992     /**
11993      * Build a transaction
11994      * @param type Type with which to build the transactions
11995      * @param transactID ID for the transaction
11996      * @param params Parameters for building the transaction
11997      * @param initLocal True if built by user, false if by remote end
11998      * @return A transaction
11999      */
12000     virtual SS7TCAPTransaction* buildTransaction(SS7TCAP::TCAPUserTransActions type, const String& transactID, NamedList& params,
12001 	bool initLocal = true);
12002 
12003 private:
12004     SS7TCAPError decodeTransactionPart(NamedList& params, DataBlock& data);
12005     void encodeTransactionPart(NamedList& params, DataBlock& data);
12006 };
12007 
12008 /**
12009  * Implementation of SS7 Transactional Capabilities Application Part Transaction - specification ITU-T
12010  * @short ITU-T SS7 TCAP transaction implementation
12011  */
12012 class YSIG_API SS7TCAPTransactionITU : public SS7TCAPTransaction
12013 {
12014 public:
12015     enum ITUComponentType {
12016 	CompUnknown         = 0x0,
12017 	Local               = 0x1,
12018 	Invoke              = 0xa1,
12019 	ReturnResultLast    = 0xa2,
12020 	ReturnError         = 0xa3,
12021 	Reject              = 0xa4,
12022 	ReturnResultNotLast = 0xa7,
12023     };
12024 
12025     enum ITUTransactionType {
12026 	Unknown                         = 0x0,
12027 	Unidirectional                  = 0x61,
12028 	Begin                           = 0x62,
12029 	End                             = 0x64,
12030 	Continue                        = 0x65,
12031 	Abort                           = 0x67,
12032     };
12033 
12034     enum ITUDialogTags {
12035 	AARQDialogTag               = 0x60,
12036 	AAREDialogTag               = 0x61,
12037 	ABRTDialogTag               = 0x64,
12038 	ResultDiagnosticUserTag     = 0xa1,
12039 	ResultDiagnosticProviderTag = 0xa2,
12040 	ResultTag                   = 0xa2,
12041 	ResultDiagnosticTag         = 0xa3,
12042     };
12043 
12044     enum ITUDialogValues {
12045 	ResultAccepted                     = 0,
12046 	ResultRejected                     = 1,
12047 	DiagnosticUserNull                 = 0x10,
12048 	DiagnosticUserNoReason             = 0x11,
12049 	DiagnosticUserAppCtxtNotSupported  = 0x12,
12050 	DiagnosticProviderNull             = 0x20,
12051 	DiagnosticProviderNoReason         = 0x21,
12052 	DiagnosticProviderNoCommonDialog   = 0x22,
12053 	AbortSourceUser                    = 0x30,
12054 	AbortSourceProvider                = 0x31,
12055     };
12056 
12057     /**
12058      * Constructor
12059      * @param tcap TCAP holding this transaction
12060      * @param type Initiating type for transaction
12061      * @param transactID Transaction ID
12062      * @param params Parameters to build this transaction
12063      * @param timeout Transaction time out interval
12064      * @param initLocal True if the transaction was initiated locally, false if not
12065      */
12066     SS7TCAPTransactionITU(SS7TCAP* tcap, SS7TCAP::TCAPUserTransActions type, const String& transactID, NamedList& params,
12067 	u_int64_t timeout, bool initLocal = true);
12068 
12069     /**
12070      * Destructor
12071      */
12072     ~SS7TCAPTransactionITU();
12073 
12074     /**
12075      * Process transaction data and fill the NamedList with the decoded data
12076      * @param params NamedList to fill with decoded data
12077      * @param data Data to decode
12078      * @return A TCAP error encountered whilst decoding
12079      */
12080     virtual SS7TCAPError handleData(NamedList& params, DataBlock& data);
12081 
12082     /**
12083      * An update request for this transaction
12084      * @param type The type of transaction to which this transaction should be updated
12085      * @param params Update parameter
12086      * @param updateByUser True if the update is made by the local user, false if it's made by the remote end
12087      * @return A TCAP Error
12088      */
12089     virtual SS7TCAPError update(SS7TCAP::TCAPUserTransActions type, NamedList& params, bool updateByUser = true);
12090 
12091     /**
12092      * Handle TCAP relevant dialog data
12093      * @param params NamedList containing (if present) dialog information
12094      * @param byUser True if the dialog information is provided by the local user, false otherwise
12095      * @return A report error
12096      */
12097     virtual SS7TCAPError handleDialogPortion(NamedList& params, bool byUser = true);
12098 
12099     /**
12100      * Encode P-Abort information
12101      * @param tr The transaction on which the abort was signalled
12102      * @param params NamedList reference from which to get the P-Abort information
12103      * @param data DataBlock reference in which to insert the encoded P-Abort information
12104      */
12105     static void encodePAbort(SS7TCAPTransaction* tr, NamedList& params, DataBlock& data);
12106 
12107     /**
12108      * Decode P-Abort TCAP message portion
12109      * @param tr The transaction on which the abort was signalled
12110      * @param params NamedList reference to fill with the decoded P-Abort information
12111      * @param data DataBlock reference from which to decode P-Abort information
12112      * @return A report error
12113      */
12114     static SS7TCAPError decodePAbort(SS7TCAPTransaction* tr, NamedList& params, DataBlock& data);
12115 
12116     /**
12117      * Update the state of this transaction to end the transaction
12118      */
12119     virtual void updateToEnd();
12120 
12121     /**
12122      * Check if the transaction present dialog information
12123      * @return True if dialog information is present, false otherwise
12124      */
dialogPresent()12125     inline bool dialogPresent()
12126 	{ return !(m_appCtxt.null()); }
12127 
12128     /**
12129      * Test for dialog when decoding
12130      * @param data Data from which the transaction is decoded
12131      * @return True if dialog portion is present, false otherwise
12132      */
12133     bool testForDialog(DataBlock& data);
12134 
12135     /**
12136      * Encode dialog portion of transaction
12137      * @param params List of parameters to encode
12138      * @param data Data block into which to insert the encoded data
12139      */
12140     void encodeDialogPortion(NamedList& params, DataBlock& data);
12141 
12142     /**
12143      * Decode dialog portion
12144      * @param params List into which to put the decoded dialog parameters
12145      * @param data Data to decodeCaps
12146      * @return A report error
12147      */
12148     SS7TCAPError decodeDialogPortion(NamedList& params, DataBlock& data);
12149 
12150     /**
12151      * Update transaction state
12152      * @param byUser True if update is requested by user, false if by remote
12153      */
12154     void updateState(bool byUser = false);
12155 
12156     /**
12157      * Request content for this transaction
12158      * @param params List of parameters of this tranaction
12159      * @param data Data block to fill with encoded content
12160      */
12161     virtual void requestContent(NamedList& params, DataBlock& data);
12162 
12163     /**
12164      * Set information in case of abnormal dialog detection
12165      * @param params List of parameters where to set the abnormal dialog information
12166      */
12167     virtual void abnormalDialogInfo(NamedList& params);
12168 
12169     /**
12170      * Dictionary for Dialogue PDUs
12171      */
12172     static const TokenDict s_dialogPDUs[];
12173 
12174     /**
12175      * Dictionary for dialogue result values
12176      */
12177     static const TokenDict s_resultPDUValues[];
12178 
12179 private:
12180     SS7TCAPError decodeComponents(NamedList& params, DataBlock& data);
12181     void encodeComponents(NamedList& params, DataBlock& data);
12182 
12183     String m_appCtxt;
12184 };
12185 
12186 // The following classes are ISDN, not SS7, but they use the same signalling
12187 //  interfaces so they will remain here
12188 
12189 /**
12190  * An interface to a Layer 2 (Q.921) ISDN message transport
12191  * @short Abstract ISDN layer 2 (Q.921) message transport
12192  */
12193 class YSIG_API ISDNLayer2 : virtual public SignallingComponent
12194 {
YCLASS(ISDNLayer2,SignallingComponent)12195     YCLASS(ISDNLayer2,SignallingComponent)
12196     friend class ISDNQ921Management;
12197 public:
12198     /**
12199      * Layer states if it has a TEI assigned
12200      */
12201     enum State {
12202 	Released,                        // Multiple frame acknowledged not allowed
12203 	WaitEstablish,                   // Wating to establish 'multiple frame acknowledged' mode
12204 	Established,                     // Multiple frame acknowledged allowed
12205 	WaitRelease,                     // Wating to release 'multiple frame acknowledged' mode
12206     };
12207 
12208     /**
12209      * Destructor
12210      */
12211     virtual ~ISDNLayer2();
12212 
12213     /**
12214      * Get the ISDN Layer 3 attached to this layer
12215      */
layer3()12216     inline ISDNLayer3* layer3() const
12217 	{ return m_layer3; }
12218 
12219     /**
12220      * Get the layer's state
12221      * @return The layer's state as enumeration
12222      */
state()12223     inline State state() const
12224 	{ return m_state; }
12225 
12226     /**
12227      * Check if this interface is the network or CPE (user) side of the link
12228      * @return True if this interface is the network side of the link
12229      */
network()12230     inline bool network() const
12231 	{ return m_network; }
12232 
12233     /**
12234      * Check if this interface should change its type
12235      * @return True if type change is allowed
12236      */
detectType()12237     inline bool detectType() const
12238 	{ return m_detectType; }
12239 
12240     /**
12241      * Get the SAPI (Service Access Point Identifier) of this interface
12242      * @return The SAPI (Service Access Point Identifier) of this interface
12243      */
localSapi()12244     inline u_int8_t localSapi() const
12245 	{ return m_sapi; }
12246 
12247     /**
12248      * Get the TEI (Terminal Endpoint Identifier) of this interface
12249      * @return The TEI (Terminal Endpoint Identifier) of this interface
12250      */
localTei()12251     inline u_int8_t localTei() const
12252 	{ return m_tei; }
12253 
12254     /**
12255      * Get the maximum length of user data transported through this layer
12256      * @return The maximum length of user data transported through this layer
12257      */
maxUserData()12258     inline u_int32_t maxUserData() const
12259 	{ return m_maxUserData; }
12260 
12261     /**
12262      * Check if this interface has a TEI assigned
12263      * @return True if this interface has a TEI assigned
12264      */
teiAssigned()12265     inline bool teiAssigned() const
12266 	{ return m_teiAssigned; }
12267 
12268     /**
12269      * Check if this interface will automatically re-establish when released
12270      * @return The auto restart flag
12271      */
autoRestart()12272     inline bool autoRestart() const
12273 	{ return m_autoRestart; }
12274 
12275     /**
12276      * Get the uptime of the interface
12277      * @return Time since interface got up in seconds
12278      */
upTime()12279     unsigned int upTime() const
12280 	{ return m_lastUp ? (Time::secNow() - m_lastUp) : 0; }
12281 
12282     /**
12283      * Implements Q.921 DL-ESTABLISH and DL-RELEASE request primitives
12284      * Descendants must implement this method to fullfill the request
12285      * @param tei This layer TEI (Terminal Endpoint Identifier)
12286      * @param establish True to establish. False to release
12287      * @param force True to establish even if we already are in this mode. This
12288      *  parameter is ignored if establish is false
12289      * @return True if the request was accepted
12290      */
multipleFrame(u_int8_t tei,bool establish,bool force)12291     virtual bool multipleFrame(u_int8_t tei, bool establish, bool force)
12292 	{ return false; }
12293 
12294     /**
12295      * Implements Q.921 DL-DATA and DL-UNIT DATA request primitives
12296      * Descendants must implement this method to fullfill the request
12297      * @param data Data to send
12298      * @param tei This layer TEI
12299      * @param ack True to send an acknowledged frame, false to send an unacknowledged one
12300      * @return True if the request was accepted
12301      */
sendData(const DataBlock & data,u_int8_t tei,bool ack)12302     virtual bool sendData(const DataBlock& data, u_int8_t tei, bool ack)
12303 	{ return false; }
12304 
12305     /**
12306      * Emergency release.
12307      * Descendants must implement this method to cleanup/reset data
12308      */
12309     virtual void cleanup() = 0;
12310 
12311     /**
12312      * Attach an ISDN Q.931 Layer 3 if the given parameter is different from the one we have
12313      * Cleanup the object before ataching the new Layer 3
12314      * This method is thread safe
12315      * @param layer3 Pointer to the Q.931 Layer 3 to attach
12316      */
12317     virtual void attach(ISDNLayer3* layer3);
12318 
12319     /**
12320      * Get the text associated with a given state
12321      * @param s The state to get the text for
12322      * @return The text associated with the given state
12323      */
stateName(State s)12324     static inline const char* stateName(State s)
12325 	{ return lookup((int)s,m_states); }
12326 
12327 protected:
12328     /**
12329      * Constructor
12330      * Initialize this interface and the component
12331      * @param params Layer's parameters
12332      * @param name Optional name of the component
12333      * @param tei Value of TEI for this layer
12334      */
12335     ISDNLayer2(const NamedList& params, const char* name = 0, u_int8_t tei = 0);
12336 
12337     /**
12338      * Retrieve the layer's mutex
12339      * @return Reference to the Layer 2 mutex
12340      */
l2Mutex()12341     inline Mutex& l2Mutex()
12342 	{ return m_layerMutex; }
12343 
12344     /**
12345      * Implements Q.921 DL-ESTABLISH indication/confirmation primitive
12346      *  of 'multiple frame acknowledged' mode established
12347      * @param tei The TEI requested
12348      * @param confirm True if this is a confirmation of a previous request.
12349      *  False if it is an indication of state change on remote request
12350      * @param timeout True if the reason is a timeout.
12351      */
12352     void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout);
12353 
12354     /**
12355      * Implements Q.921 DL-RELEASE indication/confirmation primitive
12356      *  of 'multiple frame acknowledged' mode released
12357      * @param tei The TEI released
12358      * @param confirm True if this is a confirmation of a previous request.
12359      *  False if it is an indication of state change on remote request
12360      * @param timeout True if the reason is a timeout.
12361      */
12362     void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout);
12363 
12364     /**
12365      * Notify layer 3 of data link set/release command or response
12366      * Used for stateless layer 2
12367      * @param tei The TEI of this layer
12368      * @param cmd True if received a command, false if received a response
12369      * @param value The value of the notification
12370      *	If 'cmd' is true (command), the value is true if a request to establish data link was received
12371      *   or false if received a request to release data link
12372      *	If 'cmd' is false (response), the value is the response
12373      */
12374     void dataLinkState(u_int8_t tei, bool cmd, bool value);
12375 
12376     /**
12377      * Notify layer 3 of data link idle timeout
12378      * Used for stateless layer 2
12379      */
12380     void idleTimeout();
12381 
12382     /**
12383      * Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
12384      * Receive data from remote peer
12385      * @param data Received data
12386      * @param tei The TEI for which the data was received
12387      */
12388     void receiveData(const DataBlock& data, u_int8_t tei);
12389 
12390     /**
12391      * Set TEI assigned status. Print a debug message. If status is false calls cleanup()
12392      * Descendants are responsable for TEI assigned status management
12393      * @param status The new TEI assigned status
12394      */
12395     void teiAssigned(bool status);
12396 
12397     /**
12398      * Set the state
12399      * Descendants are responsable for multiple frame status management
12400      * @param newState The new state
12401      * @param reason Reason of state change, NULL if unspecified
12402      */
12403     void changeState(State newState, const char* reason = 0);
12404 
12405     /**
12406      * Change the interface type
12407      * @return True if interface type changed
12408      */
12409     bool changeType();
12410 
12411     /**
12412      * Set the automatically re-establish when released flag
12413      * @param restart The new value of the auto restart flag
12414      */
autoRestart(bool restart)12415     inline void autoRestart(bool restart)
12416 	{ m_autoRestart = restart; }
12417 
12418     /**
12419      * Set the Reference Identifier used in management procedures
12420      * @param ri The new reference number
12421      */
setRi(u_int16_t ri)12422     inline void setRi(u_int16_t ri)
12423 	{ m_ri = ri; }
12424 
12425     /**
12426      * Parse a received packet
12427      * @param packet The packet received
12428      * @return Pointer to a newly created frame, NULL if an error occured
12429      */
12430     ISDNFrame* parsePacket(const DataBlock& packet);
12431 
12432 private:
12433     ISDNLayer3* m_layer3;                // The attached Layer 3 interface
12434     Mutex m_layerMutex;                  // Layer 2 operations mutex
12435     Mutex m_layer3Mutex;                 // Control m_layer3 operations
12436     State m_state;                       // Layer's state
12437     bool m_network;                      // Network/CPE type of the interface
12438     bool m_detectType;                   // Detect interface type
12439     u_int8_t m_sapi;                     // SAPI value
12440     u_int8_t m_tei;                      // TEI value
12441     u_int16_t m_ri;                      // Reference number
12442     u_int32_t m_lastUp;                  // Time when the interface got up
12443     bool m_checked;                      // Flag to indicate if the layer was checked
12444     bool m_teiAssigned;                  // The TEI status
12445     bool m_autoRestart;                  // True to restart when released
12446     u_int32_t m_maxUserData;             // Maximum length of user data transported trough this layer
12447     unsigned int m_teiRefNumber;         // The Reference Number (Ri) carried by a TEI management frame
12448     static const TokenDict m_states[];   // Keep the string associated with each state
12449 };
12450 
12451 /**
12452  * An interface to a Layer 3 (Q.931) ISDN message transport
12453  * @short Abstract ISDN layer 3 (Q.931) message transport
12454  */
12455 class YSIG_API ISDNLayer3 : virtual public SignallingComponent
12456 {
YCLASS(ISDNLayer3,SignallingComponent)12457     YCLASS(ISDNLayer3,SignallingComponent)
12458 public:
12459     /**
12460      * Implements Q.921 DL-ESTABLISH indication/confirmation primitive:
12461      *  'multiple frame acknowledged' mode established
12462      * @param tei The TEI of the frame
12463      * @param confirm True if this is a confirmation of a previous request.
12464      *  False if it is an indication of state change on remote request
12465      * @param timeout True if the reason is a timeout
12466      * @param layer2 Pointer to the notifier
12467      */
12468     virtual void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2)
12469 	{ }
12470 
12471     /**
12472      * Implements Q.921 DL-RELEASE indication/confirmation primitive:
12473      *  'multiple frame acknowledged' mode released
12474      * @param tei The TEI of the frame
12475      * @param confirm True if this is a confirmation of a previous request.
12476      *  False if it is an indication of state change on remote request
12477      * @param timeout True if the reason is a timeout.
12478      * @param layer2 Pointer to the notifier
12479      */
multipleFrameReleased(u_int8_t tei,bool confirm,bool timeout,ISDNLayer2 * layer2)12480     virtual void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2)
12481 	{ }
12482 
12483     /**
12484      * Notification from layer 2 of data link set/release command or response
12485      * Used for stateless layer 2
12486      * @param tei The TEI of the command or response
12487      * @param cmd True if received a command, false if received a response
12488      * @param value The value of the notification
12489      *	If 'cmd' is true (command), the value is true if a request to establish data link was received
12490      *   or false if received a request to release data link
12491      *	If 'cmd' is false (response), the value is the response
12492      * @param layer2 Pointer to the notifier
12493      */
dataLinkState(u_int8_t tei,bool cmd,bool value,ISDNLayer2 * layer2)12494     virtual void dataLinkState(u_int8_t tei, bool cmd, bool value, ISDNLayer2* layer2)
12495 	{ }
12496 
12497     /**
12498      * Notification from layer 2 of data link idle timeout
12499      * Used for stateless layer 2
12500      * @param layer2 Pointer to the notifier
12501      */
idleTimeout(ISDNLayer2 * layer2)12502     virtual void idleTimeout(ISDNLayer2* layer2)
12503 	{ }
12504 
12505     /**
12506      * Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
12507      * Receive data from remote peer
12508      * @param data Received data
12509      * @param tei The TEI of the received frame
12510      * @param layer2 Pointer to the sender
12511      */
12512     virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2) = 0;
12513 
12514     /**
12515      * Attach an ISDN Q.921 Layer 2
12516      * @param layer2 Pointer to the Q.921 Layer 2 to attach
12517      * @return Pointer to the detached Layer 2 or NULL
12518      */
attach(ISDNLayer2 * layer2)12519     virtual ISDNLayer2* attach(ISDNLayer2* layer2)
12520 	{ return 0; }
12521 
12522 protected:
12523     /**
12524      * Constructor
12525      * Initialize the component
12526      * @param name Name of this component
12527      */
12528     inline ISDNLayer3(const char* name = 0)
SignallingComponent(name)12529 	: SignallingComponent(name),
12530 	  m_layerMutex(true,"ISDNLayer3::layer")
12531 	{ }
12532 
12533     /**
12534      * Retrieve the layer's mutex
12535      * @return Reference to the Layer 3 mutex
12536      */
l3Mutex()12537     inline Mutex& l3Mutex()
12538 	{ return m_layerMutex; }
12539 
12540 private:
12541     Mutex m_layerMutex;                  // Layer 3 operations mutex
12542 };
12543 
12544 /**
12545  * Encapsulates an ISDN (Q.921) frame exchanged over a hardware HDLC interface
12546  * @short An ISDN frame
12547  */
12548 class YSIG_API ISDNFrame : public RefObject
12549 {
12550     friend class ISDNQ921;
12551     friend class ISDNQ921Management;
12552 public:
12553     /**
12554      * Frame type according to Q.921 3.6
12555      */
12556     enum Type {
12557 	DISC = 1,                        // disconnect (command)
12558 	DM = 2,                          // disconnected (response)
12559 	FRMR = 3,                        // frame reject (response)
12560 	I = 4,                           // information transfer (response)
12561 	REJ = 5,                         // reject (command/response)
12562 	RNR = 6,                         // receive not ready (command/response)
12563 	RR = 7,                          // receive ready (command/response)
12564 	SABME = 8,                       // set asynchronous balanced mode extended (command)
12565 	UA = 9,                          // unnumbered acknoledgement (response)
12566 	UI = 10,                         // unnumbered information (command)
12567 	XID = 11,                        // exchange identification (command/response)
12568 	// Note: Keep all errors greater then Invalid: The code relies on it
12569 	Invalid = 100,
12570 	ErrUnknownCR = 101,              // Error: Unknown command/response. Set by parser
12571 	ErrHdrLength = 102,              // Error: Invalid header length. Set by parser
12572 	ErrDataLength = 103,             // Error: Information field too long
12573 	ErrRxSeqNo = 104,                // Error: Invalid receive sequence number
12574 	ErrTxSeqNo = 105,                // Error: Invalid send sequence number
12575 	ErrInvalidEA = 106,              // Error: Invalid 'extended address' bit(s). Set by parser
12576 	ErrInvalidAddress = 107,         // Error: Invalid SAPI/TEI
12577 	ErrUnsupported = 108,            // Error: Unsupported command. E.g. XID
12578 	ErrInvalidCR = 109,              // Error: Invalid command/response flag
12579     };
12580 
12581     /**
12582      * Codes used for TEI management procedures (Q.921 Table 8)
12583      */
12584     enum TeiManagement {
12585 	TeiReq       = 1,                // TEI request (user to network)
12586 	TeiAssigned  = 2,                // TEI assigned (network to user)
12587 	TeiDenied    = 3,                // TEI denied (network to user)
12588 	TeiCheckReq  = 4,                // TEI check request (network to user)
12589 	TeiCheckRsp  = 5,                // TEI check response (user to network)
12590 	TeiRemove    = 6,                // TEI remove (network to user)
12591 	TeiVerify    = 7                 // TEI verify (user to network)
12592     };
12593 
12594     /**
12595      * Frame category
12596      */
12597     enum Category {
12598 	Data,                            // I, UI
12599 	Supervisory,                     // RR, RNR, REJ
12600 	Unnumbered,                      // SABME, DISC, UA DM, FRMR XID
12601 	Error
12602     };
12603 
12604     /**
12605      * Destructor
12606      */
12607     virtual ~ISDNFrame();
12608 
12609     /**
12610      * Get the type of this frame
12611      * @return The type of this frame as enumeration
12612      */
type()12613     inline Type type() const
12614 	{ return m_type; }
12615 
12616     /**
12617      * Get the error type
12618      * @return The error type of this frame as enumeration
12619      */
error()12620     inline Type error() const
12621 	{ return m_error; }
12622 
12623     /**
12624      * Get the category of this frame
12625      * @return The category of this frame as enumeration
12626      */
category()12627     inline Category category() const
12628 	{ return m_category; }
12629 
12630     /**
12631      * Check if this frame is a command
12632      * @return True if this frame is a command. False if it is a response
12633      */
command()12634     inline bool command() const
12635 	{ return m_command; }
12636 
12637     /**
12638      * Get the SAPI of this frame
12639      * @return The SAPI of this frame
12640      */
sapi()12641     inline u_int8_t sapi() const
12642 	{ return m_sapi; }
12643 
12644     /**
12645      * Get the TEI of this frame
12646      * @return The TEI of this frame
12647      */
tei()12648     inline u_int8_t tei() const
12649 	{ return m_tei; }
12650 
12651     /**
12652      * Check if this frame is a poll (expect response) or a final one
12653      * @return True if this a poll frame. False if it is a final one
12654      */
poll()12655     inline bool poll() const
12656 	{ return m_poll; }
12657 
12658     /**
12659      * Get the transmitter send sequence number
12660      * @return The transmitter send sequence number
12661      */
ns()12662     inline u_int8_t ns() const
12663 	{ return m_ns; }
12664 
12665     /**
12666      * Get the transmitter receive sequence number
12667      * @return The transmitter receive sequence number
12668      */
nr()12669     inline u_int8_t nr() const
12670 	{ return m_nr; }
12671 
12672     /**
12673      * Get the length of the frame's header
12674      * @return The length of the frame's header
12675      */
headerLength()12676     inline u_int8_t headerLength() const
12677 	{ return m_headerLength; }
12678 
12679     /**
12680      * Get the length of the data carried by this frame
12681      * @return The length of the data carried by this frame
12682      */
dataLength()12683     inline u_int32_t dataLength() const
12684 	{ return m_dataLength; }
12685 
12686     /**
12687      * Get the frame's buffer
12688      * @return The frame's buffer
12689      */
buffer()12690     inline const DataBlock& buffer() const
12691 	{ return m_buffer; }
12692 
12693     /**
12694      * Check if the frame was sent
12695      * @return True if the frame was sent
12696      */
sent()12697     inline bool sent() const
12698 	{ return m_sent; }
12699 
12700     /**
12701      * Set transmitted flag
12702      */
sent(bool value)12703     inline void sent(bool value)
12704 	{ m_sent = value; }
12705 
12706     /**
12707      * Get the text associated with the frame's type
12708      * @return The text associated with the frame's type
12709      */
name()12710     inline const char* name() const
12711 	{ return typeName(type()); }
12712 
12713     /**
12714      * Update sequence numbers for I frames
12715      * @param ns Optional update send sequence number
12716      * @param nr Optional update receive sequence number
12717      */
12718     void update(u_int8_t* ns = 0, u_int8_t* nr = 0);
12719 
12720     /**
12721      * Get the data transferred with this frame
12722      * @param dest The destination buffer
12723      */
getData(DataBlock & dest)12724     inline void getData(DataBlock& dest) const
12725 	{ dest.assign((u_int8_t*)m_buffer.data() + m_headerLength,m_dataLength); }
12726 
12727     /**
12728      * Write this frame to a string for debug purposes
12729      * @param dest The destination string
12730      * @param extendedDebug True to dump message header and data
12731      */
12732     void toString(String& dest, bool extendedDebug) const;
12733 
12734     /**
12735      * Check if the received frame is a TEI management frame
12736      * @return True if the frame is a TEI management one, false if it's not
12737      */
12738     bool checkTeiManagement() const;
12739 
12740     /**
12741      * Get reference number from frame
12742      * @param data The data block which contains it
12743      * @return Reference number
12744      */
12745     static u_int16_t getRi(const DataBlock& data);
12746 
12747     /**
12748      * Get frame message type
12749      * @param data The data block which contains it
12750      * @return Message type
12751      */
getType(const DataBlock & data)12752     inline static u_int8_t getType(const DataBlock& data)
12753 	{ return static_cast<u_int8_t>(data.at(3,0)); }
12754 
12755     /**
12756      * Get action indicator
12757      * @param data Data block which contains it
12758      * @return Action indicator value
12759      */
getAi(const DataBlock & data)12760     inline static u_int8_t getAi(const DataBlock& data)
12761 	{ return static_cast<u_int8_t>(data.at(4,0) >> 1); }
12762 
12763 
12764     /**
12765      * Parse a received data block
12766      * @param data Data to parse
12767      * @param receiver The receiver of the data
12768      * @return ISDNFrame pointer or 0 (no control field)
12769      */
12770     static ISDNFrame* parse(const DataBlock& data, ISDNLayer2* receiver);
12771 
12772     /**
12773      * Build a TEI management message buffer
12774      * @param data Destination buffer to fill
12775      * @param type The message type
12776      * @param ri The reference number
12777      * @param ai The action indicator
12778      * @return True on succes
12779      */
12780     static bool buildTeiManagement(DataBlock& data, u_int8_t type, u_int16_t ri,
12781 	u_int8_t ai);
12782 
12783     /**
12784      * Get the command bit value for a given side of a data link
12785      * @param network True for the network side,
12786      *  false for the user side of a data link
12787      * @return The appropriate command bit value
12788      */
commandBit(bool network)12789     static inline bool commandBit(bool network)
12790 	{ return network; }
12791 
12792     /**
12793      * Get the response bit value for a given side of a data link
12794      * @param network True for the network side,
12795      *  false for the user side of a data link
12796      * @return The appropriate response bit value
12797      */
responseBit(bool network)12798     static inline bool responseBit(bool network)
12799 	{ return !network; }
12800 
12801     /**
12802      * Get the command/response type from C/R bit value and sender type
12803      * @param cr The value of the C/R bit
12804      * @param sentByNetwork True if the sender is the network side of the data link
12805      * @return True if it is a command
12806      */
isCommand(u_int8_t cr,bool sentByNetwork)12807     static inline bool isCommand(u_int8_t cr, bool sentByNetwork)
12808 	{ return cr ? sentByNetwork : !sentByNetwork; }
12809 
12810     /**
12811      * Get the text associated with the given frame type
12812      * @param type Frame type to get the text for
12813      * @return The text associated with the given frame type
12814      */
typeName(Type type)12815     static inline const char* typeName(Type type)
12816 	{ return lookup(type,s_types,"Invalid frame"); }
12817 
12818     /**
12819      * Keep the association between frame types and texts
12820      */
12821     static const TokenDict s_types[];
12822 
12823 protected:
12824     /**
12825      * Constructor
12826      * Used by the parser
12827      * @param type Frame type
12828      */
12829     ISDNFrame(Type type = Invalid);
12830 
12831     /**
12832      * Constructor
12833      * Create U/S frames: SABME/DM/DISC/UA/FRMR/XID/RR/RNR/REJ
12834      * Set data members. Encode frame in buffer according to Q.921
12835      * Used by ISDNLayer2 to create outgoing frames
12836      * @param type Frame type
12837      * @param command Frame command/response's flag
12838      * @param senderNetwork True if the sender is the network side of the data link
12839      * @param sapi SAPI value
12840      * @param tei TEI value
12841      * @param pf Poll/final flag
12842      * @param nr Optional transmitter receive sequence number
12843      */
12844     ISDNFrame(Type type, bool command, bool senderNetwork,
12845 	u_int8_t sapi, u_int8_t tei, bool pf, u_int8_t nr = 0);
12846 
12847     /**
12848      * Constructor
12849      * Create I/UI frames
12850      * Set data members. Encode frame in buffer according to Q.921
12851      * Used by ISDNLayer2 to create outgoing frames
12852      * @param ack True to create an I frame. False to create an UI frame
12853      * @param senderNetwork True if the sender is the network side of the data link
12854      * @param sapi SAPI value
12855      * @param tei TEI value
12856      * @param pf Poll/final flag
12857      * @param data Transmitted data
12858      */
12859     ISDNFrame(bool ack, bool senderNetwork, u_int8_t sapi, u_int8_t tei,
12860 	bool pf, const DataBlock& data);
12861 
12862 private:
12863     Type m_type;                         // Frame type
12864     Type m_error;                        // Frame error type
12865     Category m_category;                 // Frame category
12866     // Address
12867     bool m_command;                      // Command/Response frame
12868     bool m_senderNetwork;                // True if the sender of this frame is the network side of the data link
12869     u_int8_t m_sapi;                     // SAPI value
12870     u_int8_t m_tei;                      // TEI value
12871     // Control
12872     bool m_poll;                         // Poll/Final flag
12873     u_int8_t m_ns;                       // N(S) value (when applicable): transmitter send sequence number
12874     u_int8_t m_nr;                       // N(R) value (when applicable): transmitter receive sequence number
12875     // Data
12876     u_int8_t m_headerLength;             // Header length
12877     u_int32_t m_dataLength;              // Data length
12878     DataBlock m_buffer;                  // Whole frame: header + data + FCS (frame check sequence = 2 bytes)
12879     // Outgoing frames only
12880     bool m_sent;                         // True if already sent
12881 };
12882 
12883 /**
12884  * Q.921 ISDN Layer 2 implementation on top of a hardware HDLC interface
12885  * @short ISDN Q.921 implementation on top of a hardware interface
12886  */
12887 class YSIG_API ISDNQ921 : public ISDNLayer2, public SignallingReceiver, public SignallingDumpable
12888 {
12889     YCLASS2(ISDNQ921,ISDNLayer2,SignallingReceiver)
12890     friend class ISDNQ921Management;
12891 public:
12892     /**
12893      * Constructor
12894      * Initialize this object and the component
12895      * @param params Layer's and @ref TelEngine::ISDNLayer2 parameters
12896      * @param name Name of this component
12897      * @param mgmt TEI management component
12898      * @param tei Value of TEI for this component
12899      */
12900     ISDNQ921(const NamedList& params, const char* name = 0, ISDNQ921Management* mgmt = 0, u_int8_t tei = 0);
12901 
12902     /**
12903      * Destructor
12904      */
12905     virtual ~ISDNQ921();
12906 
12907     /**
12908      * Configure and initialize Q.921 and its interface
12909      * @param config Optional configuration parameters override
12910      * @return True if Q.921 and the interface were initialized properly
12911      */
12912     virtual bool initialize(const NamedList* config);
12913 
12914     /**
12915      * Get the timeout of a data frame. After that, a higher layer may retransmit data
12916      * @return The timeout of a data frame
12917      */
dataTimeout()12918     inline u_int64_t dataTimeout() const
12919 	{ return m_retransTimer.interval() * m_n200.maxVal(); }
12920 
12921     /**
12922      * Implements Q.921 DL-ESTABLISH and DL-RELEASE request primitives
12923      * If accepted, the primitive is enqueued for further processing
12924      * This method is thread safe
12925      * @param tei This layer's TEI
12926      * @param establish True to establish. False to release
12927      * @param force True to establish even if we already are in this mode. This
12928      *  parameter is ignored if establish is false
12929      * @return True if the request was accepted
12930      */
12931     virtual bool multipleFrame(u_int8_t tei, bool establish, bool force);
12932 
12933     /**
12934      * Implements Q.921 DL-DATA and DL-UNIT DATA request primitives
12935      * Send data through the HDLC interface
12936      * This method is thread safe
12937      * @param data Data to send
12938      * @param tei The TEI to send with the data frane
12939      * @param ack True to send an acknowledged frame, false to send an unacknowledged one
12940      * @return False if the request was not accepted or send operation failed
12941      */
12942     virtual bool sendData(const DataBlock& data, u_int8_t tei, bool ack);
12943 
12944     /**
12945      * Send a SABME frame to reset the layer
12946      * @return True if a SABME frame was sent
12947      */
sendSabme()12948     inline bool sendSabme()
12949 	{ return sendUFrame(ISDNFrame::SABME,true,true); }
12950 
12951     /**
12952      * Emergency release.
12953      * Send 'disconnect' command. Reset all data. Set state to 'Released'
12954      * This method is thread safe
12955      */
12956     virtual void cleanup();
12957 
12958     /**
12959      * Set debug data of this layer
12960      * @param printFrames Enable/disable frame printing on output
12961      * @param extendedDebug Enable/disable hex data dump if print frames is enabled
12962      */
setDebug(bool printFrames,bool extendedDebug)12963     inline void setDebug(bool printFrames, bool extendedDebug)
12964 	{ m_extendedDebug = ((m_printFrames = printFrames) && extendedDebug); }
12965 
12966 protected:
12967     /**
12968      * Detach links. Disposes memory
12969      */
destroyed()12970     virtual void destroyed()
12971     {
12972 	ISDNLayer2::attach((ISDNLayer3*)0);
12973 	TelEngine::destruct(SignallingReceiver::attach(0));
12974 	SignallingComponent::destroyed();
12975     }
12976 
12977     /**
12978      * Method called periodically to check timeouts
12979      * This method is thread safe
12980      * @param when Time to use as computing base for events and timeouts
12981      */
12982     virtual void timerTick(const Time& when);
12983 
12984     /**
12985      * Process a packet received by the receiver's interface
12986      * This method is thread safe
12987      * @param packet The received packet
12988      * @return True if message was successfully processed
12989      */
12990     virtual bool receivedPacket(const DataBlock& packet);
12991 
12992     /**
12993      * Process the frame received
12994      * @param frame Pointer to frame to process
12995      * @return True if the frame was processed
12996      */
12997     bool receivedFrame(ISDNFrame* frame);
12998 
12999     /**
13000      * Process a notification generated by the attached interface
13001      * This method is thread safe
13002      * @param event Notification event reported by the interface
13003      * @return True if notification was processed
13004      */
13005     virtual bool notify(SignallingInterface::Notification event);
13006 
13007     /**
13008      * Reset object if not in Released state. Drop all frames
13009      * This method is thread safe
13010      */
13011     void reset();
13012 
13013 private:
control(NamedList & params)13014     virtual bool control(NamedList& params)
13015 	{ return SignallingDumpable::control(params,this); }
13016     // Acknoledge outgoing frames
13017     // @param frame The acknoledging frame
13018     bool ackOutgoingFrames(const ISDNFrame* frame);
13019     // Process a received I/UI frame
13020     // @param ack True for I frame, false for UI frame
13021     // @return True to send data to Layer 3
13022     bool processDataFrame(const ISDNFrame* frame, bool ack);
13023     // Process a received S frame
13024     // @return True to exit from timer recovery state
13025     bool processSFrame(const ISDNFrame* frame);
13026     // Process a received U frame
13027     // @param newState The new state if true is returned
13028     // @param confirmation True if the new state is Established or Released and
13029     //  this is a confirmation
13030     // @return True to change state
13031     bool processUFrame(const ISDNFrame* frame, State& newState,
13032 	bool& confirmation);
13033     // Accept frame according to Q.921 5.8.5
13034     // Update counters.
13035     // If not accepted the frame is rejected or dropped
13036     // reject is set to true if the frame is rejected
13037     bool acceptFrame(ISDNFrame* frame, bool& reject);
13038     // Update rejected frames counter. Print message. Send FRMR (frame reject)
13039     void rejectFrame(const ISDNFrame* frame, const char* reason = 0);
13040     // Update dropped frames counter. Print message
13041     void dropFrame(const ISDNFrame* frame, const char* reason = 0);
13042     // Send S frames other then UI frames
13043     bool sendUFrame(ISDNFrame::Type type, bool command, bool pf,
13044 	bool retrans = false);
13045     // Send U frames
13046     bool sendSFrame(ISDNFrame::Type type, bool command, bool pf);
13047     // Send a frame to remote peer
13048     // @param frame Frame to send
13049     // @return False if the operation failed
13050     bool sendFrame(const ISDNFrame* frame);
13051     // Send pending outgoing I frames
13052     // @param retrans: True   Send all transmission window
13053     //                 False  Send only the unsent frames in transmission window
13054     // @return True if a transmission took place
13055     bool sendOutgoingData(bool retrans = false);
13056     // Start/Stop T200. Stop/Start T203
13057     // If start is false reset N200 (retransmission counter)
13058     // @param start True to start. False to stop
13059     // @param t203 Start/don't start T203. Ignored if start is false
13060     // @param time Current time if known
13061     void timer(bool start, bool t203, u_int64_t time = 0);
13062 
13063     ISDNQ921Management* m_management;    // TEI management component
13064     // State variables
13065     bool m_remoteBusy;                   // Remote peer is busy: don't send any I frames
13066     bool m_timerRecovery;                // T200 expired
13067     bool m_rejectSent;                   // True if we've sent a REJ frame
13068     bool m_pendingDMSabme;               // True if we have a pending SABME on DM received
13069     bool m_lastPFBit;                    // Last P/F bit sent with an I or S frame
13070     u_int8_t m_vs;                       // Sequence number of the next transmitted I frame
13071     u_int8_t m_va;                       // Last ack'd I frame by remote peer
13072     u_int8_t m_vr;                       // Expected I frame sequence number
13073     // Timers and counters
13074     SignallingTimer m_retransTimer;      // T200: Retransmission interval
13075     SignallingTimer m_idleTimer;         // T203: Channel idle interval
13076     SignallingCounter m_window;          // Maximum/current number of pending outgoing I frames
13077     SignallingCounter m_n200;            // Maximum/current retransmission counter
13078     // Data
13079     ObjList m_outFrames;                 // Outgoing I frames queue
13080     // Statistics
13081     u_int32_t m_txFrames;                // The number of frames accepted by layer 1 to be transmitted
13082     u_int32_t m_txFailFrames;            // The number of frames not accepted by layer 1 to be transmitted
13083     u_int32_t m_rxFrames;                // The number of successfully parsed frames
13084     u_int32_t m_rxRejectedFrames;        // The number of rejected frames. Doesn't include dropped frames
13085     u_int32_t m_rxDroppedFrames;         // The number of dropped frames. Doesn't include rejected frames
13086     u_int32_t m_hwErrors;                // The number of hardware notifications
13087     // Debug flags
13088     bool m_printFrames;                  // Print frames to output
13089     bool m_extendedDebug;                // Extended debug flag
13090     // Flags used to avoid repetitive errors
13091     bool m_errorSend;                    // Send error
13092     bool m_errorReceive;                 // Receive error
13093 };
13094 
13095 /**
13096  * This class is intended to be used as a proxy between an ISDN Layer 3 and multiple
13097  *  Layer 2 objects sharing the same signalling interface.
13098  * It is used for BRI TEI management or PRI with D-channel backup.
13099  * It also keeps a list of ISDN Layer 2 object(s) used for the designated purpose
13100  * @short ISDN Layer 2 BRI TEI management or PRI with D-channel(s) backup
13101  */
13102 class YSIG_API ISDNQ921Management : public ISDNLayer2, public ISDNLayer3, public SignallingReceiver, public SignallingDumpable
13103 {
13104     YCLASS3(ISDNQ921Management,ISDNLayer2,ISDNLayer3,SignallingReceiver)
13105 public:
13106     /**
13107      * Constructor - initialize this Layer 2 and the component
13108      * @param params Layer's parameters
13109      * @param name Optional name of the component
13110      * @param net True if managing the network side of Q.921
13111      */
13112     ISDNQ921Management(const NamedList& params, const char* name = 0, bool net = true);
13113 
13114     /**
13115      * Destructor
13116      */
13117     virtual ~ISDNQ921Management();
13118 
13119     /**
13120      * Configure and initialize Q.921 Management and its children
13121      * @param config Optional configuration parameters override
13122      * @return True if Q.921 management was initialized properly
13123      */
13124     virtual bool initialize(const NamedList* config);
13125 
13126     /**
13127      * Set the engine for this management and all Layer 2 children
13128      * @param eng Pointer to the engine that will manage this mangement
13129      */
13130     virtual void engine(SignallingEngine* eng);
13131 
13132     /**
13133      * Implements Q.921 DL-ESTABLISH and DL-RELEASE request primitives
13134      * @param tei This layer TEI (-1 to apply it to all targets this object may have attached)
13135      * @param establish True to establish. False to release
13136      * @param force True to establish even if we already are established.
13137      * @return True if the request was accepted
13138      */
13139     virtual bool multipleFrame(u_int8_t tei, bool establish, bool force);
13140 
13141     /**
13142      * Implements Q.921 DL-DATA and DL-UNIT DATA request primitives
13143      * @param data Data to send
13144      * @param tei This layer TEI (-1 for broadcast)
13145      * @param ack True to send an acknowledged frame, false to send an unacknowledged one
13146      * @return True if the request was accepted
13147      */
13148     virtual bool sendData(const DataBlock& data, u_int8_t tei, bool ack);
13149 
13150     /**
13151      * Implements Q.921 send frame to the interface
13152      * @param frame The frame to be sent
13153      * @param q921 Pointer to the Q.921 that sends the frame, if any
13154      * @return True if the frame was sent
13155      */
13156     bool sendFrame(const ISDNFrame* frame, const ISDNQ921* q921 = 0);
13157 
13158 
13159     /**
13160      * Emergency release.
13161      * Cleanup all Layer 2 objects attached to this Management
13162      */
13163     virtual void cleanup();
13164 
13165     /**
13166      * Implements Q.921 DL-ESTABLISH indication/confirmation primitive:
13167      *  'multiple frame acknowledged' mode established
13168      * @param tei This layer TEI
13169      * @param confirm True if this is a confirmation of a previous request,
13170      *  false if it is an indication of state change on remote request
13171      * @param timeout True if the reason is a timeout
13172      * @param layer2 Pointer to the notifier
13173      */
13174     virtual void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
13175 
13176     /**
13177      * Implements Q.921 DL-RELEASE indication/confirmation primitive:
13178      *  'multiple frame acknowledged' mode released
13179      * @param tei This layer TEI
13180      * @param confirm True if this is a confirmation of a previous request,
13181      *  false if it is an indication of state change on remote request
13182      * @param timeout True if the reason is a timeout.
13183      * @param layer2 Pointer to the notifier
13184      */
13185     virtual void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
13186 
13187     /**
13188      * Notification from layer 2 of data link set/release command or response
13189      * Used for stateless layer 2
13190      * @param tei This layer TEI
13191      * @param cmd True if received a command, false if received a response
13192      * @param value The value of the notification
13193      * If 'cmd' is true (command), the value is true if a request to establish data link was received
13194      *   or false if received a request to release data link
13195      * If 'cmd' is false (response), the value is the response
13196      * @param layer2 Pointer to the notifier
13197      */
13198     virtual void dataLinkState(u_int8_t tei, bool cmd, bool value, ISDNLayer2* layer2);
13199 
13200     /**
13201      * Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
13202      * Receive data from an encapsulated Layer 2 and send it to the attached Layer 3
13203      * @param data Received data
13204      * @param tei The TEI as received in the packet
13205      * @param layer2 Pointer to the sender
13206      */
13207     virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2);
13208 
13209 protected:
13210     /**
13211      * Method called periodically to check timeouts
13212      * This method is thread safe
13213      * @param when Time to use as computing base for events and timeouts
13214      */
13215     virtual void timerTick(const Time& when);
13216 
13217     /**
13218      * Process a Signalling Packet received by the interface.
13219      * Parse the data and send all non-UI frames to the appropriate Layer 2.
13220      * Process UI frames
13221      * @return True if message was successfully processed
13222      */
13223     virtual bool receivedPacket(const DataBlock& packet);
13224 
13225     /**
13226      * Process a notification generated by the attached interface
13227      * @param event Notification event reported by the interface
13228      * @return True if notification was processed
13229      */
13230     virtual bool notify(SignallingInterface::Notification event);
13231 
13232     /**
13233      * Process UI frames carrying TEI management messages
13234      * @param frame The parsed frame
13235      * @return False if the frame is not a TEI management one, true otherwise
13236      */
13237     bool processTeiManagement(ISDNFrame* frame);
13238 
13239     /**
13240      * Send a TEI management frame
13241      * @param type Type of the frame to send
13242      * @param ri Reference number to send in frame
13243      * @param ai Action indicator to send in frame
13244      * @param tei The TEI to send the frame to, default use broadcast
13245      * @param pf The Poll/Final bit to set in the frame
13246      * @return True if frame was sent successfully
13247      */
13248     bool sendTeiManagement(ISDNFrame::TeiManagement type, u_int16_t ri, u_int8_t ai, u_int8_t tei = 127, bool pf = false);
13249 
13250     /**
13251      * Process TEI request message and send back to TE:
13252      *  TEI Assigned message if the request succeeded;
13253      *  TEI Denied message with the received reference number if the
13254      *   reference number is already in use;
13255      *  TEI Denied message with the reference number set to 127 if
13256      *   there is no TEI value available.
13257      * @param ri The reference number
13258      * @param ai Action indicator
13259      * @param pf The Poll/Final bit in the incoming frame
13260      */
13261     void processTeiRequest(u_int16_t ri, u_int8_t ai, bool pf);
13262 
13263     /**
13264      * Process Tei remove message removing the tei(s) contained by ai
13265      * @param ai Contains the TEI value to remove or 127 to remove all TEI values
13266      */
13267     void processTeiRemove(u_int8_t ai);
13268 
13269     /**
13270      * Process TEI Check Request message and send to the NET a message with
13271      *  the TEI and the asociated reference number
13272      * @param ai Contains the TEI value to check or 127 to check all TEI values
13273      * @param pf The Poll/Final bit in the incoming frame
13274      */
13275     void processTeiCheckRequest(u_int8_t ai, bool pf);
13276 
13277     /**
13278      * Process TEI Check Response message and set the check flag to true to know that we have a response for that TEI
13279      * @param ri The associated reference number to the ai
13280      * @param ai The TEI value as received in the answer
13281      */
13282     void processTeiCheckResponse(u_int16_t ri, u_int8_t ai);
13283 
13284     /**
13285      * Process TEI Assigned message
13286      * @param ri The reference number assigned to the ai
13287      * @param ai The TEI value assigned
13288      */
13289     void processTeiAssigned(u_int16_t ri, u_int8_t ai);
13290 
13291     /**
13292      * Process TEI Denied message
13293      * @param ri The reference number of the denied request
13294      */
13295     void processTeiDenied(u_int16_t ri);
13296 
13297     /**
13298      * Process TEI verify
13299      * @param ai The TEI value of the message initiator
13300      * @param pf The Poll/Final bit in the incoming frame
13301      */
13302     void processTeiVerify(u_int8_t ai, bool pf);
13303 
13304     /**
13305      * Send TEI request message
13306      * @param tei TEI value to assign
13307      */
13308     void sendTeiReq(u_int8_t tei);
13309 
13310     /**
13311      * Send a TEI remove frame
13312      */
13313     void sendTeiRemove();
13314 
13315 private:
13316     ISDNQ921* m_layer2[127];             // The list of Layer 2 objects attached to this Layer 3
13317     SignallingTimer m_teiManTimer;       // T202
13318     SignallingTimer m_teiTimer;          // T201
13319 };
13320 
13321 /**
13322  * Q.921 ISDN Layer 2 pasive (stateless) implementation on top of a hardware HDLC interface
13323  * @short Stateless pasive ISDN Q.921 implementation on top of a hardware interface
13324  */
13325 class YSIG_API ISDNQ921Passive : public ISDNLayer2, public SignallingReceiver, public SignallingDumpable
13326 {
13327     YCLASS2(ISDNQ921Passive,ISDNLayer2,SignallingReceiver)
13328 public:
13329     /**
13330      * Constructor
13331      * Initialize this object and the component
13332      * @param params Layer's and @ref TelEngine::ISDNLayer2 parameters
13333      * @param name Name of this component
13334      */
13335     ISDNQ921Passive(const NamedList& params, const char* name = 0);
13336 
13337     /**
13338      * Destructor
13339      */
13340     virtual ~ISDNQ921Passive();
13341 
13342     /**
13343      * Emergency release
13344      * Reset all data. Set state to 'Released'
13345      * This method is thread safe
13346      */
13347     virtual void cleanup();
13348 
13349     /**
13350      * Configure and initialize the passive Q.921 and its interface
13351      * @param config Optional configuration parameters override
13352      * @return True if Q.921 and the interface were initialized properly
13353      */
13354     virtual bool initialize(const NamedList* config);
13355 
13356     /**
13357      * Set debug data of this layer
13358      * @param printFrames Enable/disable frame printing on output
13359      * @param extendedDebug Enable/disable hex data dump if print frames is enabled
13360      */
setDebug(bool printFrames,bool extendedDebug)13361     inline void setDebug(bool printFrames, bool extendedDebug)
13362 	{ m_extendedDebug = ((m_printFrames = printFrames) && extendedDebug); }
13363 
13364 protected:
13365     /**
13366      * Detach links. Disposes memory
13367      */
destroyed()13368     virtual void destroyed()
13369     {
13370 	ISDNLayer2::attach(0);
13371 	TelEngine::destruct(SignallingReceiver::attach(0));
13372 	SignallingComponent::destroyed();
13373     }
13374 
13375     /**
13376      * Method called periodically to check timeouts
13377      * This method is thread safe
13378      * @param when Time to use as computing base for events and timeouts
13379      */
13380     virtual void timerTick(const Time& when);
13381 
13382     /**
13383      * Process a packet received by the receiver's interface
13384      * This method is thread safe
13385      * @param packet The received packet
13386      * @return True if message was successfully processed
13387      */
13388     virtual bool receivedPacket(const DataBlock& packet);
13389 
13390     /**
13391      * Process a notification generated by the attached interface
13392      * This method is thread safe
13393      * @param event Notification event reported by the interface
13394      * @return True if notification was processed
13395      */
13396     virtual bool notify(SignallingInterface::Notification event);
13397 
13398 private:
control(NamedList & params)13399     virtual bool control(NamedList& params)
13400 	{ return SignallingDumpable::control(params,this); }
13401     // Filter received frames. Accept only frames that would generate a notification to the upper layer:
13402     // UI/I, and Valid SABME/DISC/UA/DM
13403     // On success, if frame is not a data one, prepare cmd and value to notify layer 3
13404     bool acceptFrame(ISDNFrame* frame, bool& cmd, bool& value);
13405     // Show debug message. Count dropped frames
13406     bool dropFrame(const ISDNFrame* frame, const char* reason = 0);
13407 
13408     bool m_checkLinkSide;                // Check if this is the correct side of the data link
13409     SignallingTimer m_idleTimer;         // Channel idle interval
13410     u_int8_t m_lastFrame;                // Transmitter send number of the last received frame
13411     u_int32_t m_rxFrames;                // The number of successfully parsed frames
13412     u_int32_t m_rxDroppedFrames;         // The number of dropped frames. Doesn't include rejected frames
13413     u_int32_t m_hwErrors;                // The number of hardware notifications
13414     bool m_printFrames;                  // Print frames to output
13415     bool m_extendedDebug;                // Extended debug flag
13416     bool m_errorReceive;                 // Receive error
13417 };
13418 
13419 /**
13420  * The common client side of SIGTRAN ISDN Q.921 User Adaptation (RFC4233)
13421  * @short Client side of SIGTRAN ISDN Q.921 UA
13422  */
13423 class YSIG_API ISDNIUAClient : public SIGAdaptClient
13424 {
YCLASS(ISDNIUAClient,SIGAdaptClient)13425     YCLASS(ISDNIUAClient,SIGAdaptClient)
13426 public:
13427     /**
13428      * Contructor of an empty IUA client
13429      */
13430     inline ISDNIUAClient(const NamedList& params)
13431 	: SIGAdaptClient(params.safe("ISDNIUAClient"),&params,1,9900)
13432 	{ }
13433 
13434     virtual bool processMSG(unsigned char msgVersion, unsigned char msgClass,
13435 	unsigned char msgType, const DataBlock& msg, int streamId);
13436 };
13437 
13438 /**
13439  * RFC4233 ISDN Layer 2 implementation over SCTP/IP
13440  * IUA is intended to be used as a Provider-User where Q.921 runs on a
13441  *  Signalling Gateway and the user (Q.931) runs on an Application Server.
13442  * @short SIGTRAN ISDN Q.921 User Adaptation Layer
13443  */
13444 class YSIG_API ISDNIUA : public ISDNLayer2, public SIGAdaptUser
13445 {
13446     friend class ISDNIUAClient;
13447     YCLASS(ISDNIUA,ISDNLayer2)
13448 public:
13449     /**
13450      * Constructor
13451      * Initialize this object and the layer 2
13452      * @param params Object and Layer 2 parameters
13453      * @param name Optional name for Layer 2
13454      * @param tei Value of TEI for this component
13455      */
13456     ISDNIUA(const NamedList& params, const char* name = 0, u_int8_t tei = 0);
13457 
13458     /**
13459      * Destructor
13460      */
13461     virtual ~ISDNIUA();
13462 
13463     /**
13464      * Configure and initialize IUA and its transport
13465      * @param config Optional configuration parameters override
13466      * @return True if IUA and the transport were initialized properly
13467      */
13468     virtual bool initialize(const NamedList* config);
13469 
13470     /**
13471      * Implements Q.921 DL-ESTABLISH and DL-RELEASE request primitives
13472      * @param tei This layer's TEI
13473      * @param establish True to establish. False to release
13474      * @param force True to establish even if we already are in this mode. This
13475      *  parameter is ignored if establish is false
13476      * @return True if the request was accepted
13477      */
13478     virtual bool multipleFrame(u_int8_t tei, bool establish, bool force);
13479 
13480     /**
13481      * Implements Q.921 DL-DATA and DL-UNIT DATA request primitives
13482      * @param data Data to send
13483      * @param tei The TEI to send with the data frane
13484      * @param ack True to send an acknowledged frame, false to send an unacknowledged one
13485      * @return False if the request was not accepted or send operation failed
13486      */
13487     virtual bool sendData(const DataBlock& data, u_int8_t tei, bool ack);
13488 
13489     /**
13490      * Emergency release.
13491      */
13492     virtual void cleanup();
13493 
13494     /**
13495      * Traffic activity state change notification
13496      * @param active True if the ASP is active and traffic is allowed
13497      */
13498     virtual void activeChange(bool active);
13499 
13500     /**
13501      * Retrieve the numeric Interface Identifier (if any)
13502      * @return IID value, -1 if not set
13503      */
iid()13504     inline int32_t iid() const
13505 	{ return m_iid; }
13506 
13507 protected:
client()13508     ISDNIUAClient* client() const
13509 	{ return static_cast<ISDNIUAClient*>(adaptation()); }
13510     virtual bool processMGMT(unsigned char msgType, const DataBlock& msg, int streamId);
13511     virtual bool processQPTM(unsigned char msgType, const DataBlock& msg, int streamId);
13512     int32_t m_iid;
13513 };
13514 
13515 /**
13516  * Q.931 ISDN Layer 3 message Information Element
13517  * @short A Q.931 ISDN Layer 3 message Information Element
13518  */
13519 class YSIG_API ISDNQ931IE : public NamedList
13520 {
13521     friend class ISDNQ931Message;
13522 public:
13523     /**
13524      * Keep IE type enumerations. See Q.931 4.5
13525      */
13526     enum Type {
13527 	// Fixed (1 byte) length information element
13528 	Shift = 0x90,                    // Shift
13529 	MoreData = 0xa0,                 // More data
13530 	SendComplete = 0xa1,             // Sending complete
13531 	Congestion = 0xb0,               // Congestion level
13532 	Repeat = 0xd0,                   // Repeat indicator
13533 	// Variable length information element
13534 	Segmented = 0x00,                // Segmented message
13535 	BearerCaps = 0x04,               // Bearer capability
13536 	Cause = 0x08,                    // Cause
13537 	CallIdentity = 0x10,             // Call identity
13538 	CallState = 0x14,                // Call state
13539 	ChannelID = 0x18,                // Channel identification
13540 	Progress = 0x1e,                 // Progress indicator
13541 	NetFacility = 0x20,              // Network-specific facilities
13542 	Notification = 0x27,             // Notification indicator
13543 	Display = 0x28,                  // Display
13544 	DateTime = 0x29,                 // Date/time
13545 	Keypad = 0x2c,                   // Keypad facility
13546 	Signal = 0x34,                   // Signal
13547 	ConnectedNo = 0x4c,              // Connected number (Q.951)
13548 	CallingNo = 0x6c,                // Calling party number
13549 	CallingSubAddr = 0x6d,           // Calling party subaddress
13550 	CalledNo = 0x70,                 // Called party number
13551 	CalledSubAddr = 0x71,            // Called party subaddress
13552 	NetTransit = 0x78,               // Transit network selection
13553 	Restart = 0x79,                  // Restart indicator
13554 	LoLayerCompat = 0x7c,            // Low layer compatibility
13555 	HiLayerCompat = 0x7d,            // High layer compatibility
13556 	// Not used
13557 	UserUser = 0x7e,                 // User-user
13558 	Escape = 0x7f,                   // Escape for extension
13559     };
13560 
13561     /**
13562      * Constructor
13563      * Constructs an unknown IE with raw data
13564      * @param type The type of this IE
13565      */
13566     ISDNQ931IE(u_int16_t type);
13567 
13568     /**
13569      * Destructor
13570      */
13571     virtual ~ISDNQ931IE();
13572 
13573     /**
13574      * Get the type of this IE
13575      * @return The type of this IE
13576      */
type()13577     inline u_int8_t type() const
13578 	{ return (u_int8_t)m_type; }
13579 
13580     /**
13581      * Add a parameter using the IE name as prefix
13582      * @param name Parameter name
13583      * @param value Parameter value
13584      */
addParamPrefix(const char * name,const char * value)13585     inline void addParamPrefix(const char* name, const char* value)
13586 	{ addParam(*this+"."+name,value); }
13587 
13588     /**
13589      * Put this message into a string for debug purposes
13590      * @param dest The destination string
13591      * @param extendedDebug True to add the content of this IE and dump data.
13592      *  If false, only the IE name is added to the destination string
13593      * @param before Optional string to be added before
13594      */
13595     void toString(String& dest, bool extendedDebug, const char* before = 0);
13596 
13597     /**
13598      * Get the string associated with a given IE type
13599      * @param type The IE type whose string we want to get
13600      * @param defVal The value to return if not found
13601      * @return Pointer to the requested string or defValue
13602      */
13603     static inline const char* typeName(int type, const char* defVal = 0)
13604 	{ return lookup(type,s_type,defVal); }
13605 
13606     /**
13607      * Keep the string associated with IE types
13608      */
13609     static const TokenDict s_type[];
13610 
13611     /**
13612      * Internally used buffer
13613      */
13614     DataBlock m_buffer;
13615 
13616 private:
13617     u_int16_t m_type;                    // IE type
13618 };
13619 
13620 /**
13621  * Q.931 ISDN Layer 3 message
13622  * @short A Q.931 ISDN Layer 3 message
13623  */
13624 class YSIG_API ISDNQ931Message : public SignallingMessage
13625 {
13626 public:
13627     /**
13628      * Message type enumeration
13629      */
13630     enum Type {
13631 	Alerting = 0x01,                 // ALERTING
13632 	Proceeding = 0x02,               // CALL PROCEEDING
13633 	Connect = 0x07,                  // CONNECT
13634 	ConnectAck = 0x0f,               // CONNECT ACK
13635 	Progress = 0x03,                 // PROGRESS
13636 	Setup = 0x05,                    // SETUP
13637 	SetupAck = 0x0d,                 // SETUP ACK
13638 	Resume = 0x26,                   // RESUME
13639 	ResumeAck = 0x2e,                // RESUME ACK
13640 	ResumeRej = 0x22,                // RESUME REJECT
13641 	Suspend = 0x25,                  // SUSPEND
13642 	SuspendAck = 0x2d,               // SUSPEND ACK
13643 	SuspendRej = 0x21,               // SUSPEND REJECT
13644 	UserInfo = 0x20,                 // USER INFO
13645 	Disconnect = 0x45,               // DISCONNECT
13646 	Release = 0x4d,                  // RELEASE
13647 	ReleaseComplete = 0x5a,          // RELEASE COMPLETE
13648 	Restart = 0x46,                  // RESTART
13649 	RestartAck = 0x4e,               // RESTART ACK
13650 	Segment = 0x60,                  // SEGMENT
13651 	CongestionCtrl = 0x79,           // CONGESTION CONTROL
13652 	Info = 0x7b,                     // INFORMATION
13653 	Notify = 0x6e,                   // NOTIFY
13654 	Status = 0x7d,                   // STATUS
13655 	StatusEnquiry = 0x75,            // STATUS ENQUIRY
13656     };
13657 
13658     /**
13659      * Constructor
13660      * Constructs a message from given data. Used for incoming messages
13661      * @param type Message type
13662      * @param initiator The call initiator flag: True: this is the initiator
13663      * @param callRef The call reference
13664      * @param callRefLen The call reference length
13665      */
13666     ISDNQ931Message(Type type, bool initiator, u_int32_t callRef, u_int8_t callRefLen);
13667 
13668     /**
13669      * Constructor
13670      * Constructs a message with dummy call reference
13671      * @param type Message type
13672      */
13673     ISDNQ931Message(Type type);
13674 
13675     /**
13676      * Constructor
13677      * Constructs a message for a given call. Used for outgoing messages
13678      * @param type Message type
13679      * @param call The call this message belongs to
13680      */
13681     ISDNQ931Message(Type type, ISDNQ931Call* call);
13682 
13683     /**
13684      * Destructor
13685      */
13686     virtual ~ISDNQ931Message();
13687 
13688     /**
13689      * Get the type of this message
13690      * @return The type of this message as enumeration
13691      */
type()13692     inline Type type() const
13693 	{ return m_type; }
13694 
13695     /**
13696      * Check if the sender of this message is the call initiator
13697      * @return True if the sender of this message is the call initiator
13698      */
initiator()13699     inline bool initiator() const
13700 	{ return m_initiator; }
13701 
13702     /**
13703      * Get the id of the call this message belongs to
13704      * @return The call reference
13705      */
callRef()13706     inline u_int32_t callRef() const
13707 	{ return m_callRef; }
13708 
13709     /**
13710      * Get the length of the call reference
13711      * @return The length of the call reference
13712      */
callRefLen()13713     inline u_int8_t callRefLen() const
13714 	{ return m_callRefLen; }
13715 
13716     /**
13717      * Check if this message has a dummy call reference
13718      * @return True if this message has a dummy call reference
13719      */
dummyCallRef()13720     inline bool dummyCallRef() const
13721 	{ return m_dummy; }
13722 
13723     /**
13724      * Check if this message contains unknown mandatory IE(s)
13725      * @return True if this message contains unknown mandatory IE(s)
13726      */
unknownMandatory()13727     inline bool unknownMandatory() const
13728 	{ return m_unkMandatory; }
13729 
13730     /**
13731      * Set the unknown mandatory IE(s) flag
13732      */
setUnknownMandatory()13733     inline void setUnknownMandatory()
13734 	{ m_unkMandatory = true; }
13735 
13736     /**
13737      * Get the IE list of this message
13738      * @return A valid pointer to the list of this message's IEs
13739      */
ieList()13740     inline ObjList* ieList()
13741 	{ return &m_ie; }
13742 
13743     /**
13744      * Get a pointer to the first IE with the given type
13745      * @param type Requested IE's type
13746      * @param base Optional search starting element. If 0, search is started from the first IE following base
13747      * @return Pointer to the IE or 0 if not found
13748      */
13749     ISDNQ931IE* getIE(ISDNQ931IE::Type type, ISDNQ931IE* base = 0);
13750 
13751     /**
13752      * Remove an IE from list without destroying it
13753      * @param type Requested IE's type
13754      * @param base Optional search starting element. If 0, search is started from the first IE following base
13755      * @return Pointer to the IE or 0 if not found
13756      */
13757     ISDNQ931IE* removeIE(ISDNQ931IE::Type type, ISDNQ931IE* base = 0);
13758 
13759     /**
13760      * Get the value of a given parameter of a given IE
13761      * @param type Requested IE's type
13762      * @param param Requested IE's parameter. Set to 0 to use IE's name
13763      * @param defVal Default value to return if IE is missing or the parameter is missing
13764      * @return Pointer to the requested value or 0
13765      */
13766     inline const char* getIEValue(ISDNQ931IE::Type type, const char* param,
13767 	const char* defVal = 0)
13768     {
13769 	ISDNQ931IE* ie = getIE(type);
13770 	return (ie ? ie->getValue(param?param:ie->c_str(),defVal) : defVal);
13771     }
13772 
13773     /**
13774      * Append an IE with a given parameter
13775      * @param type IE's type
13776      * @param param IE's parameter. Set to 0 to use IE's name
13777      * @param value IE parameter's value
13778      * @return Pointer to the requested value or 0
13779      */
appendIEValue(ISDNQ931IE::Type type,const char * param,const char * value)13780     inline ISDNQ931IE* appendIEValue(ISDNQ931IE::Type type, const char* param,
13781 	const char* value)
13782     {
13783 	ISDNQ931IE* ie = new ISDNQ931IE(type);
13784 	ie->addParam(param?param:ie->c_str(),value);
13785 	appendSafe(ie);
13786 	return ie;
13787     }
13788 
13789     /**
13790      * Append an information element to this message
13791      * @param ie Information element to add
13792      * @return True if the IE was added or replaced, false if it was invalid
13793      */
append(ISDNQ931IE * ie)13794     inline bool append(ISDNQ931IE* ie)
13795 	{ return 0 != m_ie.append(ie); }
13796 
13797     /**
13798      * Append/insert an information element to this message. Check the IE list consistency
13799      * The given IE is 'consumed': deleted or appended to the list
13800      * @param ie Information element to add
13801      * @return True if the IE was added or replaced, false if it was invalid
13802      */
13803     bool appendSafe(ISDNQ931IE* ie);
13804 
13805     /**
13806      * Put this message into a string for debug purposes
13807      * @param dest The destination string
13808      * @param extendedDebug True to add the content of IEs and dump data.
13809      *  If false, only the IE name is added to the destination string
13810      * @param indent The line indent
13811      */
13812     void toString(String& dest, bool extendedDebug, const char* indent = 0) const;
13813 
13814     /**
13815      * Get a pointer to a data member or this message
13816      * @param name Object name
13817      * @return The requested pointer or 0 if not exists
13818      */
13819     virtual void* getObject(const String& name) const;
13820 
13821     /**
13822      * Encode this message
13823      * If message segmentation is allowed and the message is longer then maximum allowed,
13824      *  split it into Segment messages
13825      * @param parserData The parser settings
13826      * @param dest The destination list.
13827      *  If 1 is returned the list contains a DataBuffer with this message.
13828      *  If more then 1 is returned, the list is filled with data buffers with Segment messages
13829      * @return The number of segments on success or 0 on failure.
13830      */
13831     u_int8_t encode(ISDNQ931ParserData& parserData, ObjList& dest);
13832 
13833     /**
13834      * Parse received data
13835      * If the message type is Segment, decode only the header and the first IE
13836      *  If valid, fills the given buffer with the rest of the message. If segData is 0, drop the message.
13837      * @param parserData The parser settings
13838      * @param buffer The received data
13839      * @param segData Segment message data. If 0, received segmented messages will be dropped
13840      * @return Valid ISDNQ931Message pointer on success or 0
13841      */
13842     static ISDNQ931Message* parse(ISDNQ931ParserData& parserData,
13843 	const DataBlock& buffer, DataBlock* segData);
13844 
13845     /**
13846      * Get the string associated with a given message type
13847      * @param t The message type whose string we want to get
13848      * @return Pointer to the string associated with the given message type or 0
13849      */
typeName(int t)13850     static inline const char* typeName(int t)
13851 	{ return lookup(t,s_type,"Unknown"); }
13852 
13853     /**
13854      * Keep the string associated with message types
13855      */
13856     static const TokenDict s_type[];
13857 
13858     /**
13859      * Internally used buffer for debug purposes
13860      */
13861     DataBlock m_buffer;
13862 
13863 private:
13864     Type m_type;                         // Message type
13865     bool m_initiator;                    // The call initiator flag: True: this is the initiator
13866     u_int32_t m_callRef;                 // The call reference
13867     u_int8_t m_callRefLen;               // The call reference length
13868     bool m_unkMandatory;                 // True if this message contains unknown mandatory IE(s)
13869     bool m_dummy;                        // True if this message has a dummy call reference
13870     ObjList m_ie;                        // IE list
13871 };
13872 
13873 /**
13874  * Extract data from IEs. Append IEs to Q.931 messages
13875  * @short A Q.931 message IE data processor
13876  */
13877 class YSIG_API ISDNQ931IEData
13878 {
13879     friend class ISDNQ931Call;
13880     friend class ISDNQ931CallMonitor;
13881     friend class ISDNQ931;
13882     friend class ISDNQ931Monitor;
13883 private:
13884     // Constructor
13885     ISDNQ931IEData(bool bri = false);
13886     // Process received IEs
13887     // If add is true, append an IE to the message
13888     // If add is false, extract data from message. Set data to default values if IE is missing
13889     // @return False if the IE is missing when decoding or the IE wasn't added
13890     bool processBearerCaps(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13891     bool processCause(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13892     bool processDisplay(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13893     bool processKeypad(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13894     bool processChannelID(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13895     bool processProgress(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13896     bool processRestart(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13897     bool processNotification(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13898     bool processCalledNo(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13899     bool processCallingNo(ISDNQ931Message* msg, bool add, ISDNQ931ParserData* data = 0);
13900 
13901     // IE parameters
13902     String m_display;                    // Display: The data
13903     String m_callerNo;                   // CallingNo: Number
13904     String m_callerType;                 // CallingNo: Number type
13905     String m_callerPlan;                 // CallingNo: Number plan
13906     String m_callerPres;                 // CallingNo: Number presentation
13907     String m_callerScreening;            // CallingNo: Number screening
13908     String m_calledNo;                   // CalledNo: Number
13909     String m_calledType;                 // CalledNo: Number type
13910     String m_calledPlan;                 // CalledNo: Number plan
13911     String m_transferCapability;         // BearerCaps: Transfer capability
13912     String m_transferMode;               // BearerCaps: Transfer mode
13913     String m_transferRate;               // BearerCaps: Transfer rate
13914     String m_format;                     // BearerCaps: Layer 1 protocol
13915     String m_reason;                     // Cause
13916     String m_keypad;                     // Keypad: 'keypad' parameter
13917     String m_progress;                   // Progress: Progress description
13918     String m_notification;               // Notify: Notification indicator
13919     bool m_bri;                          // ChannelID: BRI interface flag
13920     bool m_channelMandatory;             // ChannelID: Indicated channel is mandatory/preferred
13921     bool m_channelByNumber;              // ChannelID: m_channels contains a channel list or a slot map
13922     String m_channelType;                // ChannelID: Channel type
13923     String m_channelSelect;              // ChannelID: Channel select
13924     String m_channels;                   // ChannelID: Channel list or slot map
13925     String m_restart;                    // Restart: The class of restarting circuits
13926 };
13927 
13928 /**
13929  * Q.931 ISDN call and call controller state
13930  * @short Q.931 ISDN call and call controller state
13931  */
13932 class YSIG_API ISDNQ931State
13933 {
13934 public:
13935     /**
13936      * Call and call controller state enumeration values
13937      */
13938     enum State {
13939 	// Common state
13940 	Null                    = 0x00,  // Null
13941 	// Call states
13942 	CallInitiated           = 0x01,  // Call initiated: sent SETUP
13943 	OverlapSend             = 0x02,  // Overlap sending
13944 	OutgoingProceeding      = 0x03,  // Outgoing call proceeding: received valid CALL PROCEEDING
13945 	CallDelivered           = 0x04,  // Call delivered: received valid ALERTING
13946 	CallPresent             = 0x06,  // Call present: received valid SETUP or recover from STATUS
13947 	CallReceived            = 0x07,  // Call received: sent ALERTING or recover from STATUS
13948 	ConnectReq              = 0x08,  // Connect request: sent/received valid CONNECT or recover from STATUS
13949 	IncomingProceeding      = 0x09,  // Incoming call proceeding: sent CALL PROCEEDING or recover from STATUS
13950 	Active                  = 0x0a,  // Active: sent/received valid CONNECT ACK
13951 	DisconnectReq           = 0x0b,  // Disconnect request: sent DISCONNECT
13952 	DisconnectIndication    = 0x0c,  // Disconnect indication: received valid DISCONNECT
13953 	SuspendReq              = 0x0f,  // Suspend request
13954 	ResumeReq               = 0x11,  // Resume reques
13955 	ReleaseReq              = 0x13,  // Release request: sent/received valid RELEASE
13956 	CallAbort               = 0x16,  // Call abort: received STATUS in Null state with remote not in Null state
13957 	OverlapRecv             = 0x19,  // Overlap receiving
13958 	// Call controller states
13959 	RestartReq              = 0x3d,  // Restart request
13960 	Restart                 = 0x3e,  // Restart
13961     };
13962 
13963     /**
13964      * Constructor
13965      */
ISDNQ931State()13966    inline ISDNQ931State() : m_state(Null)
13967 	{ }
13968 
13969     /**
13970      * Get the state
13971      * @return The state as enumeration
13972      */
state()13973     inline State state() const
13974 	{ return m_state; }
13975 
13976     /**
13977      * Get the text associated with a given state value
13978      * @param s The requested state value
13979      * @return The text associated with the given state value or 0
13980      */
stateName(u_int8_t s)13981     static const char* stateName(u_int8_t s)
13982 	{ return lookup(s,s_states,0); }
13983 
13984     /**
13985      * Keep the association between state values and their texts
13986      */
13987     static const TokenDict s_states[];
13988 
13989 protected:
13990     /**
13991      * Check if a received message type is valid in the current call state
13992      * @param type The type of the received message
13993      * @param retrans Optional flag to set on failure if the message is a retransmission
13994      * @return False if the message is not valid in the current call state
13995      */
13996     bool checkStateRecv(int type, bool* retrans);
13997 
13998     /**
13999      * Check if a message is allowed to be sent in the current call state
14000      * @param type The type of the received message
14001      * @return False if the message is not valid in the current call state
14002      */
14003     bool checkStateSend(int type);
14004 
14005     /**
14006      * The call and call controller state
14007      */
14008     State m_state;
14009 
14010 };
14011 
14012 /**
14013  * Q.931 ISDN call
14014  * @short A Q.931 ISDN call
14015  */
14016 class YSIG_API ISDNQ931Call : public ISDNQ931State, public SignallingCall
14017 {
14018     friend class ISDNQ931;
14019 public:
14020     /**
14021      * Destructor
14022      */
14023     virtual ~ISDNQ931Call();
14024 
14025     /**
14026      * Get the id of this call
14027      * @return The call reference
14028      */
callRef()14029     inline u_int32_t callRef() const
14030 	{ return m_callRef; }
14031 
14032     /**
14033      * Get the length of the call reference
14034      * @return The length of the call reference
14035      */
callRefLen()14036     inline u_int32_t callRefLen() const
14037 	{ return m_callRefLen; }
14038 
14039     /**
14040      * Get the Terminal Equipment Indicator for this call
14041      * @return Value of TEI used in this call
14042      */
callTei()14043     inline u_int8_t callTei() const
14044 	{ return m_tei; }
14045 
14046     /**
14047      * Get the circuit this call had reserved
14048      * @return The circuit reserved by this call
14049      */
circuit()14050     inline SignallingCircuit* circuit()
14051 	{ return m_circuit; }
14052 
14053     /**
14054      * Set termination (and destroy) flags
14055      * This method is thread safe
14056      * @param destroy The destroy flag. If true, the call will be destroyed
14057      * @param reason Terminate reason
14058      */
14059     void setTerminate(bool destroy, const char* reason);
14060 
14061     /**
14062      * Send an event to this call
14063      * This method is thread safe
14064      * @param event The sent event
14065      * @return True if the operation succedded
14066      */
14067     virtual bool sendEvent(SignallingEvent* event);
14068 
14069     /**
14070      * Get an event from this call
14071      * This method is thread safe
14072      * @param when The current time
14073      * @return SignallingEvent pointer or 0 if no events
14074      */
14075     virtual SignallingEvent* getEvent(const Time& when);
14076 
14077     /**
14078      * Data link (interface) state notification
14079      * This method is thread safe
14080      * @param up The data link state
14081      */
14082     void dataLinkState(bool up);
14083 
14084     /**
14085      * Get a pointer to a data member or this call
14086      * @param name Object name
14087      * @return The requested pointer or 0 if not exists
14088      */
14089     virtual void* getObject(const String& name) const;
14090 
14091 protected:
14092     /**
14093      * Constructor
14094      * @param controller The call controller
14095      * @param outgoing The call direction
14096      * @param callRef The call reference
14097      * @param callRefLen The call reference length in bytes
14098      * @param tei The Terminal Equipment Identifier used in this call
14099      */
14100     ISDNQ931Call(ISDNQ931* controller, bool outgoing, u_int32_t callRef,
14101 	u_int8_t callRefLen, u_int8_t tei = 0);
14102 
14103     /**
14104      * Send RELEASE COMPLETE if not in Null state.
14105      * Clear all call data.
14106      * Remove from controller's queue. Decrease the object's refence count
14107      * @param reason Optional release reason. If missing, the last reason is used
14108      * @param diag Optional hexified string for the cause diagnostic
14109      * @return Pointer to an SignallingEvent of type Release, with no message
14110      */
14111     SignallingEvent* releaseComplete(const char* reason = 0, const char* diag = 0);
14112 
14113     /**
14114      * Get an event from the circuit reserved for this call
14115      * @param when The current time
14116      * @return SignallingEvent pointer or 0 if no events
14117      */
14118     SignallingEvent* getCircuitEvent(const Time& when);
14119 
14120 private:
14121     // Reserve and connect a circuit. Change the reserved one if it must to
14122     bool reserveCircuit();
14123     // Process call when terminate flag is set. Check timeout
14124     // @param msg Optional message extracted from queue
14125     SignallingEvent* processTerminate(ISDNQ931Message* msg = 0);
14126     // Check timer(s)
14127     SignallingEvent* checkTimeout(u_int64_t time);
14128     // Check received messages for valid state
14129     // True to send status if not accepted
14130     bool checkMsgRecv(ISDNQ931Message* msg, bool status);
14131     // Process received messages
14132     // @param msg Valid ISDNQ931Message pointer
14133     SignallingEvent* processMsgAlerting(ISDNQ931Message* msg);
14134     SignallingEvent* processMsgCallProceeding(ISDNQ931Message* msg);
14135     SignallingEvent* processMsgConnect(ISDNQ931Message* msg);
14136     SignallingEvent* processMsgConnectAck(ISDNQ931Message* msg);
14137     SignallingEvent* processMsgDisconnect(ISDNQ931Message* msg);
14138     SignallingEvent* processMsgInfo(ISDNQ931Message* msg);
14139     SignallingEvent* processMsgNotify(ISDNQ931Message* msg);
14140     SignallingEvent* processMsgProgress(ISDNQ931Message* msg);
14141     SignallingEvent* processMsgRelease(ISDNQ931Message* msg);
14142     SignallingEvent* processMsgSetup(ISDNQ931Message* msg);
14143     SignallingEvent* processMsgSetupAck(ISDNQ931Message* msg);
14144     SignallingEvent* processMsgStatus(ISDNQ931Message* msg);
14145     SignallingEvent* processMsgStatusEnquiry(ISDNQ931Message* msg);
14146     // Send message
14147     // @param msg Pointer to SignallingMessage with parameters
14148     bool sendAlerting(SignallingMessage* sigMsg);
14149     bool sendCallProceeding(SignallingMessage* sigMsg);
14150     bool sendConnect(SignallingMessage* sigMsg);
14151     bool sendConnectAck(SignallingMessage* sigMsg);
14152     bool sendDisconnect(SignallingMessage* sigMsg);
14153     bool sendInfo(SignallingMessage* sigMsg);
14154     bool sendProgress(SignallingMessage* sigMsg);
14155     bool sendRelease(const char* reason = 0, SignallingMessage* sigMsg = 0);
14156     bool sendReleaseComplete(const char* reason = 0, const char* diag = 0, u_int8_t tei = 0);
14157     bool sendSetup(SignallingMessage* sigMsg);
14158     bool sendSuspendRej(const char* reason = 0, SignallingMessage* sigMsg = 0);
14159     bool sendSetupAck();
14160     // Errors on processing received messages
14161     // Missing mandatory IE
14162     // @param release True to send release complete and generate a release event
14163     SignallingEvent* errorNoIE(ISDNQ931Message* msg, ISDNQ931IE::Type type, bool release);
14164     SignallingEvent* errorWrongIE(ISDNQ931Message* msg, ISDNQ931IE::Type type, bool release);
14165     // Change call state
14166     void changeState(State newState);
14167     // Remove the call from controller's list
14168     void removeFromController();
14169     // Get the Q931 call controller
14170     inline ISDNQ931* q931();
14171 
14172     // Call data
14173     u_int32_t m_callRef;                 // Call reference
14174     u_int32_t m_callRefLen;              // Call reference length
14175     u_int8_t m_tei;                      // TEI used for the call
14176     SignallingCircuit* m_circuit;        // Circuit reserved for this call
14177     bool m_circuitChange;                // True if circuit changed
14178     bool m_channelIDSent;                // Incoming calls: ChannelID IE already sent
14179     bool m_rspBearerCaps;                // Incoming calls: Send BearerCaps IE in the first response
14180     bool m_inbandAvailable;              // Inband data is available
14181     bool m_net;                          // Flag indicating call is sent by a NT
14182     ISDNQ931IEData m_data;               // Data to process IEs
14183     ObjList m_inMsg;                     // Incoming message queue
14184     bool m_broadcast[127];               // TEIs that answered to PTMP SETUP
14185     // Timers
14186     SignallingTimer m_discTimer;         // T305: sending DISCONNECT
14187     SignallingTimer m_relTimer;          // T308: sending RELEASE
14188     SignallingTimer m_conTimer;          // T313: sending CONNECT
14189     SignallingTimer m_overlapSendTimer;  // T302 for overlapped sending
14190     SignallingTimer m_overlapRecvTimer;  // T304
14191     SignallingTimer m_retransSetupTimer; // T302 for setup retransmission (PTMP)
14192     // Termination
14193     bool m_terminate;                    // Terminate flag: send RELEASE
14194     bool m_destroy;                      // Destroy flag: call releaseComplete()
14195     bool m_destroyed;                    // Call destroyed flag
14196 };
14197 
14198 /**
14199  * Q.931 ISDN call monitor
14200  * @short A Q.931 ISDN call monitor
14201  */
14202 class YSIG_API ISDNQ931CallMonitor : public ISDNQ931State, public SignallingCall
14203 {
14204     friend class ISDNQ931Monitor;
14205 public:
14206     /**
14207      * Destructor
14208      */
14209     virtual ~ISDNQ931CallMonitor();
14210 
14211     /**
14212      * Check if the initiator is from the network side of the data link
14213      * @return True if the initiator is from the network side of the data link, false if it is from the user side
14214      */
netInit()14215     inline bool netInit() const
14216 	{ return m_netInit; }
14217 
14218     /**
14219      * Get an event from this call
14220      * This method is thread safe
14221      * @param when The current time
14222      * @return SignallingEvent pointer or 0 if no events
14223      */
14224     virtual SignallingEvent* getEvent(const Time& when);
14225 
14226     /**
14227      * Set termination flag
14228      * This method is thread safe
14229      * @param reason Terminate reason
14230      */
14231     void setTerminate(const char* reason);
14232 
14233     /**
14234      * Get a pointer to a data member or this call
14235      * @param name Object name
14236      * @return The requested pointer or 0 if not exists
14237      */
14238     virtual void* getObject(const String& name) const;
14239 
14240 protected:
14241     /**
14242      * Constructor
14243      * @param controller The call controller
14244      * @param callRef The call reference
14245      * @param netInit True if the initiator is from the network side of the link
14246      */
14247     ISDNQ931CallMonitor(ISDNQ931Monitor* controller, u_int32_t callRef, bool netInit);
14248 
14249     /**
14250      * Clear all call data
14251      * Remove from controller's queue. Decrease the object's refence count
14252      * @param reason Optional release reason. If missing, the last reason is used
14253      * @return Pointer to an SignallingEvent of type Release
14254      */
14255     SignallingEvent* releaseComplete(const char* reason = 0);
14256 
14257 private:
14258     // Get an event from one of the reserved circuits
14259     SignallingEvent* getCircuitEvent(const Time& when);
14260     // Process received setup message
14261     SignallingEvent* processMsgSetup(ISDNQ931Message* msg);
14262     // Process received responses to setup message (Proceeding, Alerting, Connect)
14263     SignallingEvent* processMsgResponse(ISDNQ931Message* msg);
14264     // Process termination messages (Disconnect, Release, Release Complete)
14265     SignallingEvent* processMsgTerminate(ISDNQ931Message* msg);
14266     // Process INFORMATION messages to get tones
14267     SignallingEvent* processMsgInfo(ISDNQ931Message* msg);
14268     // Reserve/release the circuits
14269     bool reserveCircuit();
14270     void releaseCircuit();
14271     // Connect the caller's or called's circuit
14272     bool connectCircuit(bool caller);
14273     // Change call state
14274     void changeState(State newState);
14275     // Remove the call from controller's list
14276     void removeFromController();
14277     // Get the Q931Monitor call controller
14278     inline ISDNQ931Monitor* q931();
14279 
14280     u_int32_t m_callRef;                 // Call reference
14281     SignallingCircuit* m_callerCircuit;  // Circuit reserved for caller
14282     SignallingCircuit* m_calledCircuit;  // Circuit reserved for called
14283     SignallingCircuit* m_eventCircuit;   // Last circuit that generated an event
14284     bool m_netInit;                      // The call initiator is from the network side of the link
14285     bool m_circuitChange;                // True if circuit changed
14286     ISDNQ931IEData m_data;               // Data to process IEs
14287     bool m_terminate;                    // Terminate flag
14288     String m_terminator;                 // The name of the entity that terminated the call
14289     ObjList m_inMsg;                     // Incoming messages queue
14290 };
14291 
14292 /**
14293  * This class holds Q.931 parser settings used to encode/decode Q.931 messages
14294  * @short Q.931 message parser data
14295  */
14296 class YSIG_API ISDNQ931ParserData
14297 {
14298 public:
14299     /**
14300      * Constructor
14301      * @param params Parser settings
14302      * @param dbg The debug enabler used for output
14303      */
14304     ISDNQ931ParserData(const NamedList& params, DebugEnabler* dbg = 0);
14305 
14306     /**
14307      * Check the state of a flag
14308      * @param mask The flag to check
14309      * @return True if the given flag is set
14310      */
flag(int mask)14311     inline bool flag(int mask) const
14312 	{ return (0 != (m_flags & mask)); }
14313 
14314     DebugEnabler* m_dbg;                 // The debug enabler used for output
14315     u_int32_t m_maxMsgLen;               // Maximum length of outgoing messages (or message segments)
14316     int m_flags;                         // The current behaviour flags
14317     int m_flagsOrig;                     // The original behaviour flags
14318     u_int8_t m_maxDisplay;               // Max Display IE size
14319     bool m_allowSegment;                 // True if message segmentation is allowed
14320     u_int8_t m_maxSegments;              // Maximum allowed segments for outgoing messages
14321     bool m_extendedDebug;                // True to fill message/IE buffer
14322 };
14323 
14324 /**
14325  * Q.931 ISDN Layer 3 implementation on top of a Layer 2
14326  * @short ISDN Q.931 implementation on top of Q.921
14327  */
14328 class YSIG_API ISDNQ931 : public SignallingCallControl, public SignallingDumpable, public ISDNLayer3
14329 {
YCLASS(ISDNQ931,ISDNLayer3)14330     YCLASS(ISDNQ931,ISDNLayer3)
14331     friend class ISDNQ931Call;
14332 public:
14333     /**
14334      * Enumeration flags defining the behaviour of the ISDN call controller and
14335      *  any active calls managed by it
14336      */
14337     enum BehaviourFlags {
14338 	// Append the progress indicator 'non-isdn-source' if present when
14339 	// sending SETUP. If this flag is not set, the indicator will be
14340 	// removed from the message
14341 	SendNonIsdnSource = 0x00000001,
14342 	// Ignore (don't send) the progress indicator 'non-isdn-destination'
14343 	// if present when sending SETUP ACKNOWLEDGE or CONNECT
14344 	IgnoreNonIsdnDest = 0x00000002,
14345 	// Always set presentation='allowed' and screening='network-provided'
14346 	// for Calling Party Number IE
14347 	ForcePresNetProv = 0x00000004,
14348 	// Translate '3.1khz-audio' transfer capability code 0x10 to/from 0x08
14349 	Translate31kAudio = 0x00000008,
14350 	// Send only transfer mode and rate when sending the Bearer Capability IE
14351 	// with transfer capability 'udi' or 'rdi' (unrestricted/restricted
14352 	// digital information)
14353 	URDITransferCapsOnly = 0x00000010,
14354 	// Don't send Layer 1 capabilities (data format) with the
14355 	// Bearer Capability IE when in circuit switch mode
14356 	NoLayer1Caps = 0x00000020,
14357 	// Don't parse incoming IEs found after a temporary (non-locking) shift
14358 	IgnoreNonLockedIE = 0x00000040,
14359 	// Don't send the Display IE
14360 	// This flag is internally set for EuroIsdnE1 type when the call
14361 	// controller is the CPE side of the link
14362 	NoDisplayIE = 0x00000080,
14363 	// Don't append a charset byte 0xb1 before Display data
14364 	NoDisplayCharset = 0x00000100,
14365 	// Send a Sending Complete IE even if no overlap dialing
14366 	ForceSendComplete = 0x00000200,
14367 	// Don't change call state to Active instead of ConnectRequest after
14368 	// sending CONNECT. This flag is internally set when the call
14369 	// controller is the CPE side of the data link
14370 	NoActiveOnConnect = 0x00000400,
14371 	// Check the validity of the notification indicator when sending a NOTIFY message
14372 	CheckNotifyInd = 0x00000800,
14373 	// Request an outbound PRI channel to be exclusive
14374 	ChannelExclusive = 0x00001000,
14375     };
14376 
14377     /**
14378      * Call controller switch type. Each value is a mask of behaviour flags
14379      */
14380     enum SwitchType {
14381 	Unknown      = 0,
14382 	// Standard Euro ISDN (CTR4, ETSI 300-102)
14383 	EuroIsdnE1   = ForceSendComplete|CheckNotifyInd|NoDisplayCharset|URDITransferCapsOnly,
14384 	// T1 Euro ISDN variant (ETSI 300-102)
14385 	EuroIsdnT1   = ForceSendComplete|CheckNotifyInd,
14386 	// National ISDN
14387 	NationalIsdn = SendNonIsdnSource,
14388 	// DMS 100
14389 	Dms100       = ForcePresNetProv|IgnoreNonIsdnDest,
14390 	// Lucent 5E
14391 	Lucent5e     = IgnoreNonLockedIE,
14392 	// AT&T 4ESS
14393 	Att4ess      = ForcePresNetProv|IgnoreNonLockedIE|Translate31kAudio|NoLayer1Caps,
14394 	// QSIG Switch
14395 	QSIG         = NoActiveOnConnect|NoDisplayIE|NoDisplayCharset
14396     };
14397 
14398     /**
14399      * Constructor
14400      * Initialize this object and the component
14401      * @param params Layer's parameters and parser settings
14402      * @param name Name of this component
14403      */
14404     ISDNQ931(const NamedList& params, const char* name = 0);
14405 
14406     /**
14407      * Destructor
14408      * Destroy all calls
14409      */
14410     virtual ~ISDNQ931();
14411 
14412     /**
14413      * Configure and initialize Q.931 and its layer 2
14414      * @param config Optional configuration parameters override
14415      * @return True if Q.931 and the layer 2 were initialized properly
14416      */
14417     virtual bool initialize(const NamedList* config);
14418 
14419     /**
14420      * Get the controller's status as text
14421      * @return Controller status name
14422      */
14423     virtual const char* statusName() const;
14424 
14425     /**
14426      * Get the layer 2 attached to this object
14427      * @return Pointer to the layer 2 attached to this object or 0 if none
14428      */
layer2()14429     inline const ISDNLayer2* layer2() const
14430 	{ return m_q921; }
14431 
14432     /**
14433      * Check if this call controller supports primary or basic rate transfer
14434      * @return True for primary rate. False for basic rate
14435      */
primaryRate()14436     inline bool primaryRate() const
14437 	{ return m_primaryRate; }
14438 
14439     /**
14440      * Chech if this call controller is at the NET or CPE side of the link
14441      * @return True if we are NET, false if we are CPE
14442      */
network()14443     inline bool network() const
14444 	{ return m_q921 ? m_q921->network() : m_networkHint; }
14445 
14446     /**
14447      * Check if this call controller supports circuit switch or packet mode transfer
14448      * @return True for circuit switch. False for packet mode
14449      */
transferModeCircuit()14450     inline bool transferModeCircuit() const
14451 	{ return m_transferModeCircuit; }
14452 
14453     /**
14454      * Get the parser settings of this call control
14455      * @return The parser settings
14456      */
parserData()14457     inline ISDNQ931ParserData& parserData()
14458 	{ return m_parserData; }
14459 
14460     /**
14461      * Get the default numbering plan for outgoing calls
14462      * @return The default numbering plan for outgoing calls
14463      */
numPlan()14464     inline const String& numPlan() const
14465 	{ return m_numPlan; }
14466 
14467     /**
14468      * Get the default number type for outgoing calls
14469      * @return The default number type for outgoing calls
14470      */
numType()14471     inline const String& numType() const
14472 	{ return m_numType; }
14473 
14474     /**
14475      * Get the default number presentation for outgoing calls
14476      * @return The default number presentation for outgoing calls
14477      */
numPresentation()14478     inline const String& numPresentation() const
14479 	{ return m_numPresentation; }
14480 
14481     /**
14482      * Get the default number screening for outgoing calls
14483      * @return The default number screening for outgoing calls
14484      */
numScreening()14485     inline const String& numScreening() const
14486 	{ return m_numScreening; }
14487 
14488     /**
14489      * Get the default data format for outgoing calls
14490      * @return The default data format for outgoing calls
14491      */
format()14492     inline const String& format() const
14493 	{ return m_format; }
14494 
14495     /**
14496      * Send a message
14497      * @param msg The message to be sent
14498      * @param tei TEI value to use at Layer 2
14499      * @param reason Optional string to write the failure reason
14500      * @return False if the message is invalid, Layer 2 is missing or refused the data
14501      */
14502     bool sendMessage(ISDNQ931Message* msg, u_int8_t tei, String* reason = 0);
14503 
14504     /**
14505      * Notification of Layer 2 up state
14506      * @param tei TEI received by the Layer 2
14507      * @param confirm True if this is a confirmation of a previous request.
14508      *  False if it is an indication of state change on remote request
14509      * @param timeout True if the reason is a timeout.
14510      * @param layer2 Pointer to the notifier
14511      */
14512     virtual void multipleFrameEstablished(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
14513 
14514     /**
14515      * Notification of Layer 2 down state
14516      * @param tei TEI received by the Layer 2
14517      * @param confirm True if this is a confirmation of a previous request.
14518      *  False if it is an indication of state change on remote request
14519      * @param timeout True if the reason is a timeout.
14520      * @param layer2 Pointer to the notifier
14521      */
14522     virtual void multipleFrameReleased(u_int8_t tei, bool confirm, bool timeout, ISDNLayer2* layer2);
14523 
14524     /**
14525      * Receive data from Layer 2
14526      * @param data Received data
14527      * @param tei TEI received by the Layer 2
14528      * @param layer2 Pointer to the sender Layer 2
14529      */
14530     virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2);
14531 
14532     /**
14533      * Attach an ISDN Q.921 transport
14534      * This method is thread safe
14535      * @param q921 Pointer to the Q.921 transport to attach
14536      * @return Pointer to the detached Layer 2 or NULL
14537      */
14538     virtual ISDNLayer2* attach(ISDNLayer2* q921);
14539 
14540     /**
14541      * Create an outgoing call. Send a NewCall event with the given msg parameter
14542      * @param msg Call parameters
14543      * @param reason Failure reason if any
14544      * @return Referenced SignallingCall pointer on success or 0 on failure
14545      */
14546     SignallingCall* call(SignallingMessage* msg, String& reason);
14547 
14548     /**
14549      * Restart one or more the circuits
14550      * @param circuits Comma separated list of circuits to be restarted
14551      * @return True if the procedure was successfully started or enqueued
14552      */
14553     bool restart(const char* circuits);
14554 
14555     /**
14556      * Send a STATUS message for a given call
14557      * @param call The call requesting the operation
14558      * @param tei The TEI to send with the STATUS message
14559      * @param cause Value for Cause IE
14560      * @param display Optional value for Display IE
14561      * @param diagnostic Optional value for cause diagnostic value
14562      * @return The result of the operation (true if successfully sent)
14563      */
14564     inline bool sendStatus(ISDNQ931Call* call, const char* cause, u_int8_t tei = 0,
14565 	const char* display = 0, const char* diagnostic = 0)
14566     {
14567 	return call && sendStatus(cause,call->callRefLen(),call->callRef(),tei,
14568 	    call->outgoing(),call->state(),display,diagnostic);
14569     }
14570 
14571     /**
14572      * Send a RELEASE or RELEASE COMPLETE message for a given call
14573      * @param call The call requesting the operation
14574      * @param release True to send RELEASE, false to send RELEASE COMPLETE
14575      * @param cause Value for Cause IE
14576      * @param tei TEI to which the release is sent to
14577      * @param diag Optional hexified string for cause dignostic
14578      * @param display Optional value for Display IE
14579      * @param signal Optional value for Signal IE
14580      * @return The result of the operation (true if successfully sent)
14581      */
14582     inline bool sendRelease(ISDNQ931Call* call, bool release, const char* cause, u_int8_t tei = 0,
14583 	const char* diag = 0, const char* display = 0, const char* signal = 0)
14584     {
14585 	return call && sendRelease(release,call->callRefLen(),call->callRef(),tei,
14586 	    call->outgoing(),cause,diag,display,signal);
14587     }
14588 
14589     /**
14590      * Set terminate to all calls
14591      * This method is thread safe
14592      * @param reason Cleanup reason
14593      */
14594     virtual void cleanup(const char* reason = "offline");
14595 
14596     /**
14597      * Set the timeout interval for a given timer if implemented
14598      * If the timer is not implemented the interval is set to 0
14599      * @param timer The destination timer
14600      * @param id The timer number as defined in Q.931
14601      */
14602     void setInterval(SignallingTimer& timer, int id);
14603 
14604     /**
14605      * Manage timeout for the call setup message
14606      */
14607     void manageTimeout();
14608 
14609     /**
14610      * Set debug data of this call controller
14611      * @param printMsg Enable/disable message printing on output
14612      * @param extendedDebug Enable/disable hex data dump if print messages is enabled
14613      */
setDebug(bool printMsg,bool extendedDebug)14614     inline void setDebug(bool printMsg, bool extendedDebug)
14615 	{ m_parserData.m_extendedDebug = m_extendedDebug =
14616 	    ((m_printMsg = printMsg) && extendedDebug); }
14617 
14618     /**
14619      * The list of behaviour flag names
14620      */
14621     static const TokenDict s_flags[];
14622 
14623      /**
14624      * The list of switch type names
14625      */
14626     static const TokenDict s_swType[];
14627 
14628 protected:
14629     /**
14630      * Detach links. Disposes memory
14631      */
destroyed()14632     virtual void destroyed()
14633     {
14634 	TelEngine::destruct(attach(0));
14635 	TelEngine::destruct(SignallingCallControl::attach(0));
14636 	ISDNLayer3::destroyed();
14637     }
14638 
14639     /**
14640      * Method called periodically to check timeouts
14641      * This method is thread safe
14642      * @param when Time to use as computing base for events and timeouts
14643      */
14644     virtual void timerTick(const Time& when);
14645 
14646     /**
14647      * Find a call given its call reference and direction
14648      * @param callRef The call reference to find
14649      * @param outgoing True to find an outgoing call, false to find an incoming one
14650      * @param tei TEI of the layer associated to the call to find
14651      * @return A referenced pointer to a call or 0
14652      */
14653     ISDNQ931Call* findCall(u_int32_t callRef, bool outgoing, u_int8_t tei = 0);
14654 
14655     /**
14656      * Find a call given a circuit number
14657      * @param circuit The circuit number to find
14658      * @return A referenced pointer to a call or 0
14659      */
14660     ISDNQ931Call* findCall(unsigned int circuit);
14661 
14662     /**
14663      * Terminate calls. If list is 0 terminate all calls
14664      * @param list Optional list of circuits (strings) to be released
14665      * @param reason The reason to be passed to each terminated call
14666      */
14667     void terminateCalls(ObjList* list, const char* reason);
14668 
14669     /**
14670      * Check if this call control can accept new calls
14671      * @param outgoing Call direction (true for outgoing)
14672      * @param reason String to be filled with the reason if not accepted
14673      * @return True if the call request is accepted
14674      */
14675     bool acceptNewCall(bool outgoing, String& reason);
14676 
14677     /**
14678      * Process received data. Process received message segments if any
14679      * @param data The received data
14680      * @return ISDNQ931Message pointer or 0
14681      */
14682     ISDNQ931Message* getMsg(const DataBlock& data);
14683 
14684     /**
14685      * End waiting for message segments
14686      * If reason is 0 parse already received data for the segmented message
14687      * This method is thread safe
14688      * @param reason Debug info reason. If non 0 drop the received segment(s)
14689      * @return ISDNQ931Message pointer or 0
14690      */
14691     ISDNQ931Message* endReceiveSegment(const char* reason = 0);
14692 
14693     /**
14694      * Process messages with global call reference or should have one
14695      * @param msg The received message
14696      * @param tei The TEI received with the message
14697      */
14698     void processGlobalMsg(ISDNQ931Message* msg, u_int8_t tei = 0);
14699 
14700     /**
14701      * Process a restart request
14702      * @param msg The received message
14703      * @param tei The TEI received with the message
14704      */
14705     void processMsgRestart(ISDNQ931Message* msg, u_int8_t tei = 0);
14706 
14707     /**
14708      * Process messages with invalid call reference
14709      * @param msg The received message
14710      * @param tei The TEI received with the message
14711      */
14712     void processInvalidMsg(ISDNQ931Message* msg, u_int8_t tei = 0);
14713 
14714     /**
14715      * Try to reserve a circuit for restarting if none. Send a restart request on it's behalf
14716      * Start counting the restart interval if no circuit reserved
14717      * This method is thread safe
14718      * @param time The time of the transmission
14719      * @param retrans Retransmission flag (true if a previous request timed out)
14720      */
14721     void sendRestart(u_int64_t time = Time::msecNow(), bool retrans = false);
14722 
14723     /**
14724      * End restart procedure on timeout or restart acknoledge
14725      * This method is thread safe
14726      * @param restart True to try to send restart for the next circuit
14727      * @param time The time of the transmission
14728      * @param timeout True if a restart request timed out
14729      */
14730     void endRestart(bool restart, u_int64_t time, bool timeout = false);
14731 
14732     /**
14733      * Send a STATUS message
14734      * @param cause Value for Cause IE
14735      * @param callRefLen The call reference length parameter.
14736      * @param callRef The call reference
14737      * @param tei The TEI to send with the STATUS message
14738      * @param initiator True if this is from the call initiator
14739      * @param state The state for CallState IE
14740      * @param display Optional value for Display IE
14741      * @param diagnostic Optional value for cause diagnostic value
14742      * @return The result of the operation (true if successfully sent)
14743      */
14744     bool sendStatus(const char* cause, u_int8_t callRefLen, u_int32_t callRef = 0,
14745 	u_int8_t tei = 0, bool initiator = false, ISDNQ931Call::State state = ISDNQ931Call::Null,
14746 	const char* display = 0, const char* diagnostic = 0);
14747 
14748     /**
14749      * Send a RELEASE or RELEASE COMPLETE message
14750      * @param release True to send RELEASE, false to send RELEASE COMPLETE
14751      * @param callRefLen The call reference length parameter
14752      * @param callRef The call reference
14753      * @param tei The TEI of the Layer 2 associated with the call
14754      * @param initiator The call initiator flag
14755      * @param cause Value for Cause IE
14756      * @param diag Optional hexified string for cause dignostic
14757      * @param display Optional value for Display IE
14758      * @param signal Optional value for Signal IE
14759      * @return The result of the operation (true if successfully sent)
14760      */
14761     bool sendRelease(bool release, u_int8_t callRefLen, u_int32_t callRef, u_int8_t tei,
14762 	bool initiator, const char* cause = 0, const char* diag = 0,
14763 	const char* display = 0, const char* signal = 0);
14764 
14765 private:
control(NamedList & params)14766     virtual bool control(NamedList& params)
14767 	{ return SignallingDumpable::control(params,this); }
14768     bool q921Up() const;                 // Check if layer 2 may be up
14769     ISDNLayer2* m_q921;                  // The attached layer 2
14770     bool m_q921Up;                       // Layer 2 state
14771     // Protocol data
14772     bool m_networkHint;                  // NET / CPE hint, layer 2 is authoritative
14773     bool m_primaryRate;                  // Primary/base rate support
14774     bool m_transferModeCircuit;          // Circuit switch/packet mode transfer
14775     u_int32_t m_callRef;                 // Current available call reference for outgoing calls
14776     u_int8_t m_callRefLen;               // Call reference length
14777     u_int32_t m_callRefMask;             // Call reference mask
14778     ISDNQ931ParserData m_parserData;     // Parser settings
14779     ISDNQ931IEData m_data;               // Process IEs
14780     // Timers & counters
14781     SignallingTimer m_l2DownTimer;       // T309: Layer 2 is down timeout
14782     SignallingTimer m_recvSgmTimer;      // T314: Receive segment timeout
14783     SignallingTimer m_syncCicTimer;      // T316: Restart individual circuit timeout
14784     SignallingCounter m_syncCicCounter;  // RESTART retransmission counter
14785     SignallingTimer m_callDiscTimer;     // Q931 call value (see ISDQ931Call)
14786     SignallingTimer m_callRelTimer;      // Q931 call value (see ISDQ931Call)
14787     SignallingTimer m_callConTimer;      // Q931 call value (see ISDQ931Call)
14788     // Default values
14789     String m_numPlan;                    // Numbering plan
14790     String m_numType;                    // Number type
14791     String m_numPresentation;            // Number presentation
14792     String m_numScreening;               // Number screening
14793     String m_format;                     // Data format
14794     String m_cpeNumber;                  // The number of the BRI CPE
14795     // Restart data
14796     SignallingCircuit* m_restartCic;     // Currently restarting circuit
14797     unsigned int m_lastRestart;          // Last restarted circuit's code
14798     SignallingTimer m_syncGroupTimer;    // Restarting circuit group interval
14799     // Message segmentation data
14800     DataBlock m_segmentData;             // Message segments buffer
14801     ISDNQ931Message* m_segmented;        // Segmented message
14802     u_int8_t m_remaining;                // Remaining segments
14803     // Debug
14804     bool m_printMsg;                     // True to print messages to output
14805     bool m_extendedDebug;                // Extended debug flag
14806     // Flags used to print error messages
14807     bool m_flagQ921Down;                 // Layer 2 is down period timed out
14808     bool m_flagQ921Invalid;              // Refusing to send message when Layer 2 is missing or down
14809 };
14810 
14811 /**
14812  * Q.931 ISDN Layer 3 implementation on top of a Layer 2. Manage Q.931 monitors
14813  * @short ISDN Q.931 implementation on top of Q.921 of call controller monitor
14814  */
14815 class YSIG_API ISDNQ931Monitor : public SignallingCallControl, public ISDNLayer3
14816 {
14817     YCLASS(ISDNQ931Monitor,ISDNLayer3)
14818     friend class ISDNQ931CallMonitor;
14819 public:
14820     /**
14821      * Constructor
14822      * Initialize this object and the component
14823      * @param params Layer's parameters and parser settings
14824      * @param name Name of this component
14825      */
14826     ISDNQ931Monitor(const NamedList& params, const char* name = 0);
14827 
14828     /**
14829      * Destructor
14830      * Destroy all calls
14831      */
14832     virtual ~ISDNQ931Monitor();
14833 
14834     /**
14835      * Configure and initialize the Q.931 monitor and its interfaces
14836      * @param config Optional configuration parameters override
14837      * @return True if Q.931 monitor and both interfaces were initialized properly
14838      */
14839     virtual bool initialize(const NamedList* config);
14840 
14841     /**
14842      * Get the controller's status as text
14843      * @return Controller status name
14844      */
14845     virtual const char* statusName() const;
14846 
14847     /**
14848      * Notification from layer 2 of data link set/release command or response
14849      * @param tei The TEI of the notification
14850      * @param cmd True if received a command, false if received a response
14851      * @param value The value of the notification
14852      *	If 'cmd' is true (command), the value is true if a request to establish data link was received
14853      *   or false if received a request to release data link
14854      *	If 'cmd' is false (response), the value is the response
14855      * @param layer2 Pointer to the notifier
14856      */
14857     virtual void dataLinkState(u_int8_t tei, bool cmd, bool value, ISDNLayer2* layer2);
14858 
14859     /**
14860      * Notification from layer 2 of data link idle timeout
14861      * @param layer2 Pointer to the notifier
14862      */
14863     virtual void idleTimeout(ISDNLayer2* layer2);
14864 
14865     /**
14866      * Implements Q.921 DL-DATA and DL-UNIT DATA indication primitives
14867      * @param data Received data
14868      * @param tei The TEI of the Layer 2
14869      * @param layer2 Pointer to the sender
14870      */
14871     virtual void receiveData(const DataBlock& data, u_int8_t tei, ISDNLayer2* layer2);
14872 
14873     /**
14874      * Attach ISDN Q.921 pasive transport that monitors one side of the link
14875      * This method is thread safe
14876      * @param q921 Pointer to the monitor to attach
14877      * @param net True if this is the network side of the data link, false for user (CPE) side
14878      * @return Pointer to detached monitor or NULL
14879      */
14880     virtual ISDNQ921Passive* attach(ISDNQ921Passive* q921, bool net);
14881 
14882     /**
14883      * Attach a circuit group to this call controller
14884      * This method is thread safe
14885      * @param circuits Pointer to the SignallingCircuitGroup to attach
14886      * @param net True if this group belongs to the network side of the data link, false for user (CPE) side
14887      * @return Pointer to the old group that was detached, NULL if none or no change
14888      */
14889     virtual SignallingCircuitGroup* attach(SignallingCircuitGroup* circuits, bool net);
14890 
14891     /**
14892      * Get a pointer to the NET or CPE circuit group
14893      * @param net True to get the network side circuits, false for user (CPE) side
14894      * @return Pointer to the circuit group requested, NULL if none attached
14895      */
circuits(bool net)14896     inline ISDNQ921Passive* circuits(bool net) const
14897 	{ return net ? m_q921Net : m_q921Cpe; }
14898 
14899     /**
14900      * Set debug data of this call controller
14901      * @param printMsg Enable/disable message printing on output
14902      * @param extendedDebug Enable/disable hex data dump if print messages is enabled
14903      */
setDebug(bool printMsg,bool extendedDebug)14904     inline void setDebug(bool printMsg, bool extendedDebug)
14905 	{ m_parserData.m_extendedDebug = m_extendedDebug =
14906 	    ((m_printMsg = printMsg) && extendedDebug); }
14907 
14908     /**
14909      * Terminate all monitors
14910      * This method is thread safe
14911      * @param reason Cleanup reason
14912      */
14913     virtual void cleanup(const char* reason = "offline")
14914 	{ terminateMonitor(0,reason); }
14915 
14916     /**
14917      * Terminate all monitors or only one
14918      * This method is thread safe
14919      * @param mon The monitor to terminate, 0 to terminate all
14920      * @param reason The termination reason
14921      */
14922     void terminateMonitor(ISDNQ931CallMonitor* mon, const char* reason);
14923 
14924 protected:
14925     /**
14926      * Detach links. Disposes memory
14927      */
destroyed()14928     virtual void destroyed()
14929     {
14930 	TelEngine::destruct(SignallingCallControl::attach(0));
14931 	TelEngine::destruct(attach((ISDNQ921Passive*)0,true));
14932 	TelEngine::destruct(attach((ISDNQ921Passive*)0,false));
14933 	attach((SignallingCircuitGroup*)0,true);
14934 	attach((SignallingCircuitGroup*)0,false);
14935 	ISDNLayer3::destroyed();
14936     }
14937 
14938     /**
14939      * Method called periodically to check timeouts
14940      * This method is thread safe
14941      * @param when Time to use as computing base for events and timeouts
14942      */
14943     virtual void timerTick(const Time& when);
14944 
14945     /**
14946      * Reserve the same circuit code from both circuit groups
14947      * This is an atomic operation: if one circuit fails to be reserved, both of them will fail
14948      * Release both circuits on failure
14949      * This method is thread safe
14950      * @param code The circuit code to reserve
14951      * @param netInit True if the caller is from the network side of the link, false if it's from CPE side
14952      * @param caller The destination caller circuit
14953      * @param called The destination called circuit
14954      * @return True on success
14955      */
14956     bool reserveCircuit(unsigned int code, bool netInit,
14957 	SignallingCircuit** caller, SignallingCircuit** called);
14958 
14959     /**
14960      * Release a circuit
14961      * This method is thread safe
14962      * @param circuit The circuit to release
14963      * @return True on success
14964      */
14965     bool releaseCircuit(SignallingCircuit* circuit);
14966 
14967     /**
14968      * Process a restart or restart acknoledge message
14969      * Terminate the monitor having the circuit given in restart message
14970      * @param msg The received message
14971      */
14972     void processMsgRestart(ISDNQ931Message* msg);
14973 
14974 private:
14975     // Find a call monitor by call reference or reserved circuit
14976     // @return Referenced call monitor pointer or 0 if not found
14977     ISDNQ931CallMonitor* findMonitor(unsigned int value, bool byCallRef);
14978     // Drop some messages. Return true if the message should be dropped
14979     bool dropMessage(const ISDNQ931Message* msg);
14980 
14981     ISDNQ921Passive* m_q921Net;          // Net side of the link
14982     ISDNQ921Passive* m_q921Cpe;          // CPE side of the link
14983     SignallingCircuitGroup* m_cicNet;    // Circuit group for the net side of the link
14984     SignallingCircuitGroup* m_cicCpe;    // Circuit group for the cpe side of the link
14985     ISDNQ931ParserData m_parserData;     // Parser settings
14986     ISDNQ931IEData m_data;               // Process IEs
14987     // Debug
14988     bool m_printMsg;                     // True to print messages to output
14989     bool m_extendedDebug;                // Extended debug flag
14990 };
14991 
14992 }
14993 
14994 #endif /* __YATESIG_H */
14995 
14996 /* vi: set ts=8 sw=4 sts=4 noet: */
14997