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: 29947 $
00028  * $Author: rjongbloed $
00029  * $Date: 2013-06-13 05:59:17 -0500 (Thu, 13 Jun 2013) $
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 <ptclib/pxml.h>
00047 #include <ptclib/threadpool.h>
00048 #include <opal/transports.h>
00049 #include <rtp/rtpconn.h>
00050 
00051  
00052 class OpalMediaFormatList;
00053 class OpalProductInfo;
00054 
00055 class SIPEndPoint;
00056 class SIPConnection;
00057 class SIPHandler;
00058 class SIP_PDU;
00059 class SIPSubscribeHandler;
00060 class SIPDialogContext;
00061 class SIPMIMEInfo;
00062 class SIPTransaction;
00063 class SDPSessionDescription;
00064 
00065 
00067 // SIPURL
00068 
00074 class SIPURL : public PURL
00075 {
00076   PCLASSINFO(SIPURL, PURL);
00077   public:
00078     static const WORD DefaultPort;
00079     static const WORD DefaultSecurePort;
00080 
00081     SIPURL();
00082 
00083     SIPURL(
00084       const PURL & url
00085     ) : PURL(url) { }
00086     SIPURL & operator=(
00087       const PURL & url
00088     ) { PURL::operator=(url); return *this; }
00089 
00092     SIPURL(
00093       const char * cstr,    
00094       const char * defaultScheme = NULL 
00095     );
00096     SIPURL & operator=(
00097       const char * cstr
00098     ) { Parse(cstr); return *this; }
00099 
00102     SIPURL(
00103       const PString & str,  
00104       const char * defaultScheme = NULL 
00105     );
00106     SIPURL & operator=(
00107       const PString & str
00108     ) { Parse(str); return *this; }
00109 
00119     SIPURL(
00120       const PString & name,
00121       const OpalTransportAddress & address,
00122       WORD listenerPort = 0,
00123       const char * scheme = NULL
00124     );
00125 
00126     SIPURL(
00127       const OpalTransportAddress & address, 
00128       WORD listenerPort = 0,
00129       const char * scheme = NULL
00130     );
00131     SIPURL & operator=(
00132       const OpalTransportAddress & address
00133     );
00134 
00135     SIPURL(
00136       const SIPMIMEInfo & mime,
00137       const char * name
00138     );
00139 
00148     virtual Comparison Compare(
00149       const PObject & obj   
00150     ) const;
00151 
00155     PString AsQuotedString() const;
00156 
00159     PString GetDisplayName(PBoolean useDefault = true) const;
00160     
00161     void SetDisplayName(const PString & str) 
00162     {
00163       m_displayName = str;
00164     }
00165 
00167     const PStringOptions & GetFieldParameters() const { return m_fieldParameters; }
00168           PStringOptions & GetFieldParameters()       { return m_fieldParameters; }
00169 
00171     PCaselessString GetTransportProto() const;
00172 
00178     OpalTransportAddress GetTransportAddress(
00179       PINDEX dnsEntry = P_MAX_INDEX
00180     ) const;
00181 
00184     void SetHostAddress(const OpalTransportAddress & addr);
00185 
00186     enum UsageContext {
00187       ExternalURI,   
00188       RequestURI,    
00189       ToURI,         
00190       FromURI,       
00191       RouteURI,      
00192       RedirectURI,   
00193       ContactURI,    
00194       RegContactURI, 
00195       RegisterURI    
00196     };
00197 
00203     void Sanitise(
00204       UsageContext context  
00205     );
00206 
00208     static PString GenerateTag();
00209 
00211     void SetTag(
00212       const PString & tag = PString::Empty(),
00213       bool force = false
00214     );
00215 
00217     PString GetTag() const;
00218 
00219   protected:
00220     void ParseAsAddress(
00221       const PString & name,
00222       const OpalTransportAddress & address,
00223       WORD listenerPort,
00224       const char * scheme);
00225 
00226     // Override from PURL()
00227     virtual PBoolean InternalParse(
00228       const char * cstr,
00229       const char * defaultScheme
00230     ) { return ReallyInternalParse(false, cstr, defaultScheme); }
00231 
00232     bool ReallyInternalParse(
00233       bool fromField,
00234       const char * cstr,
00235       const char * defaultScheme
00236     );
00237     WORD GetDefaultPort() const;
00238 
00239     PString        m_displayName;
00240     PStringOptions m_fieldParameters;
00241 };
00242 
00243 
00244 class SIPURLList : public std::list<SIPURL>
00245 {
00246   public:
00247     bool FromString(
00248       const PString & str,
00249       SIPURL::UsageContext context = SIPURL::RouteURI,
00250       bool reversed = false
00251     );
00252     PString ToString() const;
00253     SIPURL FindCompatible(const OpalTransportAddress & addr PTRACE_PARAM(, const char * listType)) const;
00254     friend ostream & operator<<(ostream & strm, const SIPURLList & urls);
00255 };
00256 
00257 
00258 
00260 // SIPMIMEInfo
00261 
00292 class SIPMIMEInfo : public PMIMEInfo
00293 {
00294   PCLASSINFO(SIPMIMEInfo, PMIMEInfo);
00295   public:
00296     SIPMIMEInfo(bool compactForm = false);
00297 
00298     virtual void PrintOn(ostream & strm) const;
00299     virtual bool InternalAddMIME(const PString & fieldName, const PString & fieldValue);
00300 
00301     void SetCompactForm(bool form) { compactForm = form; }
00302 
00303     PCaselessString GetContentType(bool includeParameters = false) const;
00304     void SetContentType(const PString & v);
00305 
00306     PCaselessString GetContentEncoding() const;
00307     void SetContentEncoding(const PString & v);
00308 
00309     SIPURL GetFrom() const;
00310     void SetFrom(const SIPURL & v);
00311 
00312     SIPURL GetPAssertedIdentity() const;
00313     void SetPAssertedIdentity(const PString & v);
00314 
00315     SIPURL GetPPreferredIdentity() const;
00316     void SetPPreferredIdentity(const PString & v);
00317 
00318     PString GetAccept() const;
00319     void SetAccept(const PString & v);
00320 
00321     PString GetAcceptEncoding() const;
00322     void SetAcceptEncoding(const PString & v);
00323 
00324     PString GetAcceptLanguage() const;
00325     void SetAcceptLanguage(const PString & v);
00326 
00327     PString GetAllow() const;
00328     unsigned GetAllowBitMask() const;
00329     void SetAllow(const PString & v);
00330 
00331     PString GetCallID() const;
00332     void SetCallID(const PString & v);
00333 
00334     SIPURL GetContact() const;
00335     bool GetContacts(SIPURLList & contacts) const;
00336     void SetContact(const PString & v);
00337 
00338     PString GetSubject() const;
00339     void SetSubject(const PString & v);
00340 
00341     SIPURL GetTo() const;
00342     void SetTo(const SIPURL & v);
00343 
00344     PString GetVia() const;
00345     void SetVia(const PString & v);
00346 
00347     bool GetViaList(PStringList & v) const;
00348     void SetViaList(const PStringList & v);
00349 
00350     PString GetFirstVia() const;
00351     OpalTransportAddress GetViaReceivedAddress() const;
00352 
00353     SIPURL GetReferTo() const;
00354     void SetReferTo(const PString & r);
00355 
00356     SIPURL GetReferredBy() const;
00357     void SetReferredBy(const PString & r);
00358 
00359     PINDEX  GetContentLength() const;
00360     void SetContentLength(PINDEX v);
00361     PBoolean IsContentLengthPresent() const;
00362 
00363     PString GetCSeq() const;
00364     void SetCSeq(const PString & v);
00365 
00366     PString GetDate() const;
00367     void SetDate(const PString & v);
00368     void SetDate(const PTime & t);
00369     void SetDate(void); // set to current date
00370 
00371     unsigned GetExpires(unsigned dflt = UINT_MAX) const;// returns default value if not found
00372     void SetExpires(unsigned v);
00373 
00374     unsigned GetMaxForwards() const;
00375     void SetMaxForwards(PINDEX v);
00376 
00377     unsigned GetMinExpires() const;
00378     void SetMinExpires(PINDEX v);
00379 
00380     PString GetProxyAuthenticate() const;
00381     void SetProxyAuthenticate(const PString & v);
00382 
00383     PString GetRoute() const;
00384     bool GetRoute(SIPURLList & proxies) const;
00385     void SetRoute(const PString & v);
00386     void SetRoute(const SIPURLList & proxies);
00387 
00388     PString GetRecordRoute() const;
00389     bool GetRecordRoute(SIPURLList & proxies, bool reversed) const;
00390     void SetRecordRoute(const PString & v);
00391     void SetRecordRoute(const SIPURLList & proxies);
00392 
00393     unsigned GetCSeqIndex() const { return GetCSeq().AsUnsigned(); }
00394 
00395     PStringSet GetRequire() const;
00396     void SetRequire(const PStringSet & v);
00397     void AddRequire(const PString & v);
00398 
00399     PStringSet GetSupported() const;
00400     void SetSupported(const PStringSet & v);
00401     void AddSupported(const PString & v);
00402 
00403     PStringSet GetUnsupported() const;
00404     void SetUnsupported(const PStringSet & v);
00405     void AddUnsupported(const PString & v);
00406     
00407     PString GetEvent() const;
00408     void SetEvent(const PString & v);
00409     
00410     PCaselessString GetSubscriptionState(PStringToString & info) const;
00411     void SetSubscriptionState(const PString & v);
00412     
00413     PString GetUserAgent() const;
00414     void SetUserAgent(const PString & v);
00415 
00416     PString GetOrganization() const;
00417     void SetOrganization(const PString & v);
00418 
00419     void GetProductInfo(OpalProductInfo & info) const;
00420     void SetProductInfo(const PString & ua, const OpalProductInfo & info);
00421 
00422     PString GetWWWAuthenticate() const;
00423     void SetWWWAuthenticate(const PString & v);
00424 
00425     PString GetSIPIfMatch() const;
00426     void SetSIPIfMatch(const PString & v);
00427 
00428     PString GetSIPETag() const;
00429     void SetSIPETag(const PString & v);
00430 
00431     void GetAlertInfo(PString & info, int & appearance) const;
00432     void SetAlertInfo(const PString & info, int appearance);
00433 
00434     PString GetCallInfo() const;
00435 
00436     PString GetAllowEvents() const;
00437     void SetAllowEvents(const PString & v);
00438     void SetAllowEvents(const PStringSet & list);
00439 
00442     PString GetFieldParameter(
00443       const PString & fieldName,    
00444       const PString & paramName,    
00445       const PString & defaultValue = PString::Empty()  
00446     ) const { return ExtractFieldParameter((*this)(fieldName), paramName, defaultValue); }
00447 
00452     void SetFieldParameter(
00453       const PString & fieldName,    
00454       const PString & paramName,    
00455       const PString & newValue      
00456     ) { SetAt(fieldName, InsertFieldParameter((*this)(fieldName), paramName, newValue)); }
00457 
00460     static PString ExtractFieldParameter(
00461       const PString & fieldValue,   
00462       const PString & paramName,    
00463       const PString & defaultValue = PString::Empty()  
00464     );
00465 
00470     static PString InsertFieldParameter(
00471       const PString & fieldValue,   
00472       const PString & paramName,    
00473       const PString & newValue      
00474     );
00475 
00476   protected:
00477     PStringSet GetTokenSet(const char * field) const;
00478     void AddTokenSet(const char * field, const PString & token);
00479     void SetTokenSet(const char * field, const PStringSet & tokens);
00480 
00482     bool compactForm;
00483 };
00484 
00485 
00487 // SIPAuthentication
00488 
00489 typedef PHTTPClientAuthentication SIPAuthentication;
00490 
00491 class SIPAuthenticator : public PHTTPClientAuthentication::AuthObject
00492 {
00493   public:
00494     SIPAuthenticator(SIP_PDU & pdu);
00495     virtual PMIMEInfo & GetMIME();
00496     virtual PString GetURI();
00497     virtual PString GetEntityBody();
00498     virtual PString GetMethod();
00499 
00500   protected:  
00501     SIP_PDU & m_pdu;
00502 };
00503 
00504 
00505 
00507 // SIP_PDU
00508 
00514 class SIP_PDU : public PSafeObject
00515 {
00516   PCLASSINFO(SIP_PDU, PSafeObject);
00517   public:
00518     enum Methods {
00519       Method_INVITE,
00520       Method_ACK,
00521       Method_OPTIONS,
00522       Method_BYE,
00523       Method_CANCEL,
00524       Method_REGISTER,
00525       Method_SUBSCRIBE,
00526       Method_NOTIFY,
00527       Method_REFER,
00528       Method_MESSAGE,
00529       Method_INFO,
00530       Method_PING,
00531       Method_PUBLISH,
00532       Method_PRACK,
00533       NumMethods
00534     };
00535 
00536     enum StatusCodes {
00537       IllegalStatusCode,
00538       Local_TransportError,
00539       Local_BadTransportAddress,
00540       Local_Timeout,
00541       Local_NoCompatibleListener,
00542       Local_CannotMapScheme,
00543       Local_TransportLost,
00544       Local_KeepAlive,
00545       Local_NotAuthenticated,
00546 
00547       Information_Trying                  = 100,
00548       Information_Ringing                 = 180,
00549       Information_CallForwarded           = 181,
00550       Information_Queued                  = 182,
00551       Information_Session_Progress        = 183,
00552 
00553       Successful_OK                       = 200,
00554       Successful_Accepted                 = 202,
00555 
00556       Redirection_MultipleChoices         = 300,
00557       Redirection_MovedPermanently        = 301,
00558       Redirection_MovedTemporarily        = 302,
00559       Redirection_UseProxy                = 305,
00560       Redirection_AlternativeService      = 380,
00561 
00562       Failure_BadRequest                  = 400,
00563       Failure_UnAuthorised                = 401,
00564       Failure_PaymentRequired             = 402,
00565       Failure_Forbidden                   = 403,
00566       Failure_NotFound                    = 404,
00567       Failure_MethodNotAllowed            = 405,
00568       Failure_NotAcceptable               = 406,
00569       Failure_ProxyAuthenticationRequired = 407,
00570       Failure_RequestTimeout              = 408,
00571       Failure_Conflict                    = 409,
00572       Failure_Gone                        = 410,
00573       Failure_LengthRequired              = 411,
00574       Failure_RequestEntityTooLarge       = 413,
00575       Failure_RequestURITooLong           = 414,
00576       Failure_UnsupportedMediaType        = 415,
00577       Failure_UnsupportedURIScheme        = 416,
00578       Failure_BadExtension                = 420,
00579       Failure_ExtensionRequired           = 421,
00580       Failure_IntervalTooBrief            = 423,
00581       Failure_UnresolvableDestination     = 476,
00582       Failure_TemporarilyUnavailable      = 480,
00583       Failure_TransactionDoesNotExist     = 481,
00584       Failure_LoopDetected                = 482,
00585       Failure_TooManyHops                 = 483,
00586       Failure_AddressIncomplete           = 484,
00587       Failure_Ambiguous                   = 485,
00588       Failure_BusyHere                    = 486,
00589       Failure_RequestTerminated           = 487,
00590       Failure_NotAcceptableHere           = 488,
00591       Failure_BadEvent                    = 489,
00592       Failure_RequestPending              = 491,
00593       Failure_Undecipherable              = 493,
00594 
00595       Failure_InternalServerError         = 500,
00596       Failure_NotImplemented              = 501,
00597       Failure_BadGateway                  = 502,
00598       Failure_ServiceUnavailable          = 503,
00599       Failure_ServerTimeout               = 504,
00600       Failure_SIPVersionNotSupported      = 505,
00601       Failure_MessageTooLarge             = 513,
00602 
00603       GlobalFailure_BusyEverywhere        = 600,
00604       GlobalFailure_Decline               = 603,
00605       GlobalFailure_DoesNotExistAnywhere  = 604,
00606       GlobalFailure_NotAcceptable         = 606,
00607 
00608       MaxStatusCode                       = 699
00609     };
00610 
00611     static PString GetStatusCodeDescription(int code);
00612     friend ostream & operator<<(ostream & strm, StatusCodes status);
00613 
00614     SIP_PDU(
00615       Methods method = SIP_PDU::NumMethods,
00616       const OpalTransportPtr & transport = NULL
00617     );
00618 
00622     SIP_PDU(
00623       const SIP_PDU & request,
00624       StatusCodes code,
00625       const SDPSessionDescription * sdp = NULL
00626     );
00627 
00628     SIP_PDU(const SIP_PDU &);
00629     SIP_PDU & operator=(const SIP_PDU &);
00630     ~SIP_PDU();
00631 
00632     void PrintOn(
00633       ostream & strm
00634     ) const;
00635 
00636     void InitialiseHeaders(
00637       const SIPURL & dest,
00638       const SIPURL & to,
00639       const SIPURL & from,
00640       const PString & callID,
00641       unsigned cseq
00642     );
00643     void InitialiseHeaders(
00644       SIPDialogContext & dialog,
00645       unsigned cseq = 0
00646     );
00647     void InitialiseHeaders(
00648       SIPConnection & connection,
00649       unsigned cseq = 0
00650     );
00651     void InitialiseHeaders(
00652       const SIP_PDU & request
00653     );
00654 
00659     bool SetRoute(const SIPURLList & routeSet);
00660     bool SetRoute(const SIPURL & proxy);
00661 
00664     void SetAllow(unsigned bitmask);
00665 
00668     StatusCodes Read();
00669     StatusCodes Parse(
00670       istream & strm,
00671       bool truncated
00672     );
00673 
00676     bool Send();
00677 
00680     bool SendResponse(
00681       StatusCodes code
00682     );
00683 
00687     void Build(PString & pduStr, PINDEX & pduLen);
00688 
00689     const PString & GetTransactionID() const { return m_transactionID; }
00690 
00691     Methods GetMethod() const                { return m_method; }
00692     StatusCodes GetStatusCode () const       { return m_statusCode; }
00693     void SetStatusCode (StatusCodes c)       { m_statusCode = c; }
00694     const SIPURL & GetURI() const            { return m_uri; }
00695     void SetURI(const SIPURL & newuri)       { m_uri = newuri; }
00696     unsigned GetVersionMajor() const         { return m_versionMajor; }
00697     unsigned GetVersionMinor() const         { return m_versionMinor; }
00698     void SetCSeq(unsigned cseq);
00699     const PString & GetEntityBody() const    { return m_entityBody; }
00700     void SetEntityBody(const PString & body) { m_entityBody = body; }
00701     void SetEntityBody();
00702     const PString & GetInfo() const          { return m_info; }
00703     void SetInfo(const PString & info)       { m_info = info; }
00704     const SIPMIMEInfo & GetMIME() const      { return m_mime; }
00705           SIPMIMEInfo & GetMIME()            { return m_mime; }
00706     SDPSessionDescription * GetSDP()         { return m_SDP; }
00707     void SetSDP(SDPSessionDescription * sdp);
00708     bool DecodeSDP(const OpalMediaFormatList & masterList);
00709 
00710     const PString & GetExternalTransportAddress() const { return m_externalTransportAddress; }
00711     OpalTransportPtr GetTransport()  const    { return m_transport; }
00712 
00713   protected:
00714     void CalculateVia();
00715     StatusCodes InternalSend(bool canDoTCP);
00716 
00717     Methods     m_method;                 // Request type, ==NumMethods for Response
00718     StatusCodes m_statusCode;
00719     SIPURL      m_uri;                    // display name & URI, no tag
00720     unsigned    m_versionMajor;
00721     unsigned    m_versionMinor;
00722     PString     m_info;
00723     SIPMIMEInfo m_mime;
00724     PString     m_entityBody;
00725     PString     m_transactionID;
00726 
00727     SDPSessionDescription * m_SDP;
00728 
00729     OpalTransportPtr     m_transport;
00730     OpalTransportAddress m_viaAddress;
00731     OpalTransportAddress m_externalTransportAddress;
00732 };
00733 
00734 
00735 PQUEUE(SIP_PDU_Queue, SIP_PDU);
00736 
00737 
00738 #if PTRACING
00739 ostream & operator<<(ostream & strm, SIP_PDU::Methods method);
00740 #endif
00741 
00742 
00744 // SIPDialogContext
00745 
00748 class SIPDialogContext
00749 {
00750   public:
00751     SIPDialogContext();
00752     SIPDialogContext(const SIPMIMEInfo & mime);
00753 
00754     PString AsString() const;
00755     bool FromString(
00756       const PString & str
00757     );
00758 
00759     const PString & GetCallID() const { return m_callId; }
00760     void SetCallID(const PString & id) { m_callId = id; }
00761 
00762     const SIPURL & GetRequestURI() const { return m_requestURI; }
00763     void SetRequestURI(const SIPURL & url);
00764 
00765     const PString & GetLocalTag() const { return m_localTag; }
00766     void SetLocalTag(const PString & tag) { m_localTag = tag; }
00767 
00768     const SIPURL & GetLocalURI() const { return m_localURI; }
00769     void SetLocalURI(const SIPURL & url);
00770 
00771     const PString & GetRemoteTag() const { return m_remoteTag; }
00772     void SetRemoteTag(const PString & tag) { m_remoteTag = tag; }
00773 
00774     const SIPURL & GetRemoteURI() const { return m_remoteURI; }
00775     void SetRemoteURI(const SIPURL & url);
00776 
00777     const SIPURLList & GetRouteSet() const { return m_routeSet; }
00778     void SetRouteSet(const PString & str) { m_routeSet.FromString(str); }
00779 
00780     const SIPURL & GetProxy() const { return m_proxy; }
00781     void SetProxy(const SIPURL & proxy, bool addToRouteSet);
00782 
00783     void Update(const SIP_PDU & response);
00784 
00785     unsigned GetNextCSeq();
00786     void IncrementCSeq(unsigned inc) { m_lastSentCSeq += inc; }
00787 
00788     bool IsDuplicateCSeq(unsigned sequenceNumber);
00789 
00790     bool IsEstablished() const
00791     {
00792       return !m_callId.IsEmpty() &&
00793              !m_requestURI.IsEmpty() &&
00794              !m_localTag.IsEmpty() &&
00795              !m_remoteTag.IsEmpty();
00796     }
00797 
00798     OpalTransportAddress GetRemoteTransportAddress(PINDEX dnsEntry) const;
00799     const PString & GetInterface() const { return m_interface; }
00800     void SetInterface(const PString & newInterface) { m_interface = newInterface; }
00801 
00802     void SetForking(bool f) { m_forking = f; }
00803 
00804   protected:
00805     PString     m_callId;
00806     SIPURL      m_requestURI;
00807     SIPURL      m_localURI;
00808     PString     m_localTag;
00809     SIPURL      m_remoteURI;
00810     PString     m_remoteTag;
00811     SIPURLList  m_routeSet;
00812     unsigned    m_lastSentCSeq;
00813     unsigned    m_lastReceivedCSeq;
00814     OpalTransportAddress m_externalTransportAddress;
00815     bool        m_forking;
00816     SIPURL      m_proxy;
00817     PString     m_interface;
00818 };
00819 
00820 
00822 
00823 struct SIPParameters
00824 {
00825   SIPParameters(
00826     const PString & aor = PString::Empty(),
00827     const PString & remote = PString::Empty()
00828   );
00829 
00830   bool Normalise(
00831     const PString & defaultUser,
00832     const PTimeInterval & defaultExpire
00833   );
00834 
00835   PCaselessString m_remoteAddress;
00836   PCaselessString m_localAddress;
00837   PCaselessString m_proxyAddress;
00838   PCaselessString m_addressOfRecord;
00839   PCaselessString m_contactAddress;
00840   PCaselessString m_interface;
00841   SIPMIMEInfo     m_mime;
00842   PString         m_authID;
00843   PString         m_password;
00844   PString         m_realm;
00845   unsigned        m_expire;
00846   unsigned        m_restoreTime;
00847   PTimeInterval   m_minRetryTime;
00848   PTimeInterval   m_maxRetryTime;
00849   void          * m_userData;
00850 };
00851 
00852 
00853 #if PTRACING
00854 ostream & operator<<(ostream & strm, const SIPParameters & params);
00855 #endif
00856 
00857 
00859 // Thread pooling stuff
00860 //
00861 // Timer call back mechanism using PNOTIFIER is too prone to deadlocks, we
00862 // want to use the existing thread pool for handling incoming PDUs.
00863 
00864 class SIPWorkItem : public PObject
00865 {
00866     PCLASSINFO(SIPWorkItem, PObject);
00867   public:
00868     SIPWorkItem(SIPEndPoint & ep, const PString & token);
00869 
00870     virtual void Work() = 0;
00871 
00872     bool GetTarget(PSafePtr<SIPTransaction> & transaction);
00873     bool GetTarget(PSafePtr<SIPConnection> & connection);
00874     bool GetTarget(PSafePtr<SIPHandler> & handler);
00875 
00876   protected:
00877     SIPEndPoint & m_endpoint;
00878     PString       m_token;
00879 };
00880 
00881 
00882 class SIPThreadPool : public PQueuedThreadPool<SIPWorkItem>
00883 {
00884     typedef PQueuedThreadPool<SIPWorkItem> BaseClass;
00885     PCLASSINFO(SIPThreadPool, BaseClass);
00886   public:
00887     SIPThreadPool(unsigned maxWorkers, const char * threadName)
00888       : BaseClass(maxWorkers, 0, threadName, PThread::HighPriority)
00889     {
00890     }
00891 };
00892 
00893 
00894 template <class Target_T>
00895 class SIPTimeoutWorkItem : public SIPWorkItem
00896 {
00897     PCLASSINFO(SIPTimeoutWorkItem, SIPWorkItem);
00898   public:
00899     typedef void (Target_T::* Callback)();
00900 
00901     SIPTimeoutWorkItem(SIPEndPoint & ep, const PString & token, Callback callback)
00902       : SIPWorkItem(ep, token)
00903       , m_callback(callback)
00904     {
00905     }
00906 
00907     virtual void Work()
00908     {
00909       PSafePtr<Target_T> target;
00910       if (GetTarget(target)) {
00911         PTRACE_CONTEXT_ID_PUSH_THREAD(target);
00912         (target->*m_callback)();
00913         PTRACE(4, "SIP\tHandled timeout");
00914       }
00915     }
00916 
00917   protected:
00918     Callback m_callback;
00919 };
00920 
00921 
00922 template <class Target_T>
00923 class SIPPoolTimer : public PPoolTimerArg3<SIPTimeoutWorkItem<Target_T>,
00924                                            SIPEndPoint &,
00925                                            PString,
00926                                            void (Target_T::*)(),
00927                                            SIPWorkItem>
00928 {
00929     typedef SIPTimeoutWorkItem<Target_T> Work_T;
00930     typedef PPoolTimerArg3<Work_T, SIPEndPoint &, PString, void (Target_T::*)(), SIPWorkItem> BaseClass;
00931     PCLASSINFO(SIPPoolTimer, BaseClass);
00932   private:
00933     PString m_token;
00934   public:
00935     SIPPoolTimer(SIPThreadPool & pool, SIPEndPoint & ep, const PString & token, void (Target_T::* callback)())
00936       : BaseClass(pool, ep, token, callback)
00937       , m_token(token)
00938     {
00939     }
00940 
00941     virtual const char * GetGroup(const Work_T &) const { return m_token; }
00942 
00943     PTIMER_OPERATORS(SIPPoolTimer);
00944 };
00945 
00946 
00948 // SIPTransaction
00949 
00950 class SIPTransactionOwner
00951 {
00952   public:
00953     SIPTransactionOwner(
00954       PSafeObject & object,
00955       SIPEndPoint & endpoint
00956     );
00957     virtual ~SIPTransactionOwner();
00958 
00959     virtual PString GetAuthID() const = 0;
00960     virtual PString GetPassword() const { return PString::Empty(); }
00961     virtual unsigned GetAllowedMethods() const;
00962 
00963     virtual void OnStartTransaction(SIPTransaction & /*transaction*/) { }
00964     virtual void OnReceivedResponse(SIPTransaction & transaction, SIP_PDU & response);
00965     virtual void OnTransactionFailed(SIPTransaction & transaction);
00966 
00967     void FinaliseForking(SIPTransaction & transaction, SIP_PDU & response);
00968     bool CleanPendingTransactions();
00969     void AbortPendingTransactions(bool all = true);
00970 
00971     virtual SIP_PDU::StatusCodes StartTransaction(
00972       const OpalTransport::WriteConnectCallback & function
00973     );
00974 
00975     SIP_PDU::StatusCodes SwitchTransportProto(const char * proto, OpalTransportPtr * transport);
00976 
00977     SIP_PDU::StatusCodes HandleAuthentication(const SIP_PDU & response);
00978 
00979     SIPEndPoint & GetEndPoint() const { return m_endpoint; }
00980     OpalTransportAddress GetRemoteTransportAddress() const { return m_dialog.GetRemoteTransportAddress(m_dnsEntry); }
00981     const SIPURL & GetRequestURI() const { return m_dialog.GetRequestURI(); }
00982     const SIPURL & GetRemoteURI() const { return m_dialog.GetRemoteURI(); }
00983     const SIPURL & GetProxy() const { return m_dialog.GetProxy(); }
00984     const PString & GetInterface() const { return m_dialog.GetInterface(); }
00985     void ResetInterface() { m_dialog.SetInterface(PString::Empty()); }
00986     PINDEX GetDNSEntry() const { return m_dnsEntry; }
00987     SIPAuthentication * GetAuthenticator() const { return m_authentication; }
00988     SIPDialogContext & GetDialog() { return m_dialog; }
00989     const SIPDialogContext & GetDialog() const { return m_dialog; }
00990 
00991   protected:
00992     PSafeObject       & m_object;
00993     SIPEndPoint       & m_endpoint;
00994     SIPDialogContext    m_dialog; // Not all derived classes use this as a dialog, but many fields useful
00995     PINDEX              m_dnsEntry;
00996     SIPAuthentication * m_authentication;
00997     unsigned            m_authenticateErrors;
00998 
00999     PSafeList<SIPTransaction> m_transactions;
01000     PMutex                    m_forkMutex;
01001 
01002   friend class SIPTransaction;
01003 };
01004 
01005 
01006 class SIPTransactionBase : public SIP_PDU
01007 {
01008     PCLASSINFO(SIPTransactionBase, SIP_PDU);
01009   protected:
01010     SIPTransactionBase(
01011       Methods method
01012     ) : SIP_PDU(method) { }
01013 
01014   public:
01015     SIPTransactionBase(
01016       const PString & transactionID
01017     ) { m_transactionID = transactionID; }
01018 
01019     Comparison Compare(
01020       const PObject & other
01021     ) const;
01022 
01023     virtual bool IsTerminated() const { return true; }
01024 };
01025 
01026 
01037 class SIPTransaction : public SIPTransactionBase
01038 {
01039     PCLASSINFO(SIPTransaction, SIPTransactionBase);
01040   protected:
01041     SIPTransaction(
01042       Methods method,
01043       SIPTransactionOwner * owner,
01044       OpalTransport * transport,
01045       bool deleteOwner = false
01046     );
01047   public:
01048     ~SIPTransaction();
01049 
01050     /* Under some circumstances a new transaction with all the same parameters
01051        but different ID needs to be created, e.g. when get authentication error. */
01052     virtual SIPTransaction * CreateDuplicate() const = 0;
01053 
01054     bool Start();
01055     bool IsTrying()     const { return m_state == Trying; }
01056     bool IsProceeding() const { return m_state == Proceeding; }
01057     bool IsInProgress() const { return m_state == Trying || m_state == Proceeding; }
01058     bool IsFailed()     const { return m_state > Terminated_Success; }
01059     bool IsCompleted()  const { return m_state >= Completed; }
01060     bool IsCanceled()   const { return m_state == Cancelling || m_state == Terminated_Cancelled || m_state == Terminated_Aborted; }
01061     bool IsTerminated() const { return m_state >= Terminated_Success; }
01062 
01063     void WaitForCompletion();
01064     PBoolean Cancel();
01065     void Abort();
01066 
01067     virtual PBoolean OnReceivedResponse(SIP_PDU & response);
01068     virtual PBoolean OnCompleted(SIP_PDU & response);
01069 
01070     SIPEndPoint & GetEndPoint() const { return m_owner->GetEndPoint(); }
01071     SIPConnection * GetConnection() const;
01072     PString         GetInterface()  const { return m_localInterface; }
01073 
01074     static PString GenerateCallID();
01075 
01076   protected:
01077     bool ResendCANCEL();
01078     void SetParameters(const SIPParameters & params);
01079 
01080     typedef SIPPoolTimer<SIPTransaction> PoolTimer;
01081 
01082     void OnRetry();
01083     void OnTimeout();
01084 
01085     P_DECLARE_TRACED_ENUM(States,
01086       NotStarted,
01087       Trying,
01088       Proceeding,
01089       Cancelling,
01090       Completed,
01091       Terminated_Success,
01092       Terminated_Timeout,
01093       Terminated_RetriesExceeded,
01094       Terminated_TransportError,
01095       Terminated_Cancelled,
01096       Terminated_Aborted
01097     );
01098     virtual void SetTerminated(States newState);
01099 
01100     SIPTransactionOwner * m_owner;
01101     bool                  m_deleteOwner;
01102 
01103     PTimeInterval m_retryTimeoutMin; 
01104     PTimeInterval m_retryTimeoutMax; 
01105 
01106     States     m_state;
01107     unsigned   m_retry;
01108     PoolTimer  m_retryTimer;
01109     PoolTimer  m_completionTimer;
01110     PSyncPoint m_completed;
01111     bool       m_pduSizeOK;
01112     PString    m_localInterface;
01113 
01114   friend class SIPConnection;
01115 };
01116 
01117 
01118 #define OPAL_PROXY_PARAM     "OPAL-proxy"
01119 #define OPAL_LOCAL_ID_PARAM  "OPAL-local-id"
01120 #define OPAL_INTERFACE_PARAM "OPAL-interface"
01121 
01122 
01124 // SIPResponse
01125 
01128 class SIPResponse : public SIPTransaction
01129 {
01130     PCLASSINFO(SIPResponse, SIPTransaction);
01131   public:
01132     SIPResponse(
01133       SIPEndPoint & endpoint,
01134       const SIP_PDU & command,
01135       StatusCodes code
01136     );
01137 
01138     virtual SIPTransaction * CreateDuplicate() const;
01139 
01140     bool Resend(SIP_PDU & command);
01141 };
01142 
01143 
01145 // SIPInvite
01146 
01152 class SIPInvite : public SIPTransaction
01153 {
01154     PCLASSINFO(SIPInvite, SIPTransaction);
01155   public:
01156     SIPInvite(
01157       SIPConnection & connection,
01158       OpalTransport * transport = NULL
01159     );
01160 
01161     virtual SIPTransaction * CreateDuplicate() const;
01162 
01163     virtual PBoolean OnReceivedResponse(SIP_PDU & response);
01164 
01165     mutable OpalRTPConnection::SessionMap m_sessions;
01166 };
01167 
01168 
01170 
01171 /* This is the ACK request sent when receiving a response to an outgoing
01172  * INVITE.
01173  */
01174 class SIPAck : public SIP_PDU
01175 {
01176     PCLASSINFO(SIPAck, SIP_PDU);
01177   public:
01178     SIPAck(
01179       const SIPTransaction & invite,
01180       const SIP_PDU & response
01181     );
01182 
01183     virtual SIPTransaction * CreateDuplicate() const;
01184 };
01185 
01186 
01188 
01189 /* This is a BYE request
01190  */
01191 class SIPBye : public SIPTransaction
01192 {
01193     PCLASSINFO(SIPBye, SIPTransaction);
01194   public:
01195     SIPBye(
01196       SIPEndPoint & endpoint,
01197       SIPDialogContext & dialog
01198     );
01199     SIPBye(
01200       SIPConnection & conn
01201     );
01202 
01203     virtual SIPTransaction * CreateDuplicate() const;
01204 };
01205 
01206 
01208 
01209 class SIPRegister : public SIPTransaction
01210 {
01211     PCLASSINFO(SIPRegister, SIPTransaction);
01212   public:
01213     P_DECLARE_TRACED_ENUM(CompatibilityModes,
01214       e_FullyCompliant,                 
01217       e_CannotRegisterMultipleContacts, 
01221       e_CannotRegisterPrivateContacts,  
01225       e_HasApplicationLayerGateway,     
01229       e_RFC5626                         
01232     );
01233 
01235     struct Params : public SIPParameters {
01236       Params()
01237         : m_registrarAddress(m_remoteAddress)
01238         , m_compatibility(SIPRegister::e_FullyCompliant)
01239         , m_instanceId(NULL)
01240       { }
01241 
01242       Params(const Params & param)
01243         : SIPParameters(param)
01244         , m_registrarAddress(m_remoteAddress)
01245         , m_compatibility(param.m_compatibility)
01246         , m_instanceId(param.m_instanceId)
01247       { }
01248 
01249       PCaselessString  & m_registrarAddress; // For backward compatibility
01250       CompatibilityModes m_compatibility;
01251       PGloballyUniqueID  m_instanceId;
01252     };
01253 
01254     SIPRegister(
01255       SIPTransactionOwner & owner,
01256       OpalTransport & transport,
01257       const PString & callId,
01258       unsigned cseq,
01259       const Params & params
01260     );
01261 
01262     virtual SIPTransaction * CreateDuplicate() const;
01263 };
01264 
01265 
01266 #if PTRACING
01267 ostream & operator<<(ostream & strm, SIPRegister::CompatibilityModes mode);
01268 ostream & operator<<(ostream & strm, const SIPRegister::Params & params);
01269 #endif
01270 
01271 
01273 
01274 class SIPSubscribe : public SIPTransaction
01275 {
01276     PCLASSINFO(SIPSubscribe, SIPTransaction);
01277   public:
01280     enum PredefinedPackages {
01281       MessageSummary,
01282       Presence,
01283       Dialog,
01284       Reg,
01285       Conference,
01286 
01287       NumPredefinedPackages,
01288 
01289       Watcher = 0x8000,
01290 
01291       MessageSummaryWatcher = Watcher|MessageSummary,
01292       PresenceWatcher       = Watcher|Presence,
01293       DialogWatcher         = Watcher|Dialog,
01294 
01295       PackageMask = Watcher-1
01296     };
01297     friend PredefinedPackages operator|(PredefinedPackages p1, PredefinedPackages p2) { return (PredefinedPackages)((int)p1|(int)p2); }
01298 
01299     class EventPackage : public PCaselessString
01300     {
01301       PCLASSINFO(EventPackage, PCaselessString);
01302       public:
01303         EventPackage(PredefinedPackages = NumPredefinedPackages);
01304         explicit EventPackage(const PString & str) : PCaselessString(str) { }
01305         explicit EventPackage(const char   *  str) : PCaselessString(str) { }
01306 
01307         EventPackage & operator=(PredefinedPackages pkg);
01308         EventPackage & operator=(const PString & str) { PCaselessString::operator=(str); return *this; }
01309         EventPackage & operator=(const char   *  str) { PCaselessString::operator=(str); return *this; }
01310 
01311         bool operator==(PredefinedPackages pkg) const { return Compare(EventPackage(pkg)) == EqualTo; }
01312         bool operator==(const PString & str) const { return Compare(str) == EqualTo; }
01313         bool operator==(const char * cstr) const { return InternalCompare(0, P_MAX_INDEX, cstr) == EqualTo; }
01314         virtual Comparison InternalCompare(PINDEX offset, PINDEX length, const char * cstr) const;
01315 
01316         bool IsWatcher() const;
01317     };
01318 
01320     struct SubscriptionStatus {
01321       SIPSubscribeHandler * m_handler;           
01322       PString               m_addressofRecord;   
01323       bool                  m_wasSubscribing;    
01324       bool                  m_reSubscribing;     
01325       SIP_PDU::StatusCodes  m_reason;            
01326       OpalProductInfo       m_productInfo;       
01327       void                * m_userData;          
01328     };
01329 
01330     struct NotifyCallbackInfo {
01331       NotifyCallbackInfo(
01332         SIPSubscribeHandler & handler,
01333         SIPEndPoint & ep,
01334         SIP_PDU & request,
01335         SIP_PDU & response
01336       );
01337 
01338 #if P_EXPAT
01339       bool LoadAndValidate(
01340         PXML & xml,
01341         const PXML::ValidationInfo * validator,
01342         PXML::Options options = PXML::WithNS
01343       );
01344 #endif
01345 
01346       bool SendResponse(
01347         SIP_PDU::StatusCodes status = SIP_PDU::Successful_OK,
01348         const char * extra = NULL
01349       );
01350 
01351       SIPSubscribeHandler & m_handler;
01352       SIPEndPoint         & m_endpoint;
01353       SIP_PDU             & m_request;
01354       SIP_PDU             & m_response;
01355       bool                  m_sendResponse;
01356     };
01357 
01358     struct Params : public SIPParameters
01359     {
01360       Params(PredefinedPackages pkg = NumPredefinedPackages)
01361         : m_agentAddress(m_remoteAddress)
01362         , m_eventPackage(pkg)
01363         , m_eventList(false)
01364       { }
01365 
01366       Params(const Params & param)
01367         : SIPParameters(param)
01368         , m_agentAddress(m_remoteAddress)
01369         , m_eventPackage(param.m_eventPackage)
01370         , m_eventList(param.m_eventList)
01371         , m_contentType(param.m_contentType)
01372         , m_onSubcribeStatus(param.m_onSubcribeStatus)
01373         , m_onNotify(param.m_onNotify)
01374       { }
01375 
01376       PCaselessString & m_agentAddress; // For backward compatibility
01377       EventPackage      m_eventPackage;
01378       bool              m_eventList;    // Enable RFC4662
01379       PCaselessString   m_contentType;  // May be \n separated list of types
01380 
01381       PNotifierTemplate<const SubscriptionStatus &> m_onSubcribeStatus;
01382       PNotifierTemplate<NotifyCallbackInfo &> m_onNotify;
01383     };
01384 
01385     SIPSubscribe(
01386         SIPTransactionOwner & owner,
01387         OpalTransport & transport,
01388         SIPDialogContext & dialog,
01389         const Params & params
01390     );
01391 
01392     virtual SIPTransaction * CreateDuplicate() const;
01393 };
01394 
01395 
01396 #if PTRACING
01397 ostream & operator<<(ostream & strm, const SIPSubscribe::Params & params);
01398 #endif
01399 
01400 
01401 typedef SIPSubscribe::EventPackage SIPEventPackage;
01402 
01403 
01405 
01406 class SIPHandler;
01407 
01408 class SIPEventPackageHandler : public PObject
01409 {
01410   unsigned m_expectedSequenceNumber;
01411 
01412 public:
01413   SIPEventPackageHandler() : m_expectedSequenceNumber(UINT_MAX) { }
01414 
01415   virtual ~SIPEventPackageHandler() { }
01416   virtual PCaselessString GetContentType() const = 0;
01417   virtual bool ValidateContentType(const PString & type, const SIPMIMEInfo & mime);
01418   virtual bool ValidateNotificationSequence(SIPSubscribeHandler & handler, unsigned newSequenceNumber, bool fullUpdate);
01419   virtual void OnReceivedNOTIFY(SIPSubscribe::NotifyCallbackInfo & notifyInfo) = 0;
01420   virtual PString OnSendNOTIFY(SIPHandler & /*handler*/, const PObject * /*body*/) { return PString::Empty(); }
01421 
01422   P_REMOVE_VIRTUAL(bool, OnReceivedNOTIFY(SIPHandler &, SIP_PDU &), false);
01423 };
01424 
01425 
01426 typedef PFactory<SIPEventPackageHandler, SIPEventPackage> SIPEventPackageFactory;
01427 
01428 
01430 
01431 class SIPNotify : public SIPTransaction
01432 {
01433     PCLASSINFO(SIPNotify, SIPTransaction);
01434   public:
01435     SIPNotify(
01436         SIPTransactionOwner & owner,
01437         OpalTransport & transport,
01438         SIPDialogContext & dialog,
01439         const SIPEventPackage & eventPackage,
01440         const PString & state,
01441         const PString & body
01442     );
01443 
01444     virtual SIPTransaction * CreateDuplicate() const;
01445 };
01446 
01447 
01449 
01450 class SIPPublish : public SIPTransaction
01451 {
01452     PCLASSINFO(SIPPublish, SIPTransaction);
01453   public:
01454     SIPPublish(
01455       SIPTransactionOwner & owner,
01456       OpalTransport & transport,
01457       const PString & id,
01458       const PString & sipIfMatch,
01459       const SIPSubscribe::Params & params,
01460       const PString & body
01461     );
01462 
01463     virtual SIPTransaction * CreateDuplicate() const;
01464 };
01465 
01466 
01468 
01469 class SIPRefer : public SIPTransaction
01470 {
01471   PCLASSINFO(SIPRefer, SIPTransaction);
01472   public:
01473     SIPRefer(
01474       SIPConnection & connection,
01475       const SIPURL & referTo,
01476       const SIPURL & referred_by,
01477       bool referSub
01478     );
01479 
01480     virtual SIPTransaction * CreateDuplicate() const;
01481 };
01482 
01483 
01485 
01486 /* This is not a generic NOTIFY PDU, but the minimal one
01487  * that gets sent when receiving a REFER
01488  */
01489 class SIPReferNotify : public SIPTransaction
01490 {
01491     PCLASSINFO(SIPReferNotify, SIPTransaction);
01492   public:
01493     SIPReferNotify(
01494       SIPConnection & connection,
01495       StatusCodes code
01496     );
01497 
01498     virtual SIPTransaction * CreateDuplicate() const;
01499 };
01500 
01501 
01503 
01504 /* This is a MESSAGE PDU, with a body
01505  */
01506 class SIPMessage : public SIPTransaction
01507 {
01508   PCLASSINFO(SIPMessage, SIPTransaction);
01509   public:
01510     struct Params : public SIPParameters
01511     {
01512       Params()
01513         : m_contentType("text/plain;charset=UTF-8")
01514       { 
01515         m_expire = 3600; // Try to get mesage through for an hour
01516       }
01517 
01518       PCaselessString             m_contentType;
01519       PString                     m_id;
01520       PString                     m_body;
01521       PAtomicInteger::IntegerType m_messageId;
01522     };
01523 
01524     SIPMessage(
01525       SIPTransactionOwner & owner,
01526       OpalTransport & transport,
01527       const Params & params
01528     );
01529     SIPMessage(
01530       SIPConnection & connection,
01531       const Params & params
01532     );
01533 
01534     virtual SIPTransaction * CreateDuplicate() const;
01535 
01536     const Params & GetParameters() const { return m_parameters; }
01537     const SIPURL & GetLocalAddress() const { return m_localAddress; }
01538 
01539   private:
01540     void Construct(const Params & params);
01541 
01542     Params m_parameters;
01543     SIPURL m_localAddress;
01544 };
01545 
01546 
01548 
01549 /* This is an OPTIONS request
01550  */
01551 class SIPOptions : public SIPTransaction
01552 {
01553     PCLASSINFO(SIPOptions, SIPTransaction);
01554     
01555   public:
01556     struct Params : public SIPParameters
01557     {
01558       Params()
01559         : m_acceptContent("application/sdp, application/media_control+xml, application/dtmf, application/dtmf-relay")
01560       { 
01561       }
01562 
01563       PCaselessString m_acceptContent;
01564       PCaselessString m_contentType;
01565       PString         m_body;
01566     };
01567 
01568     SIPOptions(
01569       SIPEndPoint & endpoint,
01570       const Params & params
01571     );
01572     SIPOptions(
01573       SIPConnection & conn,
01574       const Params & params
01575     );
01576 
01577     virtual SIPTransaction * CreateDuplicate() const;
01578 
01579   protected:
01580     void Construct(const Params & params);
01581 };
01582 
01583 
01585 
01586 /* This is an INFO request
01587  */
01588 class SIPInfo : public SIPTransaction
01589 {
01590     PCLASSINFO(SIPInfo, SIPTransaction);
01591     
01592   public:
01593     struct Params
01594     {
01595       Params(const PString & contentType = PString::Empty(),
01596              const PString & body = PString::Empty())
01597         : m_contentType(contentType)
01598         , m_body(body)
01599       {
01600       }
01601 
01602       PCaselessString m_contentType;
01603       PString         m_body;
01604     };
01605 
01606     SIPInfo(
01607       SIPConnection & conn,
01608       const Params & params
01609     );
01610 
01611     virtual SIPTransaction * CreateDuplicate() const;
01612 };
01613 
01614 
01616 
01617 /* This is a PING PDU, with a body
01618  */
01619 class SIPPing : public SIPTransaction
01620 {
01621   PCLASSINFO(SIPPing, SIPTransaction);
01622 
01623   public:
01624     SIPPing(
01625       SIPTransactionOwner & owner,
01626       OpalTransport & transport,
01627       const SIPURL & address
01628     );
01629 
01630     virtual SIPTransaction * CreateDuplicate() const;
01631 };
01632 
01633 
01635 
01636 /* This is a PRACK PDU
01637  */
01638 class SIPPrack : public SIPTransaction
01639 {
01640   PCLASSINFO(SIPPrack, SIPTransaction);
01641 
01642   public:
01643     SIPPrack(
01644       SIPConnection & conn,
01645       OpalTransport & transport,
01646       const PString & rack
01647     );
01648 
01649     virtual SIPTransaction * CreateDuplicate() const;
01650 };
01651 
01652 
01653 #endif // OPAL_SIP
01654 
01655 #endif // OPAL_SIP_SIPPDU_H
01656 
01657 
01658 // End of File ///////////////////////////////////////////////////////////////

Generated on 21 Jun 2013 for OPAL by  doxygen 1.4.7