OPAL Version 3.10.2
sippdu.h
Go to the documentation of this file.
00001 /*
00002  * sippdu.h
00003  *
00004  * Session Initiation Protocol PDU support.
00005  *
00006  * Open Phone Abstraction Library (OPAL)
00007  * Formally known as the Open H323 project.
00008  *
00009  * Copyright (c) 2002 Equivalence Pty. Ltd.
00010  *
00011  * The contents of this file are subject to the Mozilla Public License
00012  * Version 1.0 (the "License"); you may not use this file except in
00013  * compliance with the License. You may obtain a copy of the License at
00014  * http://www.mozilla.org/MPL/
00015  *
00016  * Software distributed under the License is distributed on an "AS IS"
00017  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00018  * the License for the specific language governing rights and limitations
00019  * under the License.
00020  *
00021  * The Original Code is Open Phone Abstraction Library.
00022  *
00023  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00024  *
00025  * Contributor(s): ______________________________________.
00026  *
00027  * $Revision: 25988 $
00028  * $Author: rjongbloed $
00029  * $Date: 2011-06-08 22:06:13 -0500 (Wed, 08 Jun 2011) $
00030  */
00031 
00032 #ifndef OPAL_SIP_SIPPDU_H
00033 #define OPAL_SIP_SIPPDU_H
00034 
00035 #ifdef P_USE_PRAGMA
00036 #pragma interface
00037 #endif
00038 
00039 #include <opal/buildopts.h>
00040 
00041 #if OPAL_SIP
00042 
00043 #include <ptclib/mime.h>
00044 #include <ptclib/url.h>
00045 #include <ptclib/http.h>
00046 #include <sip/sdp.h>
00047 #include <opal/rtpconn.h>
00048 
00049  
00050 class OpalTransport;
00051 class OpalTransportAddress;
00052 class OpalProductInfo;
00053 
00054 class SIPEndPoint;
00055 class SIPConnection;
00056 class SIP_PDU;
00057 class SIPSubscribeHandler;
00058 class SIPDialogContext;
00059 
00060 
00062 // SIPURL
00063 
00069 class SIPURL : public PURL
00070 {
00071   PCLASSINFO(SIPURL, PURL);
00072   public:
00073     SIPURL();
00074 
00077     SIPURL(
00078       const char * cstr,    
00079       const char * defaultScheme = NULL 
00080     );
00081 
00084     SIPURL(
00085       const PString & str,  
00086       const char * defaultScheme = NULL 
00087     );
00088 
00098     SIPURL(
00099       const PString & name,
00100       const OpalTransportAddress & address,
00101       WORD listenerPort = 0
00102     );
00103 
00104     SIPURL(
00105       const OpalTransportAddress & _address, 
00106       WORD listenerPort = 0
00107     );
00108 
00117     virtual Comparison Compare(
00118       const PObject & obj   
00119     ) const;
00120 
00124     PString AsQuotedString() const;
00125 
00128     PString GetDisplayName(PBoolean useDefault = true) const;
00129     
00130     void SetDisplayName(const PString & str) 
00131     {
00132       m_displayName = str;
00133     }
00134 
00136     const PStringOptions & GetFieldParameters() const { return m_fieldParameters; }
00137           PStringOptions & GetFieldParameters()       { return m_fieldParameters; }
00138 
00141     OpalTransportAddress GetHostAddress() const;
00142 
00143     enum UsageContext {
00144       ExternalURI,   
00145       RequestURI,    
00146       ToURI,         
00147       FromURI,       
00148       RouteURI,      
00149       RedirectURI,   
00150       ContactURI,    
00151       RegContactURI, 
00152       RegisterURI    
00153     };
00154 
00160     void Sanitise(
00161       UsageContext context  
00162     );
00163 
00169     PBoolean AdjustToDNS(
00170       PINDEX entry = 0  
00171     );
00172 
00174     static PString GenerateTag();
00175 
00177     void SetTag(
00178       const PString & tag = PString::Empty(),
00179       bool force = false
00180     );
00181 
00182   protected:
00183     void ParseAsAddress(const PString & name, const OpalTransportAddress & _address, WORD listenerPort = 0);
00184 
00204     virtual PBoolean InternalParse(
00205       const char * cstr,
00206       const char * defaultScheme
00207     );
00208 
00209     PString        m_displayName;
00210     PStringOptions m_fieldParameters;
00211 };
00212 
00213 
00214 class SIPURLList : public std::list<SIPURL>
00215 {
00216   public:
00217     bool FromString(const PString & str, bool reversed = false);
00218     PString ToString() const;
00219 };
00220 
00221 
00222 
00224 // SIPMIMEInfo
00225 
00256 class SIPMIMEInfo : public PMIMEInfo
00257 {
00258   PCLASSINFO(SIPMIMEInfo, PMIMEInfo);
00259   public:
00260     SIPMIMEInfo(bool compactForm = false);
00261 
00262     virtual void PrintOn(ostream & strm) const;
00263     virtual void ReadFrom(istream & strm);
00264 
00265     void SetCompactForm(bool form) { compactForm = form; }
00266 
00267     PCaselessString GetContentType(bool includeParameters = false) const;
00268     void SetContentType(const PString & v);
00269 
00270     PCaselessString GetContentEncoding() const;
00271     void SetContentEncoding(const PString & v);
00272 
00273     PString GetFrom() const;
00274     void SetFrom(const PString & v);
00275 
00276     PString GetPAssertedIdentity() const;
00277     void SetPAssertedIdentity(const PString & v);
00278 
00279     PString GetPPreferredIdentity() const;
00280     void SetPPreferredIdentity(const PString & v);
00281 
00282     PString GetAccept() const;
00283     void SetAccept(const PString & v);
00284 
00285     PString GetAcceptEncoding() const;
00286     void SetAcceptEncoding(const PString & v);
00287 
00288     PString GetAcceptLanguage() const;
00289     void SetAcceptLanguage(const PString & v);
00290 
00291     PString GetAllow() const;
00292     unsigned GetAllowBitMask() const;
00293     void SetAllow(const PString & v);
00294 
00295     PString GetCallID() const;
00296     void SetCallID(const PString & v);
00297 
00298     PString GetContact() const;
00299     bool GetContacts(SIPURLList & contacts) const;
00300     void SetContact(const PString & v);
00301 
00302     PString GetSubject() const;
00303     void SetSubject(const PString & v);
00304 
00305     PString GetTo() const;
00306     void SetTo(const PString & v);
00307 
00308     PString GetVia() const;
00309     void SetVia(const PString & v);
00310 
00311     bool GetViaList(PStringList & v) const;
00312     void SetViaList(const PStringList & v);
00313 
00314     PString GetFirstVia() const;
00315     OpalTransportAddress GetViaReceivedAddress() const;
00316 
00317     PString GetReferTo() const;
00318     void SetReferTo(const PString & r);
00319 
00320     PString GetReferredBy() const;
00321     void SetReferredBy(const PString & r);
00322 
00323     PINDEX  GetContentLength() const;
00324     void SetContentLength(PINDEX v);
00325     PBoolean IsContentLengthPresent() const;
00326 
00327     PString GetCSeq() const;
00328     void SetCSeq(const PString & v);
00329 
00330     PString GetDate() const;
00331     void SetDate(const PString & v);
00332     void SetDate(const PTime & t);
00333     void SetDate(void); // set to current date
00334 
00335     unsigned GetExpires(unsigned dflt = UINT_MAX) const;// returns default value if not found
00336     void SetExpires(unsigned v);
00337 
00338     PINDEX GetMaxForwards() const;
00339     void SetMaxForwards(PINDEX v);
00340 
00341     PINDEX GetMinExpires() const;
00342     void SetMinExpires(PINDEX v);
00343 
00344     PString GetProxyAuthenticate() const;
00345     void SetProxyAuthenticate(const PString & v);
00346 
00347     PString GetRoute() const;
00348     bool GetRoute(SIPURLList & proxies) const;
00349     void SetRoute(const PString & v);
00350     void SetRoute(const SIPURLList & proxies);
00351 
00352     PString GetRecordRoute() const;
00353     bool GetRecordRoute(SIPURLList & proxies, bool reversed) const;
00354     void SetRecordRoute(const PString & v);
00355     void SetRecordRoute(const SIPURLList & proxies);
00356 
00357     unsigned GetCSeqIndex() const { return GetCSeq().AsUnsigned(); }
00358 
00359     PStringSet GetRequire() const;
00360     void SetRequire(const PStringSet & v);
00361     void AddRequire(const PString & v);
00362 
00363     PStringSet GetSupported() const;
00364     void SetSupported(const PStringSet & v);
00365     void AddSupported(const PString & v);
00366 
00367     PStringSet GetUnsupported() const;
00368     void SetUnsupported(const PStringSet & v);
00369     void AddUnsupported(const PString & v);
00370     
00371     PString GetEvent() const;
00372     void SetEvent(const PString & v);
00373     
00374     PCaselessString GetSubscriptionState(PStringToString & info) const;
00375     void SetSubscriptionState(const PString & v);
00376     
00377     PString GetUserAgent() const;
00378     void SetUserAgent(const PString & v);
00379 
00380     PString GetOrganization() const;
00381     void SetOrganization(const PString & v);
00382 
00383     void GetProductInfo(OpalProductInfo & info) const;
00384     void SetProductInfo(const PString & ua, const OpalProductInfo & info);
00385 
00386     PString GetWWWAuthenticate() const;
00387     void SetWWWAuthenticate(const PString & v);
00388 
00389     PString GetSIPIfMatch() const;
00390     void SetSIPIfMatch(const PString & v);
00391 
00392     PString GetSIPETag() const;
00393     void SetSIPETag(const PString & v);
00394 
00395     void GetAlertInfo(PString & info, int & appearance);
00396     void SetAlertInfo(const PString & info, int appearance);
00397 
00398     PString GetCallInfo() const;
00399 
00400     PString GetAllowEvents() const;
00401     void SetAllowEvents(const PString & v);
00402 
00405     PString GetFieldParameter(
00406       const PString & fieldName,    
00407       const PString & paramName,    
00408       const PString & defaultValue = PString::Empty()  
00409     ) const { return ExtractFieldParameter((*this)(fieldName), paramName, defaultValue); }
00410 
00415     void SetFieldParameter(
00416       const PString & fieldName,    
00417       const PString & paramName,    
00418       const PString & newValue      
00419     ) { SetAt(fieldName, InsertFieldParameter((*this)(fieldName), paramName, newValue)); }
00420 
00423     static PString ExtractFieldParameter(
00424       const PString & fieldValue,   
00425       const PString & paramName,    
00426       const PString & defaultValue = PString::Empty()  
00427     );
00428 
00433     static PString InsertFieldParameter(
00434       const PString & fieldValue,   
00435       const PString & paramName,    
00436       const PString & newValue      
00437     );
00438 
00439   protected:
00440     PStringSet GetTokenSet(const char * field) const;
00441     void AddTokenSet(const char * field, const PString & token);
00442     void SetTokenSet(const char * field, const PStringSet & tokens);
00443 
00445     bool compactForm;
00446 };
00447 
00448 
00450 // SIPAuthentication
00451 
00452 typedef PHTTPClientAuthentication SIPAuthentication;
00453 
00454 class SIPAuthenticator : public PHTTPClientAuthentication::AuthObject
00455 {
00456   public:
00457     SIPAuthenticator(SIP_PDU & pdu);
00458     virtual PMIMEInfo & GetMIME();
00459     virtual PString GetURI();
00460     virtual PString GetEntityBody();
00461     virtual PString GetMethod();
00462 
00463   protected:  
00464     SIP_PDU & m_pdu;
00465 };
00466 
00467 
00468 
00470 // SIP_PDU
00471 
00477 class SIP_PDU : public PSafeObject
00478 {
00479   PCLASSINFO(SIP_PDU, PSafeObject);
00480   public:
00481     enum Methods {
00482       Method_INVITE,
00483       Method_ACK,
00484       Method_OPTIONS,
00485       Method_BYE,
00486       Method_CANCEL,
00487       Method_REGISTER,
00488       Method_SUBSCRIBE,
00489       Method_NOTIFY,
00490       Method_REFER,
00491       Method_MESSAGE,
00492       Method_INFO,
00493       Method_PING,
00494       Method_PUBLISH,
00495       Method_PRACK,
00496       NumMethods
00497     };
00498 
00499     enum StatusCodes {
00500       IllegalStatusCode,
00501       Local_TransportError,
00502       Local_BadTransportAddress,
00503       Local_Timeout,
00504 
00505       Information_Trying                  = 100,
00506       Information_Ringing                 = 180,
00507       Information_CallForwarded           = 181,
00508       Information_Queued                  = 182,
00509       Information_Session_Progress        = 183,
00510 
00511       Successful_OK                       = 200,
00512       Successful_Accepted                         = 202,
00513 
00514       Redirection_MultipleChoices         = 300,
00515       Redirection_MovedPermanently        = 301,
00516       Redirection_MovedTemporarily        = 302,
00517       Redirection_UseProxy                = 305,
00518       Redirection_AlternativeService      = 380,
00519 
00520       Failure_BadRequest                  = 400,
00521       Failure_UnAuthorised                = 401,
00522       Failure_PaymentRequired             = 402,
00523       Failure_Forbidden                   = 403,
00524       Failure_NotFound                    = 404,
00525       Failure_MethodNotAllowed            = 405,
00526       Failure_NotAcceptable               = 406,
00527       Failure_ProxyAuthenticationRequired = 407,
00528       Failure_RequestTimeout              = 408,
00529       Failure_Conflict                    = 409,
00530       Failure_Gone                        = 410,
00531       Failure_LengthRequired              = 411,
00532       Failure_RequestEntityTooLarge       = 413,
00533       Failure_RequestURITooLong           = 414,
00534       Failure_UnsupportedMediaType        = 415,
00535       Failure_UnsupportedURIScheme        = 416,
00536       Failure_BadExtension                = 420,
00537       Failure_ExtensionRequired           = 421,
00538       Failure_IntervalTooBrief            = 423,
00539       Failure_TemporarilyUnavailable      = 480,
00540       Failure_TransactionDoesNotExist     = 481,
00541       Failure_LoopDetected                = 482,
00542       Failure_TooManyHops                 = 483,
00543       Failure_AddressIncomplete           = 484,
00544       Failure_Ambiguous                   = 485,
00545       Failure_BusyHere                    = 486,
00546       Failure_RequestTerminated           = 487,
00547       Failure_NotAcceptableHere           = 488,
00548       Failure_BadEvent                    = 489,
00549       Failure_RequestPending              = 491,
00550       Failure_Undecipherable              = 493,
00551 
00552       Failure_InternalServerError         = 500,
00553       Failure_NotImplemented              = 501,
00554       Failure_BadGateway                  = 502,
00555       Failure_ServiceUnavailable          = 503,
00556       Failure_ServerTimeout               = 504,
00557       Failure_SIPVersionNotSupported      = 505,
00558       Failure_MessageTooLarge             = 513,
00559 
00560       GlobalFailure_BusyEverywhere        = 600,
00561       GlobalFailure_Decline               = 603,
00562       GlobalFailure_DoesNotExistAnywhere  = 604,
00563       GlobalFailure_NotAcceptable         = 606,
00564 
00565       MaxStatusCode                       = 699
00566     };
00567 
00568     static const char * GetStatusCodeDescription(int code);
00569     friend ostream & operator<<(ostream & strm, StatusCodes status);
00570 
00571     SIP_PDU(
00572       Methods method = SIP_PDU::NumMethods
00573     );
00574 
00578     SIP_PDU(
00579       const SIP_PDU & request,
00580       StatusCodes code,
00581       const SDPSessionDescription * sdp = NULL
00582     );
00583 
00584     SIP_PDU(const SIP_PDU &);
00585     SIP_PDU & operator=(const SIP_PDU &);
00586     ~SIP_PDU();
00587 
00588     void PrintOn(
00589       ostream & strm
00590     ) const;
00591 
00592     void InitialiseHeaders(
00593       const SIPURL & dest,
00594       const SIPURL & to,
00595       const SIPURL & from,
00596       const PString & callID,
00597       unsigned cseq,
00598       const PString & via
00599     );
00600     void InitialiseHeaders(
00601       SIPDialogContext & dialog,
00602       const PString & via = PString::Empty(),
00603       unsigned cseq = 0
00604     );
00605     void InitialiseHeaders(
00606       SIPConnection & connection,
00607       const OpalTransport & transport,
00608       unsigned cseq = 0
00609     );
00610     void InitialiseHeaders(
00611       const SIP_PDU & request
00612     );
00613 
00618     bool SetRoute(const SIPURLList & routeSet);
00619     bool SetRoute(const SIPURL & proxy);
00620 
00623     void SetAllow(unsigned bitmask);
00624 
00627     void AdjustVia(OpalTransport & transport);
00628 
00629     PString CreateVia(
00630       SIPEndPoint & endpoint,
00631       const OpalTransport & transport,
00632       SIPConnection * connection = NULL
00633     );
00634 
00637     SIP_PDU::StatusCodes Read(
00638       OpalTransport & transport
00639     );
00640 
00643     PBoolean Write(
00644       OpalTransport & transport,
00645       const OpalTransportAddress & remoteAddress = OpalTransportAddress(),
00646       const PString & localInterface = PString::Empty()
00647     );
00648 
00651     bool SendResponse(
00652       OpalTransport & transport,
00653       StatusCodes code,
00654       SIPEndPoint * endpoint = NULL
00655     ) const;
00656     bool SendResponse(
00657       OpalTransport & transport,
00658       SIP_PDU & response,
00659       SIPEndPoint * endpoint = NULL
00660     ) const;
00661 
00665     PString Build();
00666 
00667     PString GetTransactionID() const;
00668 
00669     Methods GetMethod() const                { return m_method; }
00670     StatusCodes GetStatusCode () const       { return m_statusCode; }
00671     void SetStatusCode (StatusCodes c)       { m_statusCode = c; }
00672     const SIPURL & GetURI() const            { return m_uri; }
00673     unsigned GetVersionMajor() const         { return m_versionMajor; }
00674     unsigned GetVersionMinor() const         { return m_versionMinor; }
00675     const PString & GetEntityBody() const    { return m_entityBody; }
00676     void SetEntityBody(const PString & body) { m_entityBody = body; }
00677     void SetEntityBody();
00678     const PString & GetInfo() const          { return m_info; }
00679     void SetInfo(const PString & info)       { m_info = info; }
00680     const SIPMIMEInfo & GetMIME() const      { return m_mime; }
00681           SIPMIMEInfo & GetMIME()            { return m_mime; }
00682     void SetURI(const SIPURL & newuri)       { m_uri = newuri; }
00683     SDPSessionDescription * GetSDP(const OpalMediaFormatList & masterList);
00684     void SetSDP(SDPSessionDescription * sdp);
00685 
00686   protected:
00687     Methods     m_method;                 // Request type, ==NumMethods for Response
00688     StatusCodes m_statusCode;
00689     SIPURL      m_uri;                    // display name & URI, no tag
00690     unsigned    m_versionMajor;
00691     unsigned    m_versionMinor;
00692     PString     m_info;
00693     SIPMIMEInfo m_mime;
00694     PString     m_entityBody;
00695 
00696     SDPSessionDescription * m_SDP;
00697 
00698     mutable PString m_transactionID;
00699 };
00700 
00701 
00702 PQUEUE(SIP_PDU_Queue, SIP_PDU);
00703 
00704 
00705 #if PTRACING
00706 ostream & operator<<(ostream & strm, SIP_PDU::Methods method);
00707 #endif
00708 
00709 
00711 // SIPDialogContext
00712 
00715 class SIPDialogContext
00716 {
00717   public:
00718     SIPDialogContext();
00719     SIPDialogContext(const SIPMIMEInfo & mime);
00720 
00721     PString AsString() const;
00722     bool FromString(
00723       const PString & str
00724     );
00725 
00726     const PString & GetCallID() const { return m_callId; }
00727     void SetCallID(const PString & id) { m_callId = id; }
00728 
00729     const SIPURL & GetRequestURI() const { return m_requestURI; }
00730     void SetRequestURI(const SIPURL & url) { m_requestURI = url; }
00731     bool SetRequestURI(const PString & uri) { return m_requestURI.Parse(uri); }
00732 
00733     const PString & GetLocalTag() const { return m_localTag; }
00734     void SetLocalTag(const PString & tag) { m_localTag = tag; }
00735 
00736     const SIPURL & GetLocalURI() const { return m_localURI; }
00737     void SetLocalURI(const SIPURL & url);
00738     bool SetLocalURI(const PString & uri);
00739 
00740     const PString & GetRemoteTag() const { return m_remoteTag; }
00741     void SetRemoteTag(const PString & tag) { m_remoteTag = tag; }
00742 
00743     const SIPURL & GetRemoteURI() const { return m_remoteURI; }
00744     void SetRemoteURI(const SIPURL & url);
00745     bool SetRemoteURI(const PString & uri);
00746 
00747     const SIPURLList & GetRouteSet() const { return m_routeSet; }
00748     void SetRouteSet(const PString & str) { m_routeSet.FromString(str); }
00749 
00750     const SIPURL & GetProxy() const { return m_proxy; }
00751     void SetProxy(const SIPURL & proxy, bool addToRouteSet);
00752 
00753     void Update(OpalTransport & transport, const SIP_PDU & response);
00754 
00755     unsigned GetNextCSeq();
00756     void IncrementCSeq(unsigned inc) { m_lastSentCSeq += inc; }
00757 
00758     bool IsDuplicateCSeq(unsigned sequenceNumber);
00759 
00760     bool IsEstablished() const
00761     {
00762       return !m_callId.IsEmpty() &&
00763              !m_requestURI.IsEmpty() &&
00764              !m_localTag.IsEmpty() &&
00765              !m_remoteTag.IsEmpty();
00766     }
00767 
00768     OpalTransportAddress GetRemoteTransportAddress() const;
00769 
00770     void SetForking(bool f) { m_forking = f; }
00771 
00772   protected:
00773     PString     m_callId;
00774     SIPURL      m_requestURI;
00775     SIPURL      m_localURI;
00776     PString     m_localTag;
00777     SIPURL      m_remoteURI;
00778     PString     m_remoteTag;
00779     SIPURLList  m_routeSet;
00780     unsigned    m_lastSentCSeq;
00781     unsigned    m_lastReceivedCSeq;
00782     OpalTransportAddress m_externalTransportAddress;
00783     bool        m_forking;
00784     SIPURL      m_proxy;
00785 };
00786 
00787 
00789 
00790 struct SIPParameters
00791 {
00792   SIPParameters(
00793     const PString & aor = PString::Empty(),
00794     const PString & remote = PString::Empty()
00795   );
00796 
00797   void Normalise(
00798     const PString & defaultUser,
00799     const PTimeInterval & defaultExpire
00800   );
00801 
00802   PCaselessString m_remoteAddress;
00803   PCaselessString m_localAddress;
00804   PCaselessString m_proxyAddress;
00805   PCaselessString m_addressOfRecord;
00806   PCaselessString m_contactAddress;
00807   SIPMIMEInfo     m_mime;
00808   PString         m_authID;
00809   PString         m_password;
00810   PString         m_realm;
00811   unsigned        m_expire;
00812   unsigned        m_restoreTime;
00813   PTimeInterval   m_minRetryTime;
00814   PTimeInterval   m_maxRetryTime;
00815   void          * m_userData;
00816 };
00817 
00818 
00819 #if PTRACING
00820 ostream & operator<<(ostream & strm, const SIPParameters & params);
00821 #endif
00822 
00823 
00825 // SIPTransaction
00826 
00837 class SIPTransaction : public SIP_PDU
00838 {
00839     PCLASSINFO(SIPTransaction, SIP_PDU);
00840   public:
00841     SIPTransaction(
00842       Methods method,
00843       SIPEndPoint   & endpoint,
00844       OpalTransport & transport
00845     );
00849     SIPTransaction(
00850       Methods method,
00851       SIPConnection & connection
00852     );
00853     ~SIPTransaction();
00854 
00855     /* Under some circumstances a new transaction with all the same parameters
00856        but different ID needs to be created, e.g. when get authentication error. */
00857     virtual SIPTransaction * CreateDuplicate() const = 0;
00858 
00859     PBoolean Start();
00860     bool IsTrying()     const { return m_state == Trying; }
00861     bool IsProceeding() const { return m_state == Proceeding; }
00862     bool IsInProgress() const { return m_state == Trying || m_state == Proceeding; }
00863     bool IsFailed()     const { return m_state > Terminated_Success; }
00864     bool IsCompleted()  const { return m_state >= Completed; }
00865     bool IsCanceled()   const { return m_state == Cancelling || m_state == Terminated_Cancelled || m_state == Terminated_Aborted; }
00866     bool IsTerminated() const { return m_state >= Terminated_Success; }
00867 
00868     void WaitForCompletion();
00869     PBoolean Cancel();
00870     void Abort();
00871 
00872     virtual PBoolean OnReceivedResponse(SIP_PDU & response);
00873     virtual PBoolean OnCompleted(SIP_PDU & response);
00874 
00875     OpalTransport & GetTransport()  const { return m_transport; }
00876     SIPConnection * GetConnection() const { return m_connection; }
00877     PString         GetInterface()  const { return m_localInterface; }
00878     void            SetInterface(const PString & localIf)  { m_localInterface = localIf; }
00879 
00880     static PString GenerateCallID();
00881 
00882   protected:
00883     bool SendPDU(SIP_PDU & pdu);
00884     bool ResendCANCEL();
00885     void SetParameters(const SIPParameters & params);
00886 
00887     PDECLARE_NOTIFIER(PTimer, SIPTransaction, OnRetry);
00888     PDECLARE_NOTIFIER(PTimer, SIPTransaction, OnTimeout);
00889 
00890     enum States {
00891       NotStarted,
00892       Trying,
00893       Proceeding,
00894       Cancelling,
00895       Completed,
00896       Terminated_Success,
00897       Terminated_Timeout,
00898       Terminated_RetriesExceeded,
00899       Terminated_TransportError,
00900       Terminated_Cancelled,
00901       Terminated_Aborted,
00902       NumStates
00903     };
00904     virtual void SetTerminated(States newState);
00905 
00906     SIPEndPoint           & m_endpoint;
00907     OpalTransport         & m_transport;
00908     PSafePtr<SIPConnection> m_connection;
00909     PTimeInterval           m_retryTimeoutMin; 
00910     PTimeInterval           m_retryTimeoutMax; 
00911 
00912     States     m_state;
00913     unsigned   m_retry;
00914     PTimer     m_retryTimer;
00915     PTimer     m_completionTimer;
00916     PSyncPoint m_completed;
00917 
00918     PString              m_localInterface;
00919     OpalTransportAddress m_remoteAddress;
00920 };
00921 
00922 
00923 #define OPAL_PROXY_PARAM    "OPAL-proxy"
00924 #define OPAL_LOCAL_ID_PARAM "OPAL-local-id"
00925 
00926 
00928 // SIPResponse
00929 
00932 class SIPResponse : public SIPTransaction
00933 {
00934     PCLASSINFO(SIPResponse, SIPTransaction);
00935   public:
00936     SIPResponse(
00937       SIPEndPoint   & endpoint,
00938       StatusCodes code
00939     );
00940 
00941     virtual SIPTransaction * CreateDuplicate() const;
00942 
00943     bool Send(OpalTransport & transport, const SIP_PDU & command);
00944 };
00945 
00946 
00948 // SIPInvite
00949 
00955 class SIPInvite : public SIPTransaction
00956 {
00957     PCLASSINFO(SIPInvite, SIPTransaction);
00958   public:
00959     SIPInvite(
00960       SIPConnection & connection,
00961       const OpalRTPSessionManager & sm
00962     );
00963 
00964     virtual SIPTransaction * CreateDuplicate() const;
00965 
00966     virtual PBoolean OnReceivedResponse(SIP_PDU & response);
00967 
00968     const OpalRTPSessionManager & GetSessionManager() const { return m_rtpSessions; }
00969           OpalRTPSessionManager & GetSessionManager()       { return m_rtpSessions; }
00970 
00971   protected:
00972     OpalRTPSessionManager m_rtpSessions;
00973 };
00974 
00975 
00977 
00978 /* This is the ACK request sent when receiving a response to an outgoing
00979  * INVITE.
00980  */
00981 class SIPAck : public SIP_PDU
00982 {
00983     PCLASSINFO(SIPAck, SIP_PDU);
00984   public:
00985     SIPAck(
00986       SIPTransaction & invite,
00987       SIP_PDU & response
00988     );
00989 
00990     virtual SIPTransaction * CreateDuplicate() const;
00991 };
00992 
00993 
00995 
00996 /* This is a BYE request
00997  */
00998 class SIPBye : public SIPTransaction
00999 {
01000     PCLASSINFO(SIPBye, SIPTransaction);
01001     
01002   public:
01003     SIPBye(
01004       SIPEndPoint & ep,
01005       OpalTransport & trans,
01006       SIPDialogContext dialog
01007     );
01008     SIPBye(
01009       SIPConnection & conn
01010     );
01011 
01012     virtual SIPTransaction * CreateDuplicate() const;
01013 };
01014 
01015 
01017 
01018 class SIPRegister : public SIPTransaction
01019 {
01020     PCLASSINFO(SIPRegister, SIPTransaction);
01021   public:
01022     enum CompatibilityModes {
01023       e_FullyCompliant,                 
01026       e_CannotRegisterMultipleContacts, 
01030       e_CannotRegisterPrivateContacts   
01034     };
01035 
01037     struct Params : public SIPParameters {
01038       Params()
01039         : m_registrarAddress(m_remoteAddress)
01040         , m_compatibility(SIPRegister::e_FullyCompliant)
01041       { }
01042 
01043       Params(const Params & param)
01044         : SIPParameters(param)
01045         , m_registrarAddress(m_remoteAddress)
01046         , m_compatibility(param.m_compatibility)
01047       { }
01048 
01049       PCaselessString  & m_registrarAddress; // For backward compatibility
01050       CompatibilityModes m_compatibility;
01051     };
01052 
01053     SIPRegister(
01054       SIPEndPoint   & endpoint,
01055       OpalTransport & transport,
01056       const PString & callId,
01057       unsigned cseq,
01058       const Params & params
01059     );
01060 
01061     virtual SIPTransaction * CreateDuplicate() const;
01062 };
01063 
01064 
01065 #if PTRACING
01066 ostream & operator<<(ostream & strm, SIPRegister::CompatibilityModes mode);
01067 ostream & operator<<(ostream & strm, const SIPRegister::Params & params);
01068 #endif
01069 
01070 
01072 
01073 class SIPSubscribe : public SIPTransaction
01074 {
01075     PCLASSINFO(SIPSubscribe, SIPTransaction);
01076   public:
01079     enum PredefinedPackages {
01080       MessageSummary,
01081       Presence,
01082       Dialog,
01083 
01084       NumPredefinedPackages,
01085 
01086       Watcher = 0x8000,
01087 
01088       MessageSummaryWatcher = Watcher|MessageSummary,
01089       PresenceWatcher       = Watcher|Presence,
01090       DialogWatcher         = Watcher|Dialog,
01091 
01092       PackageMask = Watcher-1
01093     };
01094     friend PredefinedPackages operator|(PredefinedPackages p1, PredefinedPackages p2) { return (PredefinedPackages)((int)p1|(int)p2); }
01095 
01096     class EventPackage : public PCaselessString
01097     {
01098       PCLASSINFO(EventPackage, PCaselessString);
01099       public:
01100         EventPackage(PredefinedPackages = NumPredefinedPackages);
01101         explicit EventPackage(const PString & str) : PCaselessString(str) { }
01102         explicit EventPackage(const char   *  str) : PCaselessString(str) { }
01103 
01104         EventPackage & operator=(PredefinedPackages pkg);
01105         EventPackage & operator=(const PString & str) { PCaselessString::operator=(str); return *this; }
01106         EventPackage & operator=(const char   *  str) { PCaselessString::operator=(str); return *this; }
01107 
01108         bool operator==(PredefinedPackages pkg) const { return Compare(EventPackage(pkg)) == EqualTo; }
01109         bool operator==(const PString & str) const { return Compare(str) == EqualTo; }
01110         bool operator==(const char * cstr) const { return InternalCompare(0, P_MAX_INDEX, cstr) == EqualTo; }
01111         virtual Comparison InternalCompare(PINDEX offset, PINDEX length, const char * cstr) const;
01112 
01113         bool IsWatcher() const;
01114     };
01115 
01117     struct SubscriptionStatus {
01118       SIPSubscribeHandler * m_handler;           
01119       PString               m_addressofRecord;   
01120       bool                  m_wasSubscribing;    
01121       bool                  m_reSubscribing;     
01122       SIP_PDU::StatusCodes  m_reason;            
01123       OpalProductInfo       m_productInfo;       
01124       void                * m_userData;          
01125     };
01126 
01127     struct NotifyCallbackInfo {
01128       NotifyCallbackInfo(
01129         SIPEndPoint & ep,
01130         OpalTransport & trans,
01131         SIP_PDU & notify,
01132         SIP_PDU & response
01133       );
01134 
01135       bool SendResponse(
01136         SIP_PDU::StatusCodes status,
01137         const char * extra = NULL
01138       );
01139 
01140       SIPEndPoint   & m_endpoint;
01141       OpalTransport & m_transport;
01142       SIP_PDU       & m_notify;
01143       SIP_PDU       & m_response;
01144       bool            m_sendResponse;
01145     };
01146 
01147     struct Params : public SIPParameters
01148     {
01149       Params(PredefinedPackages pkg = NumPredefinedPackages)
01150         : m_agentAddress(m_remoteAddress)
01151         , m_eventPackage(pkg)
01152         , m_eventList(false)
01153       { }
01154 
01155       Params(const Params & param)
01156         : SIPParameters(param)
01157         , m_agentAddress(m_remoteAddress)
01158         , m_eventPackage(param.m_eventPackage)
01159         , m_eventList(param.m_eventList)
01160         , m_contentType(param.m_contentType)
01161         , m_onSubcribeStatus(param.m_onSubcribeStatus)
01162         , m_onNotify(param.m_onNotify)
01163       { }
01164 
01165       PCaselessString & m_agentAddress; // For backward compatibility
01166       EventPackage      m_eventPackage;
01167       bool              m_eventList;    // Enable RFC4662
01168       PCaselessString   m_contentType;  // May be \n separated list of types
01169 
01170       PNotifierTemplate<const SubscriptionStatus &> m_onSubcribeStatus;
01171       PNotifierTemplate<NotifyCallbackInfo &> m_onNotify;
01172     };
01173 
01174     SIPSubscribe(
01175         SIPEndPoint & ep,
01176         OpalTransport & trans,
01177         SIPDialogContext & dialog,
01178         const Params & params
01179     );
01180 
01181     virtual SIPTransaction * CreateDuplicate() const;
01182 };
01183 
01184 
01185 #if PTRACING
01186 ostream & operator<<(ostream & strm, const SIPSubscribe::Params & params);
01187 #endif
01188 
01189 
01190 typedef SIPSubscribe::EventPackage SIPEventPackage;
01191 
01192 
01194 
01195 class SIPHandler;
01196 
01197 class SIPEventPackageHandler
01198 {
01199 public:
01200   virtual ~SIPEventPackageHandler() { }
01201   virtual PCaselessString GetContentType() const = 0;
01202   virtual bool ValidateContentType(const PString & type, const SIPMIMEInfo & mime);
01203   virtual bool OnReceivedNOTIFY(SIPHandler & handler, SIP_PDU & request) = 0;
01204   virtual PString OnSendNOTIFY(SIPHandler & /*handler*/, const PObject * /*body*/) { return PString::Empty(); }
01205 };
01206 
01207 
01208 typedef PFactory<SIPEventPackageHandler, SIPEventPackage> SIPEventPackageFactory;
01209 
01210 
01212 
01213 class SIPNotify : public SIPTransaction
01214 {
01215     PCLASSINFO(SIPNotify, SIPTransaction);
01216   public:
01217     SIPNotify(
01218         SIPEndPoint & ep,
01219         OpalTransport & trans,
01220         SIPDialogContext & dialog,
01221         const SIPEventPackage & eventPackage,
01222         const PString & state,
01223         const PString & body
01224     );
01225 
01226     virtual SIPTransaction * CreateDuplicate() const;
01227 };
01228 
01229 
01231 
01232 class SIPPublish : public SIPTransaction
01233 {
01234     PCLASSINFO(SIPPublish, SIPTransaction);
01235   public:
01236     SIPPublish(
01237       SIPEndPoint & ep,
01238       OpalTransport & trans,
01239       const PString & id,
01240       const PString & sipIfMatch,
01241       const SIPSubscribe::Params & params,
01242       const PString & body
01243     );
01244 
01245     virtual SIPTransaction * CreateDuplicate() const;
01246 };
01247 
01248 
01250 
01251 class SIPRefer : public SIPTransaction
01252 {
01253   PCLASSINFO(SIPRefer, SIPTransaction);
01254   public:
01255     SIPRefer(
01256       SIPConnection & connection,
01257       const SIPURL & referTo,
01258       const SIPURL & referred_by = SIPURL()
01259     );
01260 
01261     virtual SIPTransaction * CreateDuplicate() const;
01262 };
01263 
01264 
01266 
01267 /* This is not a generic NOTIFY PDU, but the minimal one
01268  * that gets sent when receiving a REFER
01269  */
01270 class SIPReferNotify : public SIPTransaction
01271 {
01272     PCLASSINFO(SIPReferNotify, SIPTransaction);
01273   public:
01274     SIPReferNotify(
01275       SIPConnection & connection,
01276       StatusCodes code
01277     );
01278 
01279     virtual SIPTransaction * CreateDuplicate() const;
01280 };
01281 
01282 
01284 
01285 /* This is a MESSAGE PDU, with a body
01286  */
01287 class SIPMessage : public SIPTransaction
01288 {
01289   PCLASSINFO(SIPMessage, SIPTransaction);
01290   public:
01291     struct Params : public SIPParameters
01292     {
01293       Params()
01294         : m_contentType("text/plain;charset=UTF-8")
01295       { 
01296         m_expire = 5000;
01297       }
01298 
01299       PCaselessString             m_contentType;
01300       PString                     m_id;
01301       PString                     m_body;
01302       PAtomicInteger::IntegerType m_messageId;
01303     };
01304 
01305     SIPMessage(
01306       SIPEndPoint & ep,
01307       OpalTransport & trans,
01308       const Params & params
01309     );
01310     SIPMessage(
01311       SIPConnection & connection,
01312       const Params & params
01313     );
01314 
01315     virtual SIPTransaction * CreateDuplicate() const;
01316 
01317     const SIPURL & GetLocalAddress() const { return m_localAddress; }
01318 
01319   private:
01320     void Construct(const Params & params);
01321 
01322     SIPURL m_localAddress;
01323 };
01324 
01325 
01327 
01328 /* This is an OPTIONS request
01329  */
01330 class SIPOptions : public SIPTransaction
01331 {
01332     PCLASSINFO(SIPOptions, SIPTransaction);
01333     
01334   public:
01335     struct Params : public SIPParameters
01336     {
01337       Params()
01338         : m_acceptContent("application/sdp, application/media_control+xml, application/dtmf, application/dtmf-relay")
01339       { 
01340       }
01341 
01342       PCaselessString m_acceptContent;
01343       PCaselessString m_contentType;
01344       PString         m_body;
01345     };
01346 
01347     SIPOptions(
01348       SIPEndPoint & ep,
01349       OpalTransport & trans,
01350       const PString & id,
01351       const Params & params
01352     );
01353     SIPOptions(
01354       SIPConnection & conn,
01355       const Params & params
01356     );
01357 
01358     virtual SIPTransaction * CreateDuplicate() const;
01359 
01360   protected:
01361     void Construct(const Params & params);
01362 };
01363 
01364 
01366 
01367 /* This is an INFO request
01368  */
01369 class SIPInfo : public SIPTransaction
01370 {
01371     PCLASSINFO(SIPInfo, SIPTransaction);
01372     
01373   public:
01374     struct Params
01375     {
01376       Params(const PString & contentType = PString::Empty(),
01377              const PString & body = PString::Empty())
01378         : m_contentType(contentType)
01379         , m_body(body)
01380       {
01381       }
01382 
01383       PCaselessString m_contentType;
01384       PString         m_body;
01385     };
01386 
01387     SIPInfo(
01388       SIPConnection & conn,
01389       const Params & params
01390     );
01391 
01392     virtual SIPTransaction * CreateDuplicate() const;
01393 };
01394 
01395 
01397 
01398 /* This is a PING PDU, with a body
01399  */
01400 class SIPPing : public SIPTransaction
01401 {
01402   PCLASSINFO(SIPPing, SIPTransaction);
01403 
01404   public:
01405     SIPPing(
01406       SIPEndPoint & ep,
01407       OpalTransport & trans,
01408       const SIPURL & address
01409     );
01410 
01411     virtual SIPTransaction * CreateDuplicate() const;
01412 };
01413 
01414 
01416 
01417 /* This is a PRACK PDU
01418  */
01419 class SIPPrack : public SIPTransaction
01420 {
01421   PCLASSINFO(SIPPrack, SIPTransaction);
01422 
01423   public:
01424     SIPPrack(
01425       SIPConnection & conn,
01426       const PString & rack
01427     );
01428 
01429     virtual SIPTransaction * CreateDuplicate() const;
01430 };
01431 
01432 
01433 #endif // OPAL_SIP
01434 
01435 #endif // OPAL_SIP_SIPPDU_H
01436 
01437 
01438 // End of File ///////////////////////////////////////////////////////////////