1 /** 2 * yatesip.h 3 * Yet Another SIP Stack 4 * This file is part of the YATE Project http://YATE.null.ro 5 * 6 * Yet Another Telephony Engine - a fully featured software PBX and IVR 7 * Copyright (C) 2004-2014 Null Team 8 * 9 * This software is distributed under multiple licenses; 10 * see the COPYING file in the main directory for licensing 11 * information for this specific distribution. 12 * 13 * This use of this software may be subject to additional restrictions. 14 * See the LEGAL file in the main directory for details. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef __YATESIP_H 22 #define __YATESIP_H 23 24 #include <yateclass.h> 25 #include <yatemime.h> 26 27 #ifdef _WINDOWS 28 29 #ifdef LIBYSIP_EXPORTS 30 #define YSIP_API __declspec(dllexport) 31 #else 32 #ifndef LIBYSIP_STATIC 33 #define YSIP_API __declspec(dllimport) 34 #endif 35 #endif 36 37 #endif /* _WINDOWS */ 38 39 #ifndef YSIP_API 40 #define YSIP_API 41 #endif 42 43 /** 44 * Holds all Telephony Engine related classes. 45 */ 46 namespace TelEngine { 47 48 /** 49 * Token table containing default human readable responses for answer codes 50 */ 51 extern YSIP_API TokenDict* SIPResponses; 52 53 class SIPEngine; 54 class SIPEvent; 55 56 class YSIP_API SIPParty : public RefObject 57 { 58 public: 59 SIPParty(Mutex* mutex = 0); 60 SIPParty(bool reliable, Mutex* mutex = 0); 61 virtual ~SIPParty(); 62 /** 63 * Transmit an event 64 * @param event Evend to send 65 * @return False on fatal failure (subsequent send would fail again) 66 */ 67 virtual bool transmit(SIPEvent* event) = 0; 68 virtual const char* getProtoName() const = 0; 69 virtual bool setParty(const URI& uri) = 0; 70 virtual void* getTransport() = 0; 71 void setAddr(const String& addr, int port, bool local); 72 void getAddr(String& addr, int& port, bool local); 73 inline void appendAddr(String& buf, bool local, bool unsafe = true) { 74 Lock lock(unsafe ? m_mutex : 0); 75 if (local) 76 SocketAddr::appendTo(buf,m_local,m_localPort); 77 else 78 SocketAddr::appendTo(buf,m_party,m_partyPort); 79 } mutex()80 inline Mutex* mutex() 81 { return m_mutex; } getLocalAddr()82 inline const String& getLocalAddr() const 83 { return m_local; } getPartyAddr()84 inline const String& getPartyAddr() const 85 { return m_party; } getLocalPort()86 inline int getLocalPort() const 87 { return m_localPort; } getPartyPort()88 inline int getPartyPort() const 89 { return m_partyPort; } isReliable()90 inline bool isReliable() const 91 { return m_reliable; } 92 protected: 93 Mutex* m_mutex; 94 bool m_reliable; 95 String m_local; 96 String m_party; 97 int m_localPort; 98 int m_partyPort; 99 }; 100 101 /** 102 * Command Sequence Number generator 103 * @short SIP CSeq generator 104 */ 105 class YSIP_API SIPSequence : public RefObject, public Mutex 106 { 107 public: 108 /** 109 * Constructor 110 * @param cseq Sequence number to start 111 */ 112 inline SIPSequence(int32_t cseq = -1) 113 : Mutex(false,"CSeq"), m_cseq(cseq) 114 { } 115 116 /** 117 * Get the last number generated by this sequence 118 * @return Last generated CSeq value between 0 and 2^31-1, negative if not initialized 119 */ getLastCSeq()120 inline int32_t getLastCSeq() const 121 { return m_cseq; } 122 123 /** 124 * Create a CSeq value suitable for use in a new request 125 * @return New CSeq value between 1 and 2^31-1 126 */ getNextCSeq()127 inline int32_t getNextCSeq() 128 { Lock mylock(this); return (++m_cseq > 0) ? m_cseq : (m_cseq = 1); } 129 130 /** 131 * Set the Command Sequence number 132 * @param cseq New sequence number to start from 133 */ setCSeq(int32_t cseq)134 inline void setCSeq(int32_t cseq) 135 { m_cseq = cseq; } 136 137 private: 138 int32_t m_cseq; 139 }; 140 141 /** 142 * An object that holds the sip message parsed into this library model. 143 * This class can be used to parse a sip message from a text buffer, or it 144 * can be used to create a text buffer from a sip message. 145 * @short A container and parser for SIP messages 146 */ 147 class YSIP_API SIPMessage : public RefObject 148 { 149 public: 150 /** 151 * Various message flags 152 */ 153 enum Flags { 154 Defaults = 0, 155 NotReqRport = 0x0001, 156 NotAddAllow = 0x0002, 157 NotAddAgent = 0x0004, 158 RportAfterBranch = 0x0008, 159 NotSetRport = 0x0010, 160 NotSetReceived = 0x0020, 161 NoConnReuse = 0x0040, // Don't add 'alias' parameter to Via header (reliable only) 162 NoTagFailure = 0x0080, // Don't add a To tag for 3xx/4xx/5xx/6xx answers 163 }; 164 165 /** 166 * Copy constructor 167 */ 168 SIPMessage(const SIPMessage& original); 169 170 /** 171 * Creates a new, empty, outgoing SIPMessage. 172 */ 173 SIPMessage(const char* _method, const char* _uri, const char* _version = "SIP/2.0"); 174 175 /** 176 * Creates a new SIPMessage from parsing a text buffer. 177 * @param ep Party to set in message 178 * @param buf Buffer to parse 179 * @param len Optional buffer length 180 * @param bodyLen Pointer to body length to be set if the message was received 181 * on a stream transport. If not 0 the buffer must contain the message 182 * without its body 183 */ 184 SIPMessage(SIPParty* ep, const char* buf, int len = -1, unsigned int* bodyLen = 0); 185 186 /** 187 * Creates a new SIPMessage as answer to another message. 188 */ 189 SIPMessage(const SIPMessage* message, int _code, const char* _reason = 0); 190 191 /** 192 * Creates an ACK message from an original message and a response. 193 */ 194 SIPMessage(const SIPMessage* original, const SIPMessage* answer); 195 196 /** 197 * Destroy the message and all 198 */ 199 virtual ~SIPMessage(); 200 201 /** 202 * Construct a new SIP message by parsing a text buffer 203 * @param ep Party to set in message 204 * @param buf Buffer to parse 205 * @param len Optional buffer length 206 * @param bodyLen Pointer to body length to be set if the message was received 207 * on a stream transport. If not 0 the buffer must contain the message 208 * without its body 209 * @return A pointer to a valid new message or NULL 210 */ 211 static SIPMessage* fromParsing(SIPParty* ep, const char* buf, int len = -1, 212 unsigned int* bodyLen = 0); 213 214 /** 215 * Build message's body. Reset it before. 216 * This method should be called after parsing a partial message (headers only) 217 * @param buf Buffer to parse 218 * @param len Optional buffer length 219 */ 220 void buildBody(const char* buf, int len = -1); 221 222 /** 223 * Complete missing fields with defaults taken from a SIP engine 224 * @param engine Pointer to the SIP engine to use for extra parameters 225 * @param user Username to set in the From header instead of that in rURI 226 * @param domain Domain to use in From instead of the local IP address 227 * @param dlgTag Value of dialog tag parameter to set in To header 228 * @param flags Miscellaneous completion flags, -1 to take them from engine 229 */ 230 void complete(SIPEngine* engine, const char* user = 0, const char* domain = 0, const char* dlgTag = 0, int flags = -1); 231 232 /** 233 * Copy an entire header line (including all parameters) from another message 234 * @param message Pointer to the message to copy the header from 235 * @param name Name of the header to copy 236 * @param newName New name to force in headers, NULL to just copy 237 * @return True if the header was found and copied 238 */ 239 bool copyHeader(const SIPMessage* message, const char* name, const char* newName = 0); 240 241 /** 242 * Copy multiple header lines (including all parameters) from another message 243 * @param message Pointer to the message to copy the header from 244 * @param name Name of the headers to copy 245 * @param newName New name to force in headers, NULL to just copy 246 * @return Number of headers found and copied 247 */ 248 int copyAllHeaders(const SIPMessage* message, const char* name, const char* newName = 0); 249 250 /** 251 * Get the endpoint this message uses 252 * @return Pointer to the endpoint of this message 253 */ getParty()254 inline SIPParty* getParty() const 255 { return m_ep; } 256 257 /** 258 * Set the endpoint this message uses 259 * @param ep Pointer to the endpoint of this message 260 */ 261 void setParty(SIPParty* ep = 0); 262 263 /** 264 * Check if this message is valid as result of the parsing 265 */ isValid()266 inline bool isValid() const 267 { return m_valid; } 268 269 /** 270 * Check if this message is an answer or a request 271 */ isAnswer()272 inline bool isAnswer() const 273 { return m_answer; } 274 275 /** 276 * Check if this message is an outgoing message 277 * @return True if this message should be sent to remote 278 */ isOutgoing()279 inline bool isOutgoing() const 280 { return m_outgoing; } 281 282 /** 283 * Check if this message is an ACK message 284 * @return True if this message has an ACK method 285 */ isACK()286 inline bool isACK() const 287 { return m_ack; } 288 289 /** 290 * Check if this message is handled by a reliable protocol 291 * @return True if a reliable protocol (TCP, SCTP) is used 292 */ isReliable()293 inline bool isReliable() const 294 { return m_ep ? m_ep->isReliable() : false; } 295 296 /** 297 * Get the Command Sequence number from this message 298 * @return Number part of CSEQ in this message 299 */ getCSeq()300 inline int32_t getCSeq() const 301 { return m_cseq; } 302 303 /** 304 * Set the Command Sequence number for this message 305 * @param cseq Sequence number for this message 306 */ setCSeq(int32_t cseq)307 inline void setCSeq(int32_t cseq) 308 { m_cseq = cseq; } 309 310 /** 311 * Get the last flags used by this message 312 * @return Flags last used, ORed together 313 */ getFlags()314 inline int getFlags() const 315 { return m_flags; } 316 317 /** 318 * Get value of flag that specifies the message is not to be sent on wire 319 * @return The value of the flag 320 */ dontSend()321 inline bool dontSend() const 322 { return m_dontSend; } 323 324 /** 325 * Set flag that specifies the message is not to be sent on wire 326 * @param val Value of the flag to send 327 */ dontSend(bool val)328 inline void dontSend(bool val) 329 { m_dontSend = val; } 330 /** 331 * Find a header line by name 332 * @param name Name of the header to locate 333 * @return A pointer to the first matching header line or 0 if not found 334 */ 335 const MimeHeaderLine* getHeader(const char* name) const; 336 337 /** 338 * Find the last header line that matches a given name name 339 * @param name Name of the header to locate 340 * @return A pointer to the last matching header line or 0 if not found 341 */ 342 const MimeHeaderLine* getLastHeader(const char* name) const; 343 344 /** 345 * Count the header lines matching a specific name 346 * @param name Name of the header to locate 347 * @return Number of matching header lines 348 */ 349 int countHeaders(const char* name) const; 350 351 /** 352 * Find a header parameter by name 353 * @param name Name of the header to locate 354 * @param param Name of the parameter to locate in the tag 355 * @param last Find the last header with that name instead of first 356 * @return A pointer to the first matching header line or 0 if not found 357 */ 358 const NamedString* getParam(const char* name, const char* param, bool last = false) const; 359 360 /** 361 * Get a string value (without parameters) from a header line 362 * @param name Name of the header to locate 363 * @param last Find the last header with that name instead of first 364 * @return The value hold in the header or an empty String 365 */ 366 const String& getHeaderValue(const char* name, bool last = false) const; 367 368 /** 369 * Get a string value from a parameter in a header line 370 * @param name Name of the header to locate 371 * @param param Name of the parameter to locate in the tag 372 * @param last Find the last header with that name instead of first 373 * @return The value hold in the parameter or an empty String 374 */ 375 const String& getParamValue(const char* name, const char* param, bool last = false) const; 376 377 /** 378 * Append a new header line constructed from name and content 379 * @param name Name of the header to add 380 * @param value Content of the new header line 381 */ 382 inline void addHeader(const char* name, const char* value = 0) 383 { header.append(new MimeHeaderLine(name,value)); } 384 385 /** 386 * Append an already constructed header line 387 * @param line Header line to add 388 */ addHeader(MimeHeaderLine * line)389 inline void addHeader(MimeHeaderLine* line) 390 { header.append(line); } 391 392 /** 393 * Clear all header lines that match a name 394 * @param name Name of the header to clear 395 */ 396 void clearHeaders(const char* name); 397 398 /** 399 * Set a header line constructed from name and content 400 */ 401 inline void setHeader(const char* name, const char* value = 0) 402 { clearHeaders(name); addHeader(name,value); } 403 404 /** 405 * Construct a new authorization line based on credentials and challenge 406 * @param username User account name 407 * @param password Clear text password for the account 408 * @param meth Method to include in the authorization digest 409 * @param uri URI to include in the authorization digest 410 * @param proxy Set to true to authenticate to a proxy, false to a server 411 * @param engine Optional engine processing this message 412 * @return A new authorization line to be used in a new transaction 413 */ 414 MimeAuthLine* buildAuth(const String& username, const String& password, 415 const String& meth, const String& uri, bool proxy = false, SIPEngine* engine = 0) const; 416 417 /** 418 * Construct a new authorization line based on this answer and original message 419 * @param original Origianl outgoing message 420 * @param engine Optional engine processing this message 421 * @return A new authorization line to be used in a new transaction 422 */ 423 MimeAuthLine* buildAuth(const SIPMessage& original, SIPEngine* engine = 0) const; 424 425 /** 426 * Prepare the message for automatic client transaction authentication. 427 * @param username Username for auto authentication 428 * @param password Password for auto authentication 429 */ 430 inline void setAutoAuth(const char* username = 0, const char* password = 0) 431 { m_authUser = username; m_authPass = password; } 432 433 /** 434 * Retrieve the username to be used for auto authentication 435 * @return Username for auto authentication 436 */ getAuthUsername()437 inline const String& getAuthUsername() const 438 { return m_authUser; } 439 440 /** 441 * Retrieve the password to be used for auto authentication 442 * @return Password for auto authentication 443 */ getAuthPassword()444 inline const String& getAuthPassword() const 445 { return m_authPass; } 446 447 /** 448 * Extract routes from Record-Route: headers 449 * @return A list of MimeHeaderLine representing SIP routes 450 */ 451 ObjList* getRoutes() const; 452 453 /** 454 * Add Route: headers to an outgoing message 455 * @param routes List of MimeHeaderLine representing SIP routes 456 */ 457 void addRoutes(const ObjList* routes); 458 459 /** 460 * Get the Command Sequence Number generator 461 * @return Pointer to the CSeq generator of this message 462 */ getSequence()463 inline SIPSequence* getSequence() const 464 { return m_seq; } 465 466 /** 467 * Set the Command Sequence Number generator 468 * @param seq Pointer to the new CSeq generator of this message 469 */ setSequence(SIPSequence * seq)470 inline void setSequence(SIPSequence* seq) 471 { m_seq = seq; } 472 473 /** 474 * Creates a binary buffer from a SIPMessage. 475 */ 476 const DataBlock& getBuffer() const; 477 478 /** 479 * Creates a text buffer from the headers. 480 */ 481 const String& getHeaders() const; 482 483 /** 484 * Set a new body for this message 485 */ 486 void setBody(MimeBody* newbody = 0); 487 488 /** 489 * Get trace ID of the message 490 * @return The trace ID 491 */ traceId()492 const String& traceId() const 493 { return msgTraceId; } 494 495 /** 496 * Sip Version 497 */ 498 String version; 499 500 /** 501 * This holds the method name of the message. 502 */ 503 String method; 504 505 /** 506 * URI of the request 507 */ 508 String uri; 509 510 /** 511 * Status code 512 */ 513 int code; 514 515 /** 516 * Reason Phrase 517 */ 518 String reason; 519 520 /** 521 * All the headers should be in this list. 522 */ 523 ObjList header; 524 525 /** 526 * All the body related things should be here, including the entire body and 527 * the parsed body. 528 */ 529 MimeBody* body; 530 531 /** 532 * Trace ID of the message 533 */ 534 String msgTraceId; 535 536 /** 537 * Message print in debug 538 */ 539 bool msgPrint; 540 541 protected: 542 bool parse(const char* buf, int len, unsigned int* bodyLen); 543 bool parseFirst(String& line); 544 SIPParty* m_ep; 545 RefPointer<SIPSequence> m_seq; 546 bool m_valid; 547 bool m_answer; 548 bool m_outgoing; 549 bool m_ack; 550 int32_t m_cseq; 551 int m_flags; 552 mutable String m_string; 553 mutable DataBlock m_data; 554 String m_authUser; 555 String m_authPass; 556 bool m_dontSend; 557 private: 558 SIPMessage(); // no, thanks 559 }; 560 561 /** 562 * A class to store information required to identify a dialog 563 * @short SIP Dialog object 564 */ 565 class YSIP_API SIPDialog : public String 566 { 567 public: 568 /** 569 * Default constructor, build an empty SIP dialog 570 */ SIPDialog()571 inline SIPDialog() 572 : remoteCSeq(-1) 573 { } 574 575 /** 576 * Copy constructor 577 * @param original Original SIP dialog to copy 578 */ 579 SIPDialog(const SIPDialog& original); 580 581 /** 582 * Constructor from a SIP message 583 * @param message SIP message to copy the dialog information from 584 */ 585 explicit SIPDialog(const SIPMessage& message); 586 587 /** 588 * Constructor from a Call ID, leaves URIs and tags empty 589 * @param callid Call ID to insert in the dialog 590 */ SIPDialog(const String & callid)591 inline explicit SIPDialog(const String& callid) 592 : String(callid), remoteCSeq(-1) 593 { } 594 595 /** 596 * Assignment from another dialog 597 * @param original Original SIP dialog to copy 598 * @return Reference to this SIP dialog 599 */ 600 SIPDialog& operator=(const SIPDialog& original); 601 602 /** 603 * Assignment from a SIP message 604 * @param message SIP message to copy the dialog information from 605 * @return Reference to this SIP dialog 606 */ 607 SIPDialog& operator=(const SIPMessage& message); 608 609 /** 610 * Assignment from a Call ID, URIs and tags are cleared 611 * @param callid Call ID to copy to the dialog 612 * @return Reference to this SIP dialog 613 */ 614 SIPDialog& operator=(const String& callid); 615 616 /** 617 * SIP dialog matching check 618 * @param other Other dialog to compare to 619 * @param ignoreURIs True to ignore local and remote URIs when comparing 620 * @return True if the two dialogs match 621 */ 622 bool matches(const SIPDialog& other, bool ignoreURIs) const; 623 624 /** 625 * Dialog equality comparation, suitable for RFC 2543 626 * @param other Other dialog to compare to 627 * @return True if the two dialogs are equal 628 */ 629 inline bool operator==(const SIPDialog& other) const 630 { return matches(other,false); } 631 632 /** 633 * Dialog inequality comparation, suitable for RFC 2543 634 * @param other Other dialog to compare to 635 * @return True if the two dialogs are different 636 */ 637 inline bool operator!=(const SIPDialog& other) const 638 { return !matches(other,false); } 639 640 /** 641 * Dialog equality comparation, suitable for RFC 3261 642 * @param other Other dialog to compare to 643 * @return True if the two dialogs match (ignoring local and remote URIs) 644 */ 645 inline bool operator&=(const SIPDialog& other) const 646 { return matches(other,true); } 647 648 /** 649 * Dialog inequality comparation, suitable for RFC 3261 650 * @param other Other dialog to compare to 651 * @return True if the two dialogs do not match (ignoring local and remote URIs) 652 */ 653 inline bool operator|=(const SIPDialog& other) const 654 { return !matches(other,true); } 655 656 /** 657 * Get the From URI from the dialog 658 * @param outgoing True if getting the URI for an outgoing transaction 659 * @return Reference to the From URI in dialog 660 */ fromURI(bool outgoing)661 inline const String& fromURI(bool outgoing) const 662 { return outgoing ? localURI : remoteURI; } 663 664 /** 665 * Get the From tag from the dialog 666 * @param outgoing True if getting the tag for an outgoing transaction 667 * @return Reference to the From URI tag in dialog 668 */ fromTag(bool outgoing)669 inline const String& fromTag(bool outgoing) const 670 { return outgoing ? localTag : remoteTag; } 671 672 /** 673 * Get the To URI from the dialog 674 * @param outgoing True if getting the URI for an outgoing transaction 675 * @return Reference to the To URI in dialog 676 */ toURI(bool outgoing)677 inline const String& toURI(bool outgoing) const 678 { return outgoing ? remoteURI : localURI; } 679 680 /** 681 * Get the To tag from the dialog 682 * @param outgoing True if getting the tag for an outgoing transaction 683 * @return Reference to the To URI tag in dialog 684 */ toTag(bool outgoing)685 inline const String& toTag(bool outgoing) const 686 { return outgoing ? remoteTag : localTag; } 687 688 /** 689 * Get the Command Sequence Number generator 690 * @return Pointer to the CSeq generator of this dialog 691 */ getSequence()692 inline SIPSequence* getSequence() const 693 { return m_seq; } 694 695 /** 696 * Set the Command Sequence Number generator 697 * @param seq Pointer to the new CSeq generator of this dialog 698 */ setSequence(SIPSequence * seq)699 inline void setSequence(SIPSequence* seq) 700 { m_seq = seq; } 701 702 /** 703 * Set a new Command Sequence generator 704 * @param cseq New sequence number to start from 705 */ 706 void setCSeq(int32_t cseq); 707 708 /** 709 * Get the last number generated by this dialog 710 * @return Last generated CSeq value between 0 and 2^31-1, negative if no generator 711 */ getLastCSeq()712 inline int32_t getLastCSeq() const 713 { return m_seq ? m_seq->getLastCSeq() : -1; } 714 715 /** 716 * Create a CSeq value suitable for use in a new request 717 * @return New CSeq value between 1 and 2^31-1, negative if no generator 718 */ getNextCSeq()719 inline int32_t getNextCSeq() 720 { return m_seq ? m_seq->getNextCSeq() : -1; } 721 722 /** 723 * Adjust the last seen remote CSeq 724 * @param cseq Remote sequence number 725 * @return True if remote sequence was adjusted 726 */ adjustCSeq(int cseq)727 inline bool adjustCSeq(int cseq) 728 { return (cseq > remoteCSeq) && ((remoteCSeq = cseq) >= 0); } 729 730 /** 731 * Adjust the last seen remote CSeq from a SIP message 732 * @param message Pointer to received SIP message 733 * @return True if remote sequence was adjusted 734 */ adjustCSeq(const SIPMessage * message)735 inline bool adjustCSeq(const SIPMessage* message) 736 { return message && adjustCSeq(message->getCSeq()); } 737 738 /** 739 * Local URI of the dialog 740 */ 741 String localURI; 742 743 /** 744 * Tag parameter of the local URI 745 */ 746 String localTag; 747 748 /** 749 * Remote URI of the dialog 750 */ 751 String remoteURI; 752 753 /** 754 * Tag parameter of the remote URI 755 */ 756 String remoteTag; 757 758 /** 759 * Last seen Command Sequence Number 760 */ 761 int remoteCSeq; 762 763 protected: 764 RefPointer<SIPSequence> m_seq; 765 }; 766 767 /** 768 * All informaton related to a SIP transaction, starting with 1st message 769 * @short A class holding one SIP transaction 770 */ 771 class YSIP_API SIPTransaction : public RefObject 772 { 773 public: 774 /** 775 * Current state of the transaction 776 */ 777 enum State { 778 // Invalid state - before constructor or after destructor 779 Invalid, 780 781 // Initial state - after the initial message was inserted 782 Initial, 783 784 // Trying state - got the message but no decision made yet 785 Trying, 786 787 // Process state - while locally processing the event 788 Process, 789 790 // Retrans state - retransmits latest message until getting ACK 791 Retrans, 792 793 // Finish state - transmits the last message on client retransmission 794 Finish, 795 796 // Cleared state - removed from engine, awaiting destruction 797 Cleared 798 }; 799 800 /** 801 * Possible return values from @ref processMessage() 802 */ 803 enum Processed { 804 // Not matched at all 805 NoMatch, 806 807 // Belongs to another dialog - probably result of a fork 808 NoDialog, 809 810 // Matched to transaction/dialog and processed 811 Matched 812 }; 813 814 /** 815 * Constructor from first message 816 * @param message A pointer to the initial message, should not be used 817 * afterwards as the transaction takes ownership 818 * @param engine A pointer to the SIP engine this transaction belongs 819 * @param outgoing True if this transaction is for an outgoing request 820 * @param autoChangeParty Optional pointer to auto change party flag (use engine's flag if missing) 821 */ 822 SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outgoing = true, 823 bool* autoChangeParty = 0); 824 825 /** 826 * Copy constructor to be used with forked INVITEs 827 * @param original Original transaction that is to be copied 828 * @param tag Dialog tag for the new transaction 829 */ 830 SIPTransaction(const SIPTransaction& original, const String& tag); 831 832 /** 833 * Destructor - clears all held objects 834 */ 835 virtual ~SIPTransaction(); 836 837 /** 838 * Get the name of a transaction state 839 */ 840 static const char* stateName(int state); 841 842 /** 843 * The current state of the transaction 844 * @return The current state as one of the State enums 845 */ getState()846 inline int getState() const 847 { return m_state; } 848 849 /** 850 * Check if the transaction is active for the upper layer 851 * @return True if the transaction is active, false if it finished 852 */ isActive()853 inline bool isActive() const 854 { return (Invalid < m_state) && (m_state < Finish); } 855 856 /** 857 * The first message that created this transaction 858 */ initialMessage()859 inline const SIPMessage* initialMessage() const 860 { return m_firstMessage; } 861 862 /** 863 * The last message (re)sent by this transaction 864 */ latestMessage()865 inline const SIPMessage* latestMessage() const 866 { return m_lastMessage; } 867 868 /** 869 * The most recent message handled by this transaction 870 */ recentMessage()871 inline const SIPMessage* recentMessage() const 872 { return m_lastMessage ? m_lastMessage : m_firstMessage; } 873 874 /** 875 * The SIPEngine this transaction belongs to 876 */ getEngine()877 inline SIPEngine* getEngine() const 878 { return m_engine; } 879 880 /** 881 * Check if this transaction was initiated by the remote peer or locally 882 * @return True if the transaction was created by an outgoing message 883 */ isOutgoing()884 inline bool isOutgoing() const 885 { return m_outgoing; } 886 887 /** 888 * Check if this transaction was initiated locally or by the remote peer 889 * @return True if the transaction was created by an incoming message 890 */ isIncoming()891 inline bool isIncoming() const 892 { return !m_outgoing; } 893 894 /** 895 * Check if this transaction is an INVITE transaction or not 896 * @return True if the transaction is an INVITE 897 */ isInvite()898 inline bool isInvite() const 899 { return m_invite; } 900 901 /** 902 * Check if this transaction is handled by a reliable protocol 903 * @return True if a reliable protocol (TCP, SCTP) is used 904 */ isReliable()905 inline bool isReliable() const 906 { return m_firstMessage ? m_firstMessage->isReliable() : false; } 907 908 /** 909 * The SIP method this transaction handles 910 */ getMethod()911 inline const String& getMethod() const 912 { return m_firstMessage ? m_firstMessage->method : String::empty(); } 913 914 /** 915 * The SIP URI this transaction handles 916 */ getURI()917 inline const String& getURI() const 918 { return m_firstMessage ? m_firstMessage->uri : String::empty(); } 919 920 /** 921 * The Via branch that may uniquely identify this transaction 922 * @return The branch parameter taken from the Via header 923 */ getBranch()924 inline const String& getBranch() const 925 { return m_branch; } 926 927 /** 928 * The call ID may identify this transaction 929 * @return The Call-ID parameter taken from the message 930 */ getCallID()931 inline const String& getCallID() const 932 { return m_callid; } 933 934 /** 935 * The dialog tag that may identify this transaction 936 * @return The dialog tag parameter 937 */ getDialogTag()938 inline const String& getDialogTag() const 939 { return m_tag; } 940 941 /** 942 * Set a new dialog tag, optionally build a random one 943 * @param tag New dialog tag, a null string will build a random tag 944 */ 945 void setDialogTag(const char* tag = 0); 946 947 /** 948 * Set the (re)transmission flag that allows the latest outgoing message 949 * to be send over the wire 950 */ setTransmit()951 inline void setTransmit() 952 { m_transmit = true; } 953 954 /** 955 * Change transaction status to Cleared 956 * This method is not thread safe 957 */ setCleared()958 inline void setCleared() 959 { changeState(Cleared); } 960 961 /** 962 * Get the transmission attempts count for non-reliable transports 963 * @return Current number of transmission attempts 964 */ getTransCount()965 inline unsigned int getTransCount() const 966 { return m_transCount; } 967 968 /** 969 * Set the number of transmission attempts for non-reliable transports 970 * @param count Transmission attempts, clamped between 2 and 10, negative values ignored 971 */ 972 void setTransCount(int count); 973 974 /** 975 * Get the automatic UAC 2xx ACK generation flag 976 * @return True if an ACK will be generated automatically for 2xx answers 977 */ autoAck()978 inline bool autoAck() const 979 { return m_autoAck; } 980 981 /** 982 * Set the automatic UAC 2xx ACK generation flag 983 * @param setAuto True to automatically generate the ACK when receiving a 2xx answer 984 */ autoAck(bool setAuto)985 inline void autoAck(bool setAuto) 986 { m_autoAck = setAuto; } 987 988 /** 989 * Send back an authentication required response 990 * @param realm Authentication realm to send in the answer 991 * @param domain Domain for which it will authenticate 992 * @param stale True if the previous password is valid but nonce is too old 993 * @param proxy True to authenticate as proxy, false as user agent 994 */ 995 void requestAuth(const String& realm, const String& domain, bool stale, bool proxy = false); 996 997 /** 998 * Detect the proper credentials for any user in the engine 999 * @param user String to store the authenticated user name or user to 1000 * look for (if not null on entry) 1001 * @param proxy True to authenticate as proxy, false as user agent 1002 * @param userData Pointer to an optional object that is passed back to @ref SIPEngine::checkUser 1003 * @return Age of the nonce if user matches, negative for a failure 1004 */ 1005 int authUser(String& user, bool proxy = false, GenObject* userData = 0); 1006 1007 /** 1008 * Check if a message belongs to this transaction and process it if so 1009 * @param message A pointer to the message to check, should not be used 1010 * afterwards if this method returned Matched 1011 * @param branch The branch parameter extracted from first Via header 1012 * @return Matched if the message was handled by this transaction, in 1013 * which case it takes ownership over the message 1014 */ 1015 virtual Processed processMessage(SIPMessage* message, const String& branch); 1016 1017 /** 1018 * Process a message belonging to this transaction 1019 * @param message A pointer to the message to process, the caller must 1020 * make sure it belongs to this transaction 1021 */ 1022 virtual void processMessage(SIPMessage* message); 1023 1024 /** 1025 * Get an event for this transaction if any is available. 1026 * It provides default handling for invalid states, otherwise calls 1027 * the more specific protected version. 1028 * You may override this method if you need processing of invalid states. 1029 * @param pendingOnly True to only return outgoing and pending events 1030 * @param time Time to use in timeouts, zero to use system time 1031 * @return A newly allocated event or NULL if none is needed 1032 */ 1033 virtual SIPEvent* getEvent(bool pendingOnly = false, u_int64_t time = 0); 1034 1035 /** 1036 * Checks if a response message can be sent 1037 * @return True if the transaction can send a response message 1038 */ 1039 bool setResponse() const; 1040 1041 /** 1042 * Creates and transmits a final response message 1043 * @param code Response code to send 1044 * @param reason Human readable reason text (optional) 1045 * @return True if the message was queued for transmission 1046 */ 1047 bool setResponse(int code, const char* reason = 0); 1048 1049 /** 1050 * Transmits a final response message 1051 */ 1052 void setResponse(SIPMessage* message); 1053 1054 /** 1055 * Retrieve the latest response code 1056 * @return Code of most recent response, zero if none is known 1057 */ getResponseCode()1058 inline int getResponseCode() const 1059 { return m_response; } 1060 1061 /** 1062 * Transmit an ACK message in UAC mode 1063 * @param ackBody Optional ACK message body, consumed by the method 1064 * @return True if state was correct and the message was queued for transmission 1065 */ 1066 bool setAcknowledge(MimeBody* ackBody = 0); 1067 1068 /** 1069 * Message send failure notification 1070 * @param msg Failed message 1071 */ 1072 void msgTransmitFailed(SIPMessage* msg); 1073 1074 /** 1075 * Set an arbitrary pointer as user specific data 1076 */ setUserData(void * data)1077 inline void setUserData(void* data) 1078 { m_private = data; } 1079 1080 /** 1081 * Return the opaque user data 1082 */ getUserData()1083 inline void* getUserData() const 1084 { return m_private; } 1085 1086 /** 1087 * Silent this transaction 1088 */ 1089 void setSilent(); 1090 1091 /** 1092 * Trace ID of the transaction 1093 * @return Trace ID associated with this transaction 1094 */ traceId()1095 const String& traceId() const 1096 { return m_traceId; } 1097 1098 protected: 1099 /** 1100 * Constructor from previous auto authenticated transaction. This is used only internally 1101 * @param original Original transaction that failed authentication 1102 * @param answer SIP answer that creates the new transaction 1103 */ 1104 SIPTransaction(SIPTransaction& original, SIPMessage* answer); 1105 1106 /** 1107 * Pre-destruction notification used to clean up the transaction 1108 */ 1109 virtual void destroyed(); 1110 1111 /** 1112 * Attempt to perform automatic client transaction authentication 1113 * @param answer SIP answer that creates the new transaction 1114 * @return True if current client processing must be abandoned 1115 */ 1116 bool tryAutoAuth(SIPMessage* answer); 1117 1118 /** 1119 * Get an event only for client transactions 1120 * @param state The current state of the transaction 1121 * @param timeout If timeout occured, number of remaining timeouts, 1122 * otherwise -1 1123 * @return A newly allocated event or NULL if none is needed 1124 */ 1125 virtual SIPEvent* getClientEvent(int state, int timeout); 1126 1127 /** 1128 * Get an event only for server transactions. 1129 * @param state The current state of the transaction 1130 * @param timeout If timeout occured, number of remaining timeouts, 1131 * otherwise -1 1132 * @return A newly allocated event or NULL if none is needed 1133 */ 1134 virtual SIPEvent* getServerEvent(int state, int timeout); 1135 1136 /** 1137 * Process only the messages for client transactions 1138 * @param message A pointer to the message to process, should not be used 1139 * afterwards if this method returned True 1140 * @param state The current state of the transaction 1141 */ 1142 virtual void processClientMessage(SIPMessage* message, int state); 1143 1144 /** 1145 * Process only the messages for server transactions 1146 * @param message A pointer to the message to process, should not be used 1147 * afterwards if this method returned True 1148 * @param state The current state of the transaction 1149 */ 1150 virtual void processServerMessage(SIPMessage* message, int state); 1151 1152 /** 1153 * Change the transaction state 1154 * @param newstate The desired new state 1155 * @return True if state change occured 1156 */ 1157 bool changeState(int newstate); 1158 1159 /** 1160 * Set the latest message sent by this transaction 1161 * @param message Pointer to the latest message 1162 */ 1163 void setLatestMessage(SIPMessage* message = 0); 1164 1165 /** 1166 * Store a pending event to be picked up at the next @ref getEvent() call 1167 * @param event Event to store 1168 * @param replace True to replace any existing pending event 1169 */ 1170 void setPendingEvent(SIPEvent* event = 0, bool replace = false); 1171 1172 /** 1173 * Check if there is a pending event waiting 1174 * @return True is there is a pending event 1175 */ isPendingEvent()1176 inline bool isPendingEvent() const 1177 { return (m_pending != 0); } 1178 1179 /** 1180 * Set a repetitive timeout 1181 * @param delay How often (in microseconds) to fire the timeout 1182 * @param count How many times to keep firing the timeout 1183 */ 1184 void setTimeout(u_int64_t delay = 0, unsigned int count = 1); 1185 1186 bool m_outgoing; 1187 bool m_invite; 1188 bool m_transmit; 1189 int m_state; 1190 int m_response; 1191 unsigned int m_transCount; 1192 unsigned int m_timeouts; 1193 u_int64_t m_delay; 1194 u_int64_t m_timeout; 1195 SIPMessage* m_firstMessage; 1196 SIPMessage* m_lastMessage; 1197 SIPEvent* m_pending; 1198 SIPEngine* m_engine; 1199 String m_branch; 1200 String m_callid; 1201 String m_tag; 1202 void *m_private; 1203 bool m_autoChangeParty; 1204 bool m_autoAck; 1205 bool m_silent; 1206 String m_traceId; 1207 }; 1208 1209 /** 1210 * This object is an event that will be taken from SIPEngine 1211 * @short A SIP event as retrieved from engine 1212 */ 1213 class YSIP_API SIPEvent 1214 { 1215 friend class SIPTransaction; 1216 public: 1217 SIPEvent()1218 SIPEvent() 1219 : m_message(0), m_transaction(0), m_state(SIPTransaction::Invalid) 1220 { } 1221 1222 SIPEvent(SIPMessage* message, SIPTransaction* transaction = 0); 1223 1224 ~SIPEvent(); 1225 1226 /** 1227 * Get the SIP engine this event belongs to, if any 1228 * @return Pointer to owning SIP engine or NULL 1229 */ getEngine()1230 inline SIPEngine* getEngine() const 1231 { return m_transaction ? m_transaction->getEngine() : 0; } 1232 1233 /** 1234 * Get the SIP message this event is supposed to handle 1235 * @return Pointer to SIP message causing the event 1236 */ getMessage()1237 inline SIPMessage* getMessage() const 1238 { return m_message; } 1239 1240 /** 1241 * Get the SIP transaction that generated the event, if any 1242 * @return Pointer to owning SIP transaction or NULL 1243 */ getTransaction()1244 inline SIPTransaction* getTransaction() const 1245 { return m_transaction; } 1246 1247 /** 1248 * Check if the message is an outgoing message 1249 * @return True if the message should be sent to remote 1250 */ isOutgoing()1251 inline bool isOutgoing() const 1252 { return m_message && m_message->isOutgoing(); } 1253 1254 /** 1255 * Check if the message is an incoming message 1256 * @return True if the message is coming from remote 1257 */ isIncoming()1258 inline bool isIncoming() const 1259 { return m_message && !m_message->isOutgoing(); } 1260 1261 /** 1262 * Get the pointer to the endpoint this event uses 1263 */ getParty()1264 inline SIPParty* getParty() const 1265 { return m_message ? m_message->getParty() : 0; } 1266 1267 /** 1268 * Return the opaque user data stored in the transaction 1269 */ getUserData()1270 inline void* getUserData() const 1271 { return m_transaction ? m_transaction->getUserData() : 0; } 1272 1273 /** 1274 * The state of the transaction when the event was generated 1275 */ getState()1276 inline int getState() const 1277 { return m_state; } 1278 1279 /** 1280 * Check if the transaction was active when the event was generated 1281 * @return True if the transaction was active, false if it finished 1282 */ isActive()1283 inline bool isActive() const 1284 { return (SIPTransaction::Invalid < m_state) && (m_state < SIPTransaction::Finish); } 1285 1286 /** 1287 * Retrieve the trace ID associated with this event 1288 * @return The trace ID, it can be empty. 1289 */ traceId()1290 inline const String& traceId() const 1291 { return m_transaction ? m_transaction->traceId() : String::empty(); } 1292 1293 protected: 1294 SIPMessage* m_message; 1295 SIPTransaction* m_transaction; 1296 int m_state; 1297 }; 1298 1299 /** 1300 * The SIP engine holds common methods and the list of current transactions 1301 * @short The SIP engine and transaction list 1302 */ 1303 class YSIP_API SIPEngine : public DebugEnabler, public Mutex 1304 { 1305 public: 1306 /** 1307 * Create the SIP Engine 1308 */ 1309 SIPEngine(const char* userAgent = 0); 1310 1311 /** 1312 * Destroy the SIP Engine 1313 */ 1314 virtual ~SIPEngine(); 1315 1316 /** 1317 * Build a new SIPParty for a message 1318 * @param message Pointer to the message to build the party 1319 * @return True on success, false if party could not be built 1320 */ 1321 virtual bool buildParty(SIPMessage* message) = 0; 1322 1323 /** 1324 * Allocate a new trace ID. If tracing is not active, string will not be modified 1325 * @param id String where to put allocated ID. 1326 */ 1327 virtual void allocTraceId(String& id) = 0; 1328 1329 /** 1330 * Print a SIP message only if it has a trace ID 1331 * @param message The message to print 1332 * @param incoming True if the message is incoming 1333 */ 1334 virtual void traceMsg(SIPMessage* message, bool incoming = true) = 0; 1335 1336 /** 1337 * Check user credentials for validity 1338 * @param username User account name 1339 * @param realm Authentication realm 1340 * @param nonce Authentication opaque nonce generated by the server 1341 * @param method Method of the SIP message that is being authenticated 1342 * @param uri URI of the SIP message that is being authenticated 1343 * @param response Response computed by the authenticated entity 1344 * @param message Message that is to be authenticated 1345 * @param authLine Extra credentials line to validate 1346 * @param userData Pointer to an optional object passed from @ref authUser 1347 * @return True if valid user/password, false if verification failed 1348 */ 1349 virtual bool checkUser(String& username, const String& realm, const String& nonce, 1350 const String& method, const String& uri, const String& response, 1351 const SIPMessage* message, const MimeHeaderLine* authLine, GenObject* userData); 1352 1353 /** 1354 * Authenticate a message by other means than user credentials. By default 1355 * it calls @ref checkUser with empty user credential fields 1356 * @param noUser No plausible user credentials were detected so far 1357 * @param username User account name 1358 * @param message Message that is to be authenticated 1359 * @param authLine Extra credentials line to validate 1360 * @param userData Pointer to an optional object passed from @ref authUser 1361 * @return True if message is authenticated, false if verification failed 1362 */ 1363 virtual bool checkAuth(bool noUser, String& username, const SIPMessage* message, 1364 const MimeHeaderLine* authLine, GenObject* userData); 1365 1366 /** 1367 * Detect the proper credentials for any user in the engine 1368 * @param message Pointer to the message to check 1369 * @param user String to store the authenticated user name or user to 1370 * look for (if not null on entry) 1371 * @param proxy True to authenticate as proxy, false as user agent 1372 * @param userData Pointer to an optional object that is passed back to @ref checkUser 1373 * @return Age of the nonce if user matches, negative for a failure 1374 */ 1375 int authUser(const SIPMessage* message, String& user, bool proxy = false, GenObject* userData = 0); 1376 1377 /** 1378 * Add a message into the transaction list 1379 * @param ep Party of the received message 1380 * @param buf A buffer containing the SIP message text 1381 * @param len The length of the message or -1 to interpret as C string 1382 * @return Pointer to the transaction or NULL if message was invalid 1383 */ 1384 SIPTransaction* addMessage(SIPParty* ep, const char* buf, int len = -1); 1385 1386 /** 1387 * Add a message into the transaction list 1388 * This method is thread safe 1389 * @param message A parsed SIP message to add to the transactions 1390 * @param autoChangeParty Optional auto change party to set in transaction if a new one is created 1391 * @return Pointer to the transaction or NULL if message was invalid 1392 */ 1393 SIPTransaction* addMessage(SIPMessage* message, bool* autoChangeParty = 0); 1394 1395 /** 1396 * Get a SIPEvent from the queue. 1397 * This method mainly looks into the transaction list and get all kind of 1398 * events, like an incoming request (INVITE, REGISTRATION), a timer, an 1399 * outgoing message. 1400 * This method is thread safe 1401 */ 1402 SIPEvent *getEvent(); 1403 1404 /** 1405 * This method should be called very often to get the events from the list and 1406 * to send them to processEvent method. 1407 * @return True if some events were processed this turn 1408 */ 1409 bool process(); 1410 1411 /** 1412 * Default handling for events. 1413 * This method should be overriden for what you need and at the end you 1414 * should call this default one 1415 * This method is thread safe 1416 */ 1417 virtual void processEvent(SIPEvent *event); 1418 1419 /** 1420 * Handle answers that create new dialogs for an outgoing INVITE 1421 * @param answer The message that creates the INVITE fork 1422 * @param trans One of the transactions part of the same INVITE 1423 * @return Pointer to new transaction or NULL if message is ignored 1424 */ 1425 virtual SIPTransaction* forkInvite(SIPMessage* answer, SIPTransaction* trans); 1426 1427 /** 1428 * Get the timeout to be used for transactions involving human interaction. 1429 * The default implementation returns the proxy INVITE timeout (timer C = 3 minutes) 1430 * minus the INVITE response retransmit interval (timer T2 = 4 seconds) 1431 * @return Duration of the timeout in microseconds 1432 */ 1433 virtual u_int64_t getUserTimeout() const; 1434 1435 /** 1436 * Get the length of a timer 1437 * @param which A one-character constant that selects which timer to return 1438 * @param reliable Whether we request the timer value for a reliable protocol 1439 * @return Duration of the selected timer or 0 if invalid 1440 */ 1441 u_int64_t getTimer(char which, bool reliable = false) const; 1442 1443 /** 1444 * Get the number of times to send a SIP request. 1445 * This value applies only when retransmission is required 1446 * @return The number of times to send a SIP request 1447 */ getReqTransCount()1448 inline unsigned int getReqTransCount() const 1449 { return m_reqTransCount; } 1450 1451 /** 1452 * Get the number of times to send a response to a SIP request. 1453 * This value applies only when retransmission is required 1454 * @return The number of times to send a response to a SIP request 1455 */ getRspTransCount()1456 inline unsigned int getRspTransCount() const 1457 { return m_rspTransCount; } 1458 1459 /** 1460 * Get the default value of the Max-Forwards header for this engine 1461 * @return The maximum number of hops the request is allowed to pass 1462 */ getMaxForwards()1463 inline unsigned int getMaxForwards() const 1464 { return m_maxForwards; } 1465 1466 /** 1467 * Get the User agent for this SIP engine 1468 */ getUserAgent()1469 inline const String& getUserAgent() const 1470 { return m_userAgent; } 1471 1472 /** 1473 * Get the Command Sequence Number generator 1474 * @return Pointer to the CSeq generator of this engine 1475 */ getSequence()1476 inline SIPSequence* getSequence() const 1477 { return m_seq; } 1478 1479 /** 1480 * Get a CSeq value suitable for use in a new request 1481 * @return New CSeq value 1482 */ getNextCSeq()1483 inline int32_t getNextCSeq() 1484 { return m_seq->getNextCSeq(); } 1485 1486 /** 1487 * Check if the engine is set up for lazy "100 Trying" messages 1488 * @return True if the first 100 message is to be skipped for non-INVITE 1489 */ lazyTrying()1490 inline bool lazyTrying() const 1491 { return m_lazyTrying; } 1492 1493 /** 1494 * Set the lazy "100 Trying" messages flag 1495 * @param lazy100 True to not send the 1st 100 message for non-INVITE 1496 */ lazyTrying(bool lazy100)1497 inline void lazyTrying(bool lazy100) 1498 { m_lazyTrying = lazy100; } 1499 1500 /** 1501 * Retrieve various flags for this engine 1502 * @return Value of flags ORed together 1503 */ flags()1504 inline int flags() const 1505 { return m_flags; } 1506 1507 /** 1508 * Check if message party should be changed from latest dialog party 1509 * @return Value of auto change party option 1510 */ autoChangeParty()1511 inline bool autoChangeParty() const 1512 { return m_autoChangeParty; } 1513 1514 /** 1515 * Get an authentication nonce 1516 * @param nonce String reference to fill with the current nonce 1517 */ 1518 void nonceGet(String& nonce); 1519 1520 /** 1521 * Get the age of an authentication nonce 1522 * @param nonce String nonce to check for validity and age 1523 * @return Age of the nonce in seconds, negative for invalid 1524 */ 1525 long nonceAge(const String& nonce); 1526 1527 /** 1528 * Get a nonce count 1529 * @param nc String reference to fill with new nonce count 1530 */ 1531 void ncGet(String& nc); 1532 1533 /** 1534 * Build an authentication response 1535 * @param username User account name 1536 * @param realm Authentication realm 1537 * @param passwd Account password 1538 * @param nonce Authentication opaque nonce generated by the server 1539 * @param method Method of the SIP message that is being authenticated 1540 * @param uri URI of the SIP message that is being authenticated 1541 * @param response String to store the computed response 1542 * @param qop Optional quality of protection type (set in list name) and parameters 1543 */ 1544 static void buildAuth(const String& username, const String& realm, const String& passwd, 1545 const String& nonce, const String& method, const String& uri, String& response, 1546 const NamedList& qop = NamedList::empty()); 1547 1548 /** 1549 * Build an authentication response from already hashed components 1550 * @param hash_a1 MD5 digest of username:realm:password 1551 * @param nonce Authentication opaque nonce generated by the server 1552 * @param hash_a2 MD5 digest of method:uri 1553 * @param response String to store the computed response 1554 */ 1555 static void buildAuth(const String& hash_a1, const String& nonce, const String& hash_a2, 1556 String& response); 1557 1558 /** 1559 * Check if a method is in the allowed methods list 1560 * @param method Uppercase name of the method to check 1561 * @return True if the method should be allowed processing 1562 */ 1563 bool isAllowed(const char* method) const; 1564 1565 /** 1566 * Add a method to the allowed methods list 1567 * @param method Uppercase name of the method to add 1568 */ 1569 void addAllowed(const char* method); 1570 1571 /** 1572 * Get all the allowed methods 1573 * @return Comma separated list of allowed methods 1574 */ getAllowed()1575 inline const String& getAllowed() const 1576 { return m_allowed; } 1577 1578 /** 1579 * Remove a transaction from the list without dereferencing it 1580 * @param transaction Pointer to transaction to remove 1581 */ remove(SIPTransaction * transaction)1582 inline void remove(SIPTransaction* transaction) 1583 { lock(); m_transList.remove(transaction,false); unlock(); } 1584 1585 /** 1586 * Append a transaction to the end of the list 1587 * @param transaction Pointer to transaction to append 1588 */ append(SIPTransaction * transaction)1589 inline void append(SIPTransaction* transaction) 1590 { lock(); m_transList.append(transaction); unlock(); } 1591 1592 /** 1593 * Insert a transaction at the start of the list 1594 * @param transaction Pointer to transaction to insert 1595 */ insert(SIPTransaction * transaction)1596 inline void insert(SIPTransaction* transaction) 1597 { lock(); m_transList.insert(transaction); unlock(); } 1598 1599 /** 1600 * Get the number of active SIP transactions 1601 * @return Count of transactions in the list 1602 */ transactionCount()1603 inline unsigned int transactionCount() 1604 { Lock mylock(this); return m_transList.count(); } 1605 1606 protected: 1607 /** 1608 * The list that holds all the SIP transactions. 1609 */ 1610 ObjList m_transList; 1611 1612 u_int64_t m_t1; 1613 u_int64_t m_t4; 1614 int m_reqTransCount; 1615 int m_rspTransCount; 1616 unsigned int m_maxForwards; 1617 int m_flags; 1618 bool m_lazyTrying; 1619 String m_userAgent; 1620 String m_allowed; 1621 RefPointer<SIPSequence> m_seq; 1622 u_int32_t m_nc; 1623 String m_nonce; 1624 String m_nonce_secret; 1625 u_int32_t m_nonce_time; 1626 Mutex m_nonce_mutex; 1627 bool m_autoChangeParty; 1628 }; 1629 1630 } 1631 1632 #endif /* __YATESIP_H */ 1633 1634 /* vi: set ts=8 sw=4 sts=4 noet: */ 1635