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"),¶ms,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"),¶ms,"ss7-test"), 8547 SS7Layer4(sio,¶ms), 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"),¶ms,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