# 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 ///////////////////////////////////////////////////////////////