1 /* 2 * sippdu.h 3 * 4 * Session Initiation Protocol PDU support. 5 * 6 * Open Phone Abstraction Library (OPAL) 7 * Formally known as the Open H323 project. 8 * 9 * Copyright (c) 2002 Equivalence Pty. Ltd. 10 * 11 * The contents of this file are subject to the Mozilla Public License 12 * Version 1.0 (the "License"); you may not use this file except in 13 * compliance with the License. You may obtain a copy of the License at 14 * http://www.mozilla.org/MPL/ 15 * 16 * Software distributed under the License is distributed on an "AS IS" 17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 18 * the License for the specific language governing rights and limitations 19 * under the License. 20 * 21 * The Original Code is Open Phone Abstraction Library. 22 * 23 * The Initial Developer of the Original Code is Equivalence Pty. Ltd. 24 * 25 * Contributor(s): ______________________________________. 26 * 27 * $Revision: 29080 $ 28 * $Author: rjongbloed $ 29 * $Date: 2013-02-12 18:52:05 -0600 (Tue, 12 Feb 2013) $ 30 */ 31 32 #ifndef OPAL_SIP_SIPPDU_H 33 #define OPAL_SIP_SIPPDU_H 34 35 #ifdef P_USE_PRAGMA 36 #pragma interface 37 #endif 38 39 #include <opal/buildopts.h> 40 41 #if OPAL_SIP 42 43 #include <ptclib/mime.h> 44 #include <ptclib/url.h> 45 #include <ptclib/http.h> 46 #include <sip/sdp.h> 47 #include <opal/rtpconn.h> 48 49 50 class OpalTransport; 51 class OpalTransportAddress; 52 class OpalProductInfo; 53 54 class SIPEndPoint; 55 class SIPConnection; 56 class SIP_PDU; 57 class SIPSubscribeHandler; 58 class SIPDialogContext; 59 class SIPMIMEInfo; 60 61 62 ///////////////////////////////////////////////////////////////////////// 63 // SIPURL 64 65 /** This class extends PURL to include displayname, optional "<>" delimiters 66 and extended parameters - like tag. 67 It may be used for From:, To: and Contact: lines. 68 */ 69 70 class SIPURL : public PURL 71 { 72 PCLASSINFO(SIPURL, PURL); 73 public: 74 SIPURL(); 75 SIPURL(const PURL & url)76 SIPURL( 77 const PURL & url 78 ) : PURL(url) { } 79 SIPURL & operator=( 80 const PURL & url 81 ) { PURL::operator=(url); return *this; } 82 83 /** str goes straight to Parse() 84 */ 85 SIPURL( 86 const char * cstr, ///< C string representation of the URL. 87 const char * defaultScheme = NULL ///< Default scheme for URL 88 ); 89 SIPURL & operator=( 90 const char * cstr 91 ) { Parse(cstr); return *this; } 92 93 /** str goes straight to Parse() 94 */ 95 SIPURL( 96 const PString & str, ///< String representation of the URL. 97 const char * defaultScheme = NULL ///< Default scheme for URL 98 ); 99 SIPURL & operator=( 100 const PString & str 101 ) { Parse(str); return *this; } 102 103 /** If name does not start with 'sip' then construct URI in the form 104 <pre><code> 105 sip:name\@host:port;transport=transport 106 </code></pre> 107 where host comes from address, 108 port is listenerPort or port from address if that was 0 109 transport is udp unless address specified tcp 110 Send name starting with 'sip' or constructed URI to Parse() 111 */ 112 SIPURL( 113 const PString & name, 114 const OpalTransportAddress & address, 115 WORD listenerPort = 0 116 ); 117 118 SIPURL( 119 const OpalTransportAddress & address, 120 WORD listenerPort = 0 121 ); 122 SIPURL & operator=( 123 const OpalTransportAddress & address 124 ); 125 126 SIPURL( 127 const SIPMIMEInfo & mime, 128 const char * name 129 ); 130 131 /**Compare the two SIPURLs and return their relative rank. 132 Note that does an intelligent comparison according to the rules 133 in RFC3261 Section 19.1.4. 134 135 @return 136 <code>LessThan</code>, <code>EqualTo</code> or <code>GreaterThan</code> 137 according to the relative rank of the objects. 138 */ 139 virtual Comparison Compare( 140 const PObject & obj ///< Object to compare against. 141 ) const; 142 143 /** Returns complete SIPURL as one string, including displayname (in 144 quotes) and address in angle brackets. 145 */ 146 PString AsQuotedString() const; 147 148 /** Returns display name only 149 */ 150 PString GetDisplayName(PBoolean useDefault = true) const; 151 SetDisplayName(const PString & str)152 void SetDisplayName(const PString & str) 153 { 154 m_displayName = str; 155 } 156 157 /// Return string options in field parameters GetFieldParameters()158 const PStringOptions & GetFieldParameters() const { return m_fieldParameters; } GetFieldParameters()159 PStringOptions & GetFieldParameters() { return m_fieldParameters; } 160 161 /**Get the host and port as a transport address. 162 */ 163 OpalTransportAddress GetHostAddress() const; 164 165 /**Set the host and port as a transport address. 166 */ 167 void SetHostAddress(const OpalTransportAddress & addr); 168 169 enum UsageContext { 170 ExternalURI, ///< URI used anywhere outside of protocol 171 RequestURI, ///< Request-URI (after the INVITE) 172 ToURI, ///< To header field 173 FromURI, ///< From header field 174 RouteURI, ///< Record-Route header field 175 RedirectURI, ///< Redirect Contact header field 176 ContactURI, ///< General Contact header field 177 RegContactURI, ///< Registration Contact header field 178 RegisterURI ///< URI on REGISTER request line. 179 }; 180 181 /** Removes tag parm & query vars and recalculates urlString 182 (scheme, user, password, host, port & URI parms (like transport)) 183 which are not allowed in the context specified, e.g. Request-URI etc 184 According to RFC3261, 19.1.1 Table 1 185 */ 186 void Sanitise( 187 UsageContext context ///< Context for URI 188 ); 189 190 /** This will adjust the current URL according to RFC3263, using DNS SRV records. 191 192 @return FALSE if DNS is available but entry is larger than last SRV record entry, 193 TRUE if DNS lookup fails or no DNS is available 194 */ 195 PBoolean AdjustToDNS( 196 PINDEX entry = 0 /// Entry in the SRV record to adjust to 197 ); 198 199 /// Generate a unique string suitable as a dialog tag 200 static PString GenerateTag(); 201 202 /// Set a tag with a new unique ID. 203 void SetTag( 204 const PString & tag = PString::Empty(), 205 bool force = false 206 ); 207 208 protected: 209 void ParseAsAddress(const PString & name, const OpalTransportAddress & _address, WORD listenerPort = 0); 210 211 // Override from PURL() InternalParse(const char * cstr,const char * defaultScheme)212 virtual PBoolean InternalParse( 213 const char * cstr, 214 const char * defaultScheme 215 ) { return ReallyInternalParse(false, cstr, defaultScheme); } 216 217 bool ReallyInternalParse( 218 bool fromField, 219 const char * cstr, 220 const char * defaultScheme 221 ); 222 223 PString m_displayName; 224 PStringOptions m_fieldParameters; 225 }; 226 227 228 class SIPURLList : public std::list<SIPURL> 229 { 230 public: 231 bool FromString( 232 const PString & str, 233 SIPURL::UsageContext context = SIPURL::RouteURI, 234 bool reversed = false 235 ); 236 PString ToString() const; 237 friend ostream & operator<<(ostream & strm, const SIPURLList & urls); 238 }; 239 240 241 242 ///////////////////////////////////////////////////////////////////////// 243 // SIPMIMEInfo 244 245 /** Session Initiation Protocol MIME info container 246 This is a string dictionary: for each item mime header is key, value 247 is value. 248 Headers may be full ("From") or compact ("f"). Colons not included. 249 PMIMEInfo::ReadFrom (>>) parses from stream. That adds a header-value 250 element for each mime line. If a mime header is duplicated in the 251 stream then the additional value is appended to the existing, 252 separated by "/n". 253 PMIMEInfo::ReadFrom supports multi-line values if the next line starts 254 with a space - it just appends the next line to the existing string 255 with the separating space. 256 There is no checking of header names or values. 257 compactForm decides whether 'Set' methods store full or compact headers. 258 'Set' methods replace values, there is no method for appending except 259 ReadFrom. 260 'Get' methods work whether stored headers are full or compact. 261 262 to do to satisfy RFC3261 (mandatory(*) & should): 263 Accept 264 Accept-Encoding 265 Accept-Language 266 *Allow 267 *Max-Forwards 268 *Min-Expires 269 *Proxy-Authenticate 270 Supported 271 *Unsupported 272 *WWW-Authenticate 273 */ 274 275 class SIPMIMEInfo : public PMIMEInfo 276 { 277 PCLASSINFO(SIPMIMEInfo, PMIMEInfo); 278 public: 279 SIPMIMEInfo(bool compactForm = false); 280 281 virtual void PrintOn(ostream & strm) const; 282 virtual bool InternalAddMIME(const PString & fieldName, const PString & fieldValue); 283 SetCompactForm(bool form)284 void SetCompactForm(bool form) { compactForm = form; } 285 286 PCaselessString GetContentType(bool includeParameters = false) const; 287 void SetContentType(const PString & v); 288 289 PCaselessString GetContentEncoding() const; 290 void SetContentEncoding(const PString & v); 291 292 SIPURL GetFrom() const; 293 void SetFrom(const PString & v); 294 295 SIPURL GetPAssertedIdentity() const; 296 void SetPAssertedIdentity(const PString & v); 297 298 SIPURL GetPPreferredIdentity() const; 299 void SetPPreferredIdentity(const PString & v); 300 301 PString GetAccept() const; 302 void SetAccept(const PString & v); 303 304 PString GetAcceptEncoding() const; 305 void SetAcceptEncoding(const PString & v); 306 307 PString GetAcceptLanguage() const; 308 void SetAcceptLanguage(const PString & v); 309 310 PString GetAllow() const; 311 unsigned GetAllowBitMask() const; 312 void SetAllow(const PString & v); 313 314 PString GetCallID() const; 315 void SetCallID(const PString & v); 316 317 SIPURL GetContact() const; 318 bool GetContacts(SIPURLList & contacts) const; 319 void SetContact(const PString & v); 320 321 PString GetSubject() const; 322 void SetSubject(const PString & v); 323 324 SIPURL GetTo() const; 325 void SetTo(const PString & v); 326 327 PString GetVia() const; 328 void SetVia(const PString & v); 329 330 bool GetViaList(PStringList & v) const; 331 void SetViaList(const PStringList & v); 332 333 PString GetFirstVia() const; 334 OpalTransportAddress GetViaReceivedAddress() const; 335 336 SIPURL GetReferTo() const; 337 void SetReferTo(const PString & r); 338 339 SIPURL GetReferredBy() const; 340 void SetReferredBy(const PString & r); 341 342 PINDEX GetContentLength() const; 343 void SetContentLength(PINDEX v); 344 PBoolean IsContentLengthPresent() const; 345 346 PString GetCSeq() const; 347 void SetCSeq(const PString & v); 348 349 PString GetDate() const; 350 void SetDate(const PString & v); 351 void SetDate(const PTime & t); 352 void SetDate(void); // set to current date 353 354 unsigned GetExpires(unsigned dflt = UINT_MAX) const;// returns default value if not found 355 void SetExpires(unsigned v); 356 357 PINDEX GetMaxForwards() const; 358 void SetMaxForwards(PINDEX v); 359 360 PINDEX GetMinExpires() const; 361 void SetMinExpires(PINDEX v); 362 363 PString GetProxyAuthenticate() const; 364 void SetProxyAuthenticate(const PString & v); 365 366 PString GetRoute() const; 367 bool GetRoute(SIPURLList & proxies) const; 368 void SetRoute(const PString & v); 369 void SetRoute(const SIPURLList & proxies); 370 371 PString GetRecordRoute() const; 372 bool GetRecordRoute(SIPURLList & proxies, bool reversed) const; 373 void SetRecordRoute(const PString & v); 374 void SetRecordRoute(const SIPURLList & proxies); 375 GetCSeqIndex()376 unsigned GetCSeqIndex() const { return GetCSeq().AsUnsigned(); } 377 378 PStringSet GetRequire() const; 379 void SetRequire(const PStringSet & v); 380 void AddRequire(const PString & v); 381 382 PStringSet GetSupported() const; 383 void SetSupported(const PStringSet & v); 384 void AddSupported(const PString & v); 385 386 PStringSet GetUnsupported() const; 387 void SetUnsupported(const PStringSet & v); 388 void AddUnsupported(const PString & v); 389 390 PString GetEvent() const; 391 void SetEvent(const PString & v); 392 393 PCaselessString GetSubscriptionState(PStringToString & info) const; 394 void SetSubscriptionState(const PString & v); 395 396 PString GetUserAgent() const; 397 void SetUserAgent(const PString & v); 398 399 PString GetOrganization() const; 400 void SetOrganization(const PString & v); 401 402 void GetProductInfo(OpalProductInfo & info) const; 403 void SetProductInfo(const PString & ua, const OpalProductInfo & info); 404 405 PString GetWWWAuthenticate() const; 406 void SetWWWAuthenticate(const PString & v); 407 408 PString GetSIPIfMatch() const; 409 void SetSIPIfMatch(const PString & v); 410 411 PString GetSIPETag() const; 412 void SetSIPETag(const PString & v); 413 414 void GetAlertInfo(PString & info, int & appearance); 415 void SetAlertInfo(const PString & info, int appearance); 416 417 PString GetCallInfo() const; 418 419 PString GetAllowEvents() const; 420 void SetAllowEvents(const PString & v); 421 422 /** return the value of a header field parameter, empty if none 423 */ 424 PString GetFieldParameter( 425 const PString & fieldName, ///< Field name in dictionary 426 const PString & paramName, ///< Field parameter name 427 const PString & defaultValue = PString::Empty() ///< Default value for parameter 428 ) const { return ExtractFieldParameter((*this)(fieldName), paramName, defaultValue); } 429 430 /** set the value for a header field parameter, replace the 431 * current value, or add the parameter and its 432 * value if not already present. 433 */ SetFieldParameter(const PString & fieldName,const PString & paramName,const PString & newValue)434 void SetFieldParameter( 435 const PString & fieldName, ///< Field name in dictionary 436 const PString & paramName, ///< Field parameter name 437 const PString & newValue ///< New value for parameter 438 ) { SetAt(fieldName, InsertFieldParameter((*this)(fieldName), paramName, newValue)); } 439 440 /** return the value of a header field parameter, empty if none 441 */ 442 static PString ExtractFieldParameter( 443 const PString & fieldValue, ///< Value of field string 444 const PString & paramName, ///< Field parameter name 445 const PString & defaultValue = PString::Empty() ///< Default value for parameter 446 ); 447 448 /** set the value for a header field parameter, replace the 449 * current value, or add the parameter and its 450 * value if not already present. 451 */ 452 static PString InsertFieldParameter( 453 const PString & fieldValue, ///< Value of field string 454 const PString & paramName, ///< Field parameter name 455 const PString & newValue ///< New value for parameter 456 ); 457 458 protected: 459 PStringSet GetTokenSet(const char * field) const; 460 void AddTokenSet(const char * field, const PString & token); 461 void SetTokenSet(const char * field, const PStringSet & tokens); 462 463 /// Encode using compact form 464 bool compactForm; 465 }; 466 467 468 ///////////////////////////////////////////////////////////////////////// 469 // SIPAuthentication 470 471 typedef PHTTPClientAuthentication SIPAuthentication; 472 473 class SIPAuthenticator : public PHTTPClientAuthentication::AuthObject 474 { 475 public: 476 SIPAuthenticator(SIP_PDU & pdu); 477 virtual PMIMEInfo & GetMIME(); 478 virtual PString GetURI(); 479 virtual PString GetEntityBody(); 480 virtual PString GetMethod(); 481 482 protected: 483 SIP_PDU & m_pdu; 484 }; 485 486 487 488 ///////////////////////////////////////////////////////////////////////// 489 // SIP_PDU 490 491 /** Session Initiation Protocol message. 492 Each message contains a header, MIME lines and possibly SDP. 493 Class provides methods for reading from and writing to transport. 494 */ 495 496 class SIP_PDU : public PSafeObject 497 { 498 PCLASSINFO(SIP_PDU, PSafeObject); 499 public: 500 enum Methods { 501 Method_INVITE, 502 Method_ACK, 503 Method_OPTIONS, 504 Method_BYE, 505 Method_CANCEL, 506 Method_REGISTER, 507 Method_SUBSCRIBE, 508 Method_NOTIFY, 509 Method_REFER, 510 Method_MESSAGE, 511 Method_INFO, 512 Method_PING, 513 Method_PUBLISH, 514 Method_PRACK, 515 NumMethods 516 }; 517 518 enum StatusCodes { 519 IllegalStatusCode, 520 Local_TransportError, 521 Local_BadTransportAddress, 522 Local_Timeout, 523 524 Information_Trying = 100, 525 Information_Ringing = 180, 526 Information_CallForwarded = 181, 527 Information_Queued = 182, 528 Information_Session_Progress = 183, 529 530 Successful_OK = 200, 531 Successful_Accepted = 202, 532 533 Redirection_MultipleChoices = 300, 534 Redirection_MovedPermanently = 301, 535 Redirection_MovedTemporarily = 302, 536 Redirection_UseProxy = 305, 537 Redirection_AlternativeService = 380, 538 539 Failure_BadRequest = 400, 540 Failure_UnAuthorised = 401, 541 Failure_PaymentRequired = 402, 542 Failure_Forbidden = 403, 543 Failure_NotFound = 404, 544 Failure_MethodNotAllowed = 405, 545 Failure_NotAcceptable = 406, 546 Failure_ProxyAuthenticationRequired = 407, 547 Failure_RequestTimeout = 408, 548 Failure_Conflict = 409, 549 Failure_Gone = 410, 550 Failure_LengthRequired = 411, 551 Failure_RequestEntityTooLarge = 413, 552 Failure_RequestURITooLong = 414, 553 Failure_UnsupportedMediaType = 415, 554 Failure_UnsupportedURIScheme = 416, 555 Failure_BadExtension = 420, 556 Failure_ExtensionRequired = 421, 557 Failure_IntervalTooBrief = 423, 558 Failure_TemporarilyUnavailable = 480, 559 Failure_TransactionDoesNotExist = 481, 560 Failure_LoopDetected = 482, 561 Failure_TooManyHops = 483, 562 Failure_AddressIncomplete = 484, 563 Failure_Ambiguous = 485, 564 Failure_BusyHere = 486, 565 Failure_RequestTerminated = 487, 566 Failure_NotAcceptableHere = 488, 567 Failure_BadEvent = 489, 568 Failure_RequestPending = 491, 569 Failure_Undecipherable = 493, 570 571 Failure_InternalServerError = 500, 572 Failure_NotImplemented = 501, 573 Failure_BadGateway = 502, 574 Failure_ServiceUnavailable = 503, 575 Failure_ServerTimeout = 504, 576 Failure_SIPVersionNotSupported = 505, 577 Failure_MessageTooLarge = 513, 578 579 GlobalFailure_BusyEverywhere = 600, 580 GlobalFailure_Decline = 603, 581 GlobalFailure_DoesNotExistAnywhere = 604, 582 GlobalFailure_NotAcceptable = 606, 583 584 MaxStatusCode = 699 585 }; 586 587 static const char * GetStatusCodeDescription(int code); 588 friend ostream & operator<<(ostream & strm, StatusCodes status); 589 590 SIP_PDU( 591 Methods method = SIP_PDU::NumMethods 592 ); 593 594 /** Construct a Response message 595 extra is passed as message body 596 */ 597 SIP_PDU( 598 const SIP_PDU & request, 599 StatusCodes code, 600 const SDPSessionDescription * sdp = NULL 601 ); 602 603 SIP_PDU(const SIP_PDU &); 604 SIP_PDU & operator=(const SIP_PDU &); 605 ~SIP_PDU(); 606 607 void PrintOn( 608 ostream & strm 609 ) const; 610 611 void InitialiseHeaders( 612 const SIPURL & dest, 613 const SIPURL & to, 614 const SIPURL & from, 615 const PString & callID, 616 unsigned cseq, 617 const PString & via 618 ); 619 void InitialiseHeaders( 620 SIPDialogContext & dialog, 621 const PString & via = PString::Empty(), 622 unsigned cseq = 0 623 ); 624 void InitialiseHeaders( 625 SIPConnection & connection, 626 const OpalTransport & transport, 627 unsigned cseq = 0 628 ); 629 void InitialiseHeaders( 630 const SIP_PDU & request 631 ); 632 633 /**Add and populate Route header following the given routeSet. 634 If first route is strict, exchange with URI. 635 Returns true if routeSet. 636 */ 637 bool SetRoute(const SIPURLList & routeSet); 638 bool SetRoute(const SIPURL & proxy); 639 640 /**Set mime allow field to all supported methods. 641 */ 642 void SetAllow(unsigned bitmask); 643 644 /**Update the VIA field following RFC3261, 18.2.1 and RFC3581. 645 */ 646 void AdjustVia(OpalTransport & transport); 647 648 PString CreateVia( 649 SIPEndPoint & endpoint, 650 const OpalTransport & transport 651 ); 652 653 /**Read PDU from the specified transport. 654 */ 655 SIP_PDU::StatusCodes Read( 656 OpalTransport & transport 657 ); 658 659 /**Write the PDU to the transport. 660 */ 661 PBoolean Write( 662 OpalTransport & transport, 663 const OpalTransportAddress & remoteAddress = OpalTransportAddress(), 664 const PString & localInterface = PString::Empty() 665 ); 666 667 /**Write PDU as a response to a request. 668 */ 669 bool SendResponse( 670 OpalTransport & transport, 671 StatusCodes code, 672 SIPEndPoint * endpoint = NULL 673 ) const; 674 bool SendResponse( 675 OpalTransport & transport, 676 SIP_PDU & response, 677 SIPEndPoint * endpoint = NULL 678 ) const; 679 680 /** Construct the PDU string to output. 681 Returns the total length of the PDU. 682 */ 683 PString Build(); 684 685 PString GetTransactionID() const; 686 GetMethod()687 Methods GetMethod() const { return m_method; } GetStatusCode()688 StatusCodes GetStatusCode () const { return m_statusCode; } SetStatusCode(StatusCodes c)689 void SetStatusCode (StatusCodes c) { m_statusCode = c; } GetURI()690 const SIPURL & GetURI() const { return m_uri; } SetURI(const SIPURL & newuri)691 void SetURI(const SIPURL & newuri) { m_uri = newuri; } GetVersionMajor()692 unsigned GetVersionMajor() const { return m_versionMajor; } GetVersionMinor()693 unsigned GetVersionMinor() const { return m_versionMinor; } 694 void SetCSeq(unsigned cseq); GetEntityBody()695 const PString & GetEntityBody() const { return m_entityBody; } SetEntityBody(const PString & body)696 void SetEntityBody(const PString & body) { m_entityBody = body; } 697 void SetEntityBody(); GetInfo()698 const PString & GetInfo() const { return m_info; } SetInfo(const PString & info)699 void SetInfo(const PString & info) { m_info = info; } GetMIME()700 const SIPMIMEInfo & GetMIME() const { return m_mime; } GetMIME()701 SIPMIMEInfo & GetMIME() { return m_mime; } 702 SDPSessionDescription * GetSDP(const OpalMediaFormatList & masterList); 703 void SetSDP(SDPSessionDescription * sdp); 704 705 protected: 706 Methods m_method; // Request type, ==NumMethods for Response 707 StatusCodes m_statusCode; 708 SIPURL m_uri; // display name & URI, no tag 709 unsigned m_versionMajor; 710 unsigned m_versionMinor; 711 PString m_info; 712 SIPMIMEInfo m_mime; 713 PString m_entityBody; 714 715 SDPSessionDescription * m_SDP; 716 717 mutable PString m_transactionID; 718 }; 719 720 721 PQUEUE(SIP_PDU_Queue, SIP_PDU); 722 723 724 #if PTRACING 725 ostream & operator<<(ostream & strm, SIP_PDU::Methods method); 726 #endif 727 728 729 ///////////////////////////////////////////////////////////////////////// 730 // SIPDialogContext 731 732 /** Session Initiation Protocol dialog context information. 733 */ 734 class SIPDialogContext 735 { 736 public: 737 SIPDialogContext(); 738 SIPDialogContext(const SIPMIMEInfo & mime); 739 740 PString AsString() const; 741 bool FromString( 742 const PString & str 743 ); 744 GetCallID()745 const PString & GetCallID() const { return m_callId; } SetCallID(const PString & id)746 void SetCallID(const PString & id) { m_callId = id; } 747 GetRequestURI()748 const SIPURL & GetRequestURI() const { return m_requestURI; } SetRequestURI(const SIPURL & url)749 void SetRequestURI(const SIPURL & url) { m_requestURI = url; } 750 GetLocalTag()751 const PString & GetLocalTag() const { return m_localTag; } SetLocalTag(const PString & tag)752 void SetLocalTag(const PString & tag) { m_localTag = tag; } 753 GetLocalURI()754 const SIPURL & GetLocalURI() const { return m_localURI; } 755 void SetLocalURI(const SIPURL & url); 756 GetRemoteTag()757 const PString & GetRemoteTag() const { return m_remoteTag; } SetRemoteTag(const PString & tag)758 void SetRemoteTag(const PString & tag) { m_remoteTag = tag; } 759 GetRemoteURI()760 const SIPURL & GetRemoteURI() const { return m_remoteURI; } 761 void SetRemoteURI(const SIPURL & url); 762 GetRouteSet()763 const SIPURLList & GetRouteSet() const { return m_routeSet; } SetRouteSet(const PString & str)764 void SetRouteSet(const PString & str) { m_routeSet.FromString(str); } 765 GetProxy()766 const SIPURL & GetProxy() const { return m_proxy; } 767 void SetProxy(const SIPURL & proxy, bool addToRouteSet); 768 769 void Update(OpalTransport & transport, const SIP_PDU & response); 770 771 unsigned GetNextCSeq(); IncrementCSeq(unsigned inc)772 void IncrementCSeq(unsigned inc) { m_lastSentCSeq += inc; } 773 774 bool IsDuplicateCSeq(unsigned sequenceNumber); 775 IsEstablished()776 bool IsEstablished() const 777 { 778 return !m_callId.IsEmpty() && 779 !m_requestURI.IsEmpty() && 780 !m_localTag.IsEmpty() && 781 !m_remoteTag.IsEmpty(); 782 } 783 784 OpalTransportAddress GetRemoteTransportAddress() const; 785 SetForking(bool f)786 void SetForking(bool f) { m_forking = f; } 787 788 protected: 789 PString m_callId; 790 SIPURL m_requestURI; 791 SIPURL m_localURI; 792 PString m_localTag; 793 SIPURL m_remoteURI; 794 PString m_remoteTag; 795 SIPURLList m_routeSet; 796 unsigned m_lastSentCSeq; 797 unsigned m_lastReceivedCSeq; 798 OpalTransportAddress m_externalTransportAddress; 799 bool m_forking; 800 SIPURL m_proxy; 801 }; 802 803 804 ///////////////////////////////////////////////////////////////////////// 805 806 struct SIPParameters 807 { 808 SIPParameters( 809 const PString & aor = PString::Empty(), 810 const PString & remote = PString::Empty() 811 ); 812 813 void Normalise( 814 const PString & defaultUser, 815 const PTimeInterval & defaultExpire 816 ); 817 818 PCaselessString m_remoteAddress; 819 PCaselessString m_localAddress; 820 PCaselessString m_proxyAddress; 821 PCaselessString m_addressOfRecord; 822 PCaselessString m_contactAddress; 823 PCaselessString m_interface; 824 SIPMIMEInfo m_mime; 825 PString m_authID; 826 PString m_password; 827 PString m_realm; 828 unsigned m_expire; 829 unsigned m_restoreTime; 830 PTimeInterval m_minRetryTime; 831 PTimeInterval m_maxRetryTime; 832 void * m_userData; 833 }; 834 835 836 #if PTRACING 837 ostream & operator<<(ostream & strm, const SIPParameters & params); 838 #endif 839 840 841 ///////////////////////////////////////////////////////////////////////// 842 // SIPTransaction 843 844 /** Session Initiation Protocol transaction. 845 A transaction is a stateful independent entity that provides services to 846 a connection (Transaction User). Transactions are contained within 847 connections. 848 A client transaction handles sending a request and receiving its 849 responses. 850 A server transaction handles sending responses to a received request. 851 In either case the SIP_PDU ancestor is the sent or received request. 852 */ 853 854 class SIPTransaction : public SIP_PDU 855 { 856 PCLASSINFO(SIPTransaction, SIP_PDU); 857 public: 858 SIPTransaction( 859 Methods method, 860 SIPEndPoint & endpoint, 861 OpalTransport & transport 862 ); 863 /** Construct a transaction for requests in a dialog. 864 * The transport is used to determine the local address 865 */ 866 SIPTransaction( 867 Methods method, 868 SIPConnection & connection 869 ); 870 ~SIPTransaction(); 871 872 /* Under some circumstances a new transaction with all the same parameters 873 but different ID needs to be created, e.g. when get authentication error. */ 874 virtual SIPTransaction * CreateDuplicate() const = 0; 875 876 PBoolean Start(); IsTrying()877 bool IsTrying() const { return m_state == Trying; } IsProceeding()878 bool IsProceeding() const { return m_state == Proceeding; } IsInProgress()879 bool IsInProgress() const { return m_state == Trying || m_state == Proceeding; } IsFailed()880 bool IsFailed() const { return m_state > Terminated_Success; } IsCompleted()881 bool IsCompleted() const { return m_state >= Completed; } IsCanceled()882 bool IsCanceled() const { return m_state == Cancelling || m_state == Terminated_Cancelled || m_state == Terminated_Aborted; } IsTerminated()883 bool IsTerminated() const { return m_state >= Terminated_Success; } 884 885 void WaitForCompletion(); 886 PBoolean Cancel(); 887 void Abort(); 888 889 virtual PBoolean OnReceivedResponse(SIP_PDU & response); 890 virtual PBoolean OnCompleted(SIP_PDU & response); 891 GetTransport()892 OpalTransport & GetTransport() const { return m_transport; } GetConnection()893 SIPConnection * GetConnection() const { return m_connection; } GetInterface()894 PString GetInterface() const { return m_localInterface; } SetInterface(const PString & localIf)895 void SetInterface(const PString & localIf) { m_localInterface = localIf; } 896 897 static PString GenerateCallID(); 898 899 protected: 900 bool SendPDU(SIP_PDU & pdu); 901 bool ResendCANCEL(); 902 void SetParameters(const SIPParameters & params); 903 904 PDECLARE_NOTIFIER(PTimer, SIPTransaction, OnRetry); 905 PDECLARE_NOTIFIER(PTimer, SIPTransaction, OnTimeout); 906 907 enum States { 908 NotStarted, 909 Trying, 910 Proceeding, 911 Cancelling, 912 Completed, 913 Terminated_Success, 914 Terminated_Timeout, 915 Terminated_RetriesExceeded, 916 Terminated_TransportError, 917 Terminated_Cancelled, 918 Terminated_Aborted, 919 NumStates 920 }; 921 virtual void SetTerminated(States newState); 922 923 SIPEndPoint & m_endpoint; 924 OpalTransport & m_transport; 925 PSafePtr<SIPConnection> m_connection; 926 PTimeInterval m_retryTimeoutMin; 927 PTimeInterval m_retryTimeoutMax; 928 929 States m_state; 930 unsigned m_retry; 931 PTimer m_retryTimer; 932 PTimer m_completionTimer; 933 PSyncPoint m_completed; 934 935 PString m_localInterface; 936 OpalTransportAddress m_remoteAddress; 937 }; 938 939 940 #define OPAL_PROXY_PARAM "OPAL-proxy" 941 #define OPAL_LOCAL_ID_PARAM "OPAL-local-id" 942 #define OPAL_INTERFACE_PARAM "OPAL-interface" 943 944 945 ///////////////////////////////////////////////////////////////////////// 946 // SIPResponse 947 948 /** When we receive a command, we need a transaction to send repeated responses. 949 */ 950 class SIPResponse : public SIPTransaction 951 { 952 PCLASSINFO(SIPResponse, SIPTransaction); 953 public: 954 SIPResponse( 955 SIPEndPoint & endpoint, 956 StatusCodes code 957 ); 958 959 virtual SIPTransaction * CreateDuplicate() const; 960 961 bool Send(OpalTransport & transport, const SIP_PDU & command); 962 }; 963 964 965 ///////////////////////////////////////////////////////////////////////// 966 // SIPInvite 967 968 /** Session Initiation Protocol transaction for INVITE 969 INVITE implements a three-way handshake to handle the human input and 970 extended duration of the transaction. 971 */ 972 973 class SIPInvite : public SIPTransaction 974 { 975 PCLASSINFO(SIPInvite, SIPTransaction); 976 public: 977 SIPInvite( 978 SIPConnection & connection, 979 const OpalRTPSessionManager & sm 980 ); 981 982 virtual SIPTransaction * CreateDuplicate() const; 983 984 virtual PBoolean OnReceivedResponse(SIP_PDU & response); 985 GetSessionManager()986 const OpalRTPSessionManager & GetSessionManager() const { return m_rtpSessions; } GetSessionManager()987 OpalRTPSessionManager & GetSessionManager() { return m_rtpSessions; } 988 989 protected: 990 OpalRTPSessionManager m_rtpSessions; 991 }; 992 993 994 ///////////////////////////////////////////////////////////////////////// 995 996 /* This is the ACK request sent when receiving a response to an outgoing 997 * INVITE. 998 */ 999 class SIPAck : public SIP_PDU 1000 { 1001 PCLASSINFO(SIPAck, SIP_PDU); 1002 public: 1003 SIPAck( 1004 SIPTransaction & invite, 1005 SIP_PDU & response 1006 ); 1007 1008 virtual SIPTransaction * CreateDuplicate() const; 1009 }; 1010 1011 1012 ///////////////////////////////////////////////////////////////////////// 1013 1014 /* This is a BYE request 1015 */ 1016 class SIPBye : public SIPTransaction 1017 { 1018 PCLASSINFO(SIPBye, SIPTransaction); 1019 1020 public: 1021 SIPBye( 1022 SIPEndPoint & ep, 1023 OpalTransport & trans, 1024 SIPDialogContext dialog 1025 ); 1026 SIPBye( 1027 SIPConnection & conn 1028 ); 1029 1030 virtual SIPTransaction * CreateDuplicate() const; 1031 }; 1032 1033 1034 ///////////////////////////////////////////////////////////////////////// 1035 1036 class SIPRegister : public SIPTransaction 1037 { 1038 PCLASSINFO(SIPRegister, SIPTransaction); 1039 public: 1040 enum CompatibilityModes { 1041 e_FullyCompliant, /**< Registrar is fully compliant, we will register 1042 all listeners of all types (e.g. sip, sips etc) 1043 in the Contact field. */ 1044 e_CannotRegisterMultipleContacts, /**< Registrar refuses to register more than one 1045 contact field. Correct behaviour is to return 1046 a contact with the fields it can accept in 1047 the 200 OK */ 1048 e_CannotRegisterPrivateContacts, /**< Registrar refuses to register any RFC 1049 contact field. Correct behaviour is to return 1050 a contact with the fields it can accept in 1051 the 200 OK */ 1052 e_HasApplicationLayerGateway /**< Router has Application Layer Gateway code that 1053 is doing address transations, so we do not try 1054 to do it ourselves as well or it goes horribly 1055 wrong. */ 1056 }; 1057 1058 /// Registrar parameters 1059 struct Params : public SIPParameters { ParamsParams1060 Params() 1061 : m_registrarAddress(m_remoteAddress) 1062 , m_compatibility(SIPRegister::e_FullyCompliant) 1063 { } 1064 ParamsParams1065 Params(const Params & param) 1066 : SIPParameters(param) 1067 , m_registrarAddress(m_remoteAddress) 1068 , m_compatibility(param.m_compatibility) 1069 { } 1070 1071 PCaselessString & m_registrarAddress; // For backward compatibility 1072 CompatibilityModes m_compatibility; 1073 }; 1074 1075 SIPRegister( 1076 SIPEndPoint & endpoint, 1077 OpalTransport & transport, 1078 const PString & callId, 1079 unsigned cseq, 1080 const Params & params 1081 ); 1082 1083 virtual SIPTransaction * CreateDuplicate() const; 1084 }; 1085 1086 1087 #if PTRACING 1088 ostream & operator<<(ostream & strm, SIPRegister::CompatibilityModes mode); 1089 ostream & operator<<(ostream & strm, const SIPRegister::Params & params); 1090 #endif 1091 1092 1093 ///////////////////////////////////////////////////////////////////////// 1094 1095 class SIPSubscribe : public SIPTransaction 1096 { 1097 PCLASSINFO(SIPSubscribe, SIPTransaction); 1098 public: 1099 /** Valid types for an event package 1100 */ 1101 enum PredefinedPackages { 1102 MessageSummary, 1103 Presence, 1104 Dialog, 1105 1106 NumPredefinedPackages, 1107 1108 Watcher = 0x8000, 1109 1110 MessageSummaryWatcher = Watcher|MessageSummary, 1111 PresenceWatcher = Watcher|Presence, 1112 DialogWatcher = Watcher|Dialog, 1113 1114 PackageMask = Watcher-1 1115 }; 1116 friend PredefinedPackages operator|(PredefinedPackages p1, PredefinedPackages p2) { return (PredefinedPackages)((int)p1|(int)p2); } 1117 1118 class EventPackage : public PCaselessString 1119 { 1120 PCLASSINFO(EventPackage, PCaselessString); 1121 public: 1122 EventPackage(PredefinedPackages = NumPredefinedPackages); EventPackage(const PString & str)1123 explicit EventPackage(const PString & str) : PCaselessString(str) { } EventPackage(const char * str)1124 explicit EventPackage(const char * str) : PCaselessString(str) { } 1125 1126 EventPackage & operator=(PredefinedPackages pkg); 1127 EventPackage & operator=(const PString & str) { PCaselessString::operator=(str); return *this; } 1128 EventPackage & operator=(const char * str) { PCaselessString::operator=(str); return *this; } 1129 1130 bool operator==(PredefinedPackages pkg) const { return Compare(EventPackage(pkg)) == EqualTo; } 1131 bool operator==(const PString & str) const { return Compare(str) == EqualTo; } 1132 bool operator==(const char * cstr) const { return InternalCompare(0, P_MAX_INDEX, cstr) == EqualTo; } 1133 virtual Comparison InternalCompare(PINDEX offset, PINDEX length, const char * cstr) const; 1134 1135 bool IsWatcher() const; 1136 }; 1137 1138 /** Information provided on the subscription status. */ 1139 struct SubscriptionStatus { 1140 SIPSubscribeHandler * m_handler; ///< Handler for subscription 1141 PString m_addressofRecord; ///< Address of record for registration 1142 bool m_wasSubscribing; ///< Was registering or unregistering 1143 bool m_reSubscribing; ///< Was a registration refresh 1144 SIP_PDU::StatusCodes m_reason; ///< Reason for status change 1145 OpalProductInfo m_productInfo; ///< Server product info from registrar if available. 1146 void * m_userData; ///< User data corresponding to this registration 1147 }; 1148 1149 struct NotifyCallbackInfo { 1150 NotifyCallbackInfo( 1151 SIPEndPoint & ep, 1152 OpalTransport & trans, 1153 SIP_PDU & notify, 1154 SIP_PDU & response 1155 ); 1156 1157 bool SendResponse( 1158 SIP_PDU::StatusCodes status, 1159 const char * extra = NULL 1160 ); 1161 1162 SIPEndPoint & m_endpoint; 1163 OpalTransport & m_transport; 1164 SIP_PDU & m_notify; 1165 SIP_PDU & m_response; 1166 bool m_sendResponse; 1167 }; 1168 1169 struct Params : public SIPParameters 1170 { 1171 Params(PredefinedPackages pkg = NumPredefinedPackages) m_agentAddressParams1172 : m_agentAddress(m_remoteAddress) 1173 , m_eventPackage(pkg) 1174 , m_eventList(false) 1175 { } 1176 ParamsParams1177 Params(const Params & param) 1178 : SIPParameters(param) 1179 , m_agentAddress(m_remoteAddress) 1180 , m_eventPackage(param.m_eventPackage) 1181 , m_eventList(param.m_eventList) 1182 , m_contentType(param.m_contentType) 1183 , m_onSubcribeStatus(param.m_onSubcribeStatus) 1184 , m_onNotify(param.m_onNotify) 1185 { } 1186 1187 PCaselessString & m_agentAddress; // For backward compatibility 1188 EventPackage m_eventPackage; 1189 bool m_eventList; // Enable RFC4662 1190 PCaselessString m_contentType; // May be \n separated list of types 1191 1192 PNotifierTemplate<const SubscriptionStatus &> m_onSubcribeStatus; 1193 PNotifierTemplate<NotifyCallbackInfo &> m_onNotify; 1194 }; 1195 1196 SIPSubscribe( 1197 SIPEndPoint & ep, 1198 OpalTransport & trans, 1199 SIPDialogContext & dialog, 1200 const Params & params 1201 ); 1202 1203 virtual SIPTransaction * CreateDuplicate() const; 1204 }; 1205 1206 1207 #if PTRACING 1208 ostream & operator<<(ostream & strm, const SIPSubscribe::Params & params); 1209 #endif 1210 1211 1212 typedef SIPSubscribe::EventPackage SIPEventPackage; 1213 1214 1215 ///////////////////////////////////////////////////////////////////////// 1216 1217 class SIPHandler; 1218 1219 class SIPEventPackageHandler 1220 { 1221 public: ~SIPEventPackageHandler()1222 virtual ~SIPEventPackageHandler() { } 1223 virtual PCaselessString GetContentType() const = 0; 1224 virtual bool ValidateContentType(const PString & type, const SIPMIMEInfo & mime); 1225 virtual bool OnReceivedNOTIFY(SIPHandler & handler, SIP_PDU & request) = 0; OnSendNOTIFY(SIPHandler &,const PObject *)1226 virtual PString OnSendNOTIFY(SIPHandler & /*handler*/, const PObject * /*body*/) { return PString::Empty(); } 1227 }; 1228 1229 1230 typedef PFactory<SIPEventPackageHandler, SIPEventPackage> SIPEventPackageFactory; 1231 1232 1233 ///////////////////////////////////////////////////////////////////////// 1234 1235 class SIPNotify : public SIPTransaction 1236 { 1237 PCLASSINFO(SIPNotify, SIPTransaction); 1238 public: 1239 SIPNotify( 1240 SIPEndPoint & ep, 1241 OpalTransport & trans, 1242 SIPDialogContext & dialog, 1243 const SIPEventPackage & eventPackage, 1244 const PString & state, 1245 const PString & body 1246 ); 1247 1248 virtual SIPTransaction * CreateDuplicate() const; 1249 }; 1250 1251 1252 ///////////////////////////////////////////////////////////////////////// 1253 1254 class SIPPublish : public SIPTransaction 1255 { 1256 PCLASSINFO(SIPPublish, SIPTransaction); 1257 public: 1258 SIPPublish( 1259 SIPEndPoint & ep, 1260 OpalTransport & trans, 1261 const PString & id, 1262 const PString & sipIfMatch, 1263 const SIPSubscribe::Params & params, 1264 const PString & body 1265 ); 1266 1267 virtual SIPTransaction * CreateDuplicate() const; 1268 }; 1269 1270 1271 ///////////////////////////////////////////////////////////////////////// 1272 1273 class SIPRefer : public SIPTransaction 1274 { 1275 PCLASSINFO(SIPRefer, SIPTransaction); 1276 public: 1277 SIPRefer( 1278 SIPConnection & connection, 1279 const SIPURL & referTo, 1280 const SIPURL & referred_by, 1281 bool referSub 1282 ); 1283 1284 virtual SIPTransaction * CreateDuplicate() const; 1285 }; 1286 1287 1288 ///////////////////////////////////////////////////////////////////////// 1289 1290 /* This is not a generic NOTIFY PDU, but the minimal one 1291 * that gets sent when receiving a REFER 1292 */ 1293 class SIPReferNotify : public SIPTransaction 1294 { 1295 PCLASSINFO(SIPReferNotify, SIPTransaction); 1296 public: 1297 SIPReferNotify( 1298 SIPConnection & connection, 1299 StatusCodes code 1300 ); 1301 1302 virtual SIPTransaction * CreateDuplicate() const; 1303 }; 1304 1305 1306 ///////////////////////////////////////////////////////////////////////// 1307 1308 /* This is a MESSAGE PDU, with a body 1309 */ 1310 class SIPMessage : public SIPTransaction 1311 { 1312 PCLASSINFO(SIPMessage, SIPTransaction); 1313 public: 1314 struct Params : public SIPParameters 1315 { ParamsParams1316 Params() 1317 : m_contentType("text/plain;charset=UTF-8") 1318 { 1319 m_expire = 5000; 1320 } 1321 1322 PCaselessString m_contentType; 1323 PString m_id; 1324 PString m_body; 1325 PAtomicInteger::IntegerType m_messageId; 1326 }; 1327 1328 SIPMessage( 1329 SIPEndPoint & ep, 1330 OpalTransport & trans, 1331 const Params & params 1332 ); 1333 SIPMessage( 1334 SIPConnection & connection, 1335 const Params & params 1336 ); 1337 1338 virtual SIPTransaction * CreateDuplicate() const; 1339 GetLocalAddress()1340 const SIPURL & GetLocalAddress() const { return m_localAddress; } 1341 1342 private: 1343 void Construct(const Params & params); 1344 1345 SIPURL m_localAddress; 1346 }; 1347 1348 1349 ///////////////////////////////////////////////////////////////////////// 1350 1351 /* This is an OPTIONS request 1352 */ 1353 class SIPOptions : public SIPTransaction 1354 { 1355 PCLASSINFO(SIPOptions, SIPTransaction); 1356 1357 public: 1358 struct Params : public SIPParameters 1359 { ParamsParams1360 Params() 1361 : m_acceptContent("application/sdp, application/media_control+xml, application/dtmf, application/dtmf-relay") 1362 { 1363 } 1364 1365 PCaselessString m_acceptContent; 1366 PCaselessString m_contentType; 1367 PString m_body; 1368 }; 1369 1370 SIPOptions( 1371 SIPEndPoint & ep, 1372 OpalTransport & trans, 1373 const PString & id, 1374 const Params & params 1375 ); 1376 SIPOptions( 1377 SIPConnection & conn, 1378 const Params & params 1379 ); 1380 1381 virtual SIPTransaction * CreateDuplicate() const; 1382 1383 protected: 1384 void Construct(const Params & params); 1385 }; 1386 1387 1388 ///////////////////////////////////////////////////////////////////////// 1389 1390 /* This is an INFO request 1391 */ 1392 class SIPInfo : public SIPTransaction 1393 { 1394 PCLASSINFO(SIPInfo, SIPTransaction); 1395 1396 public: 1397 struct Params 1398 { 1399 Params(const PString & contentType = PString::Empty(), 1400 const PString & body = PString::Empty()) m_contentTypeParams1401 : m_contentType(contentType) 1402 , m_body(body) 1403 { 1404 } 1405 1406 PCaselessString m_contentType; 1407 PString m_body; 1408 }; 1409 1410 SIPInfo( 1411 SIPConnection & conn, 1412 const Params & params 1413 ); 1414 1415 virtual SIPTransaction * CreateDuplicate() const; 1416 }; 1417 1418 1419 ///////////////////////////////////////////////////////////////////////// 1420 1421 /* This is a PING PDU, with a body 1422 */ 1423 class SIPPing : public SIPTransaction 1424 { 1425 PCLASSINFO(SIPPing, SIPTransaction); 1426 1427 public: 1428 SIPPing( 1429 SIPEndPoint & ep, 1430 OpalTransport & trans, 1431 const SIPURL & address 1432 ); 1433 1434 virtual SIPTransaction * CreateDuplicate() const; 1435 }; 1436 1437 1438 ///////////////////////////////////////////////////////////////////////// 1439 1440 /* This is a PRACK PDU 1441 */ 1442 class SIPPrack : public SIPTransaction 1443 { 1444 PCLASSINFO(SIPPrack, SIPTransaction); 1445 1446 public: 1447 SIPPrack( 1448 SIPConnection & conn, 1449 const PString & rack 1450 ); 1451 1452 virtual SIPTransaction * CreateDuplicate() const; 1453 }; 1454 1455 1456 #endif // OPAL_SIP 1457 1458 #endif // OPAL_SIP_SIPPDU_H 1459 1460 1461 // End of File /////////////////////////////////////////////////////////////// 1462