OPAL  Version 3.14.3
sippdu.h
Go to the documentation of this file.
1 /*
2  * sippdu.h
3  *
4  * Session Initiation Protocol PDU support.
5  *
6  * Open Phone Abstraction Library (OPAL)
7  * Formally known as the Open H323 project.
8  *
9  * Copyright (c) 2002 Equivalence Pty. Ltd.
10  *
11  * The contents of this file are subject to the Mozilla Public License
12  * Version 1.0 (the "License"); you may not use this file except in
13  * compliance with the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS"
17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18  * the License for the specific language governing rights and limitations
19  * under the License.
20  *
21  * The Original Code is Open Phone Abstraction Library.
22  *
23  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24  *
25  * Contributor(s): ______________________________________.
26  *
27  * $Revision: 31325 $
28  * $Author: rjongbloed $
29  * $Date: 2014-01-31 12:25:13 +1100 (Fri, 31 Jan 2014) $
30  */
31 
32 #ifndef OPAL_SIP_SIPPDU_H
33 #define OPAL_SIP_SIPPDU_H
34 
35 #ifdef P_USE_PRAGMA
36 #pragma interface
37 #endif
38 
39 #include <opal_config.h>
40 
41 #if OPAL_SIP
42 
43 #include <ptclib/mime.h>
44 #include <ptclib/url.h>
45 #include <ptclib/http.h>
46 #include <ptclib/pxml.h>
47 #include <ptclib/threadpool.h>
48 #include <opal/transports.h>
49 #include <rtp/rtpconn.h>
50 
51 
53 class OpalProductInfo;
54 
55 class SIPEndPoint;
56 class SIPConnection;
57 class SIPHandler;
58 class SIP_PDU;
60 class SIPDialogContext;
61 class SIPMIMEInfo;
62 class SIPTransaction;
63 class SDPSessionDescription;
64 
65 
67 // SIPURL
68 
74 class SIPURL : public PURL
75 {
76  PCLASSINFO(SIPURL, PURL);
77  public:
78  static const WORD DefaultPort;
79  static const WORD DefaultSecurePort;
80 
81  SIPURL();
82 
84  const PURL & url
85  ) : PURL(url) { }
87  const PURL & url
88  ) { PURL::operator=(url); return *this; }
89 
92  SIPURL(
93  const char * cstr,
94  const char * defaultScheme = NULL
95  );
97  const char * cstr
98  ) { Parse(cstr); return *this; }
99 
102  SIPURL(
103  const PString & str,
104  const char * defaultScheme = NULL
105  );
107  const PString & str
108  ) { Parse(str); return *this; }
109 
119  SIPURL(
120  const PString & name,
121  const OpalTransportAddress & address,
122  WORD listenerPort = 0,
123  const char * scheme = NULL
124  );
125 
126  SIPURL(
127  const OpalTransportAddress & address,
128  WORD listenerPort = 0,
129  const char * scheme = NULL
130  );
131  SIPURL & operator=(
132  const OpalTransportAddress & address
133  );
134 
135  SIPURL(
136  const SIPMIMEInfo & mime,
137  const char * name
138  );
139 
148  virtual Comparison Compare(
149  const PObject & obj
150  ) const;
151 
155  PString AsQuotedString() const;
156 
159  PString GetDisplayName(PBoolean useDefault = true) const;
160 
161  void SetDisplayName(const PString & str)
162  {
163  m_displayName = str;
164  }
165 
167  const PStringOptions & GetFieldParameters() const { return m_fieldParameters; }
168  PStringOptions & GetFieldParameters() { return m_fieldParameters; }
169 
171  PCaselessString GetTransportProto() const;
172 
179  PINDEX dnsEntry = P_MAX_INDEX
180  ) const;
181 
184  void SetHostAddress(const OpalTransportAddress & addr);
185 
196  };
197 
203  void Sanitise(
204  UsageContext context
205  );
206 
208  static PString GenerateTag();
209 
211  void SetTag(
212  const PString & tag = PString::Empty(),
213  bool force = false
214  );
215 
217  PString GetTag() const;
218 
219  protected:
220  void ParseAsAddress(
221  const PString & name,
222  const OpalTransportAddress & address,
223  WORD listenerPort,
224  const char * scheme);
225 
226  // Override from PURL()
227  virtual PBoolean InternalParse(
228  const char * cstr,
229  const char * defaultScheme
230  ) { return ReallyInternalParse(false, cstr, defaultScheme); }
231 
232  bool ReallyInternalParse(
233  bool fromField,
234  const char * cstr,
235  const char * defaultScheme
236  );
237  WORD GetDefaultPort() const;
238 
239  PString m_displayName;
240  PStringOptions m_fieldParameters;
241 };
242 
243 
244 class SIPURLList : public std::list<SIPURL>
245 {
246  public:
247  bool FromString(
248  const PString & str,
250  bool reversed = false
251  );
252  PString ToString() const;
253  SIPURL FindCompatible(const OpalTransportAddress & addr PTRACE_PARAM(, const char * listType)) const;
254  friend ostream & operator<<(ostream & strm, const SIPURLList & urls);
255 
256  protected:
257  void InternalFromString(const PString & str, SIPURL::UsageContext context, bool reversed);
258 };
259 
260 
261 
263 // SIPMIMEInfo
264 
295 class SIPMIMEInfo : public PMIMEInfo
296 {
297  PCLASSINFO(SIPMIMEInfo, PMIMEInfo);
298  public:
299  SIPMIMEInfo(bool compactForm = false);
300 
301  virtual void PrintOn(ostream & strm) const;
302  virtual bool InternalAddMIME(const PString & fieldName, const PString & fieldValue);
303 
304  void SetCompactForm(bool form) { compactForm = form; }
305 
306  PCaselessString GetContentType(bool includeParameters = false) const;
307  void SetContentType(const PString & v);
308 
309  PCaselessString GetContentEncoding() const;
310  void SetContentEncoding(const PString & v);
311 
312  SIPURL GetFrom() const;
313  void SetFrom(const SIPURL & v);
314 
316  void SetPAssertedIdentity(const PString & v);
317 
319  void SetPPreferredIdentity(const PString & v);
320 
321  PString GetAccept() const;
322  void SetAccept(const PString & v);
323 
324  PString GetAcceptEncoding() const;
325  void SetAcceptEncoding(const PString & v);
326 
327  PString GetAcceptLanguage() const;
328  void SetAcceptLanguage(const PString & v);
329 
330  PString GetAllow() const;
331  unsigned GetAllowBitMask() const;
332  void SetAllow(const PString & v);
333 
334  PString GetCallID() const;
335  void SetCallID(const PString & v);
336 
337  SIPURL GetContact() const;
338  bool GetContacts(SIPURLList & contacts) const;
339  void SetContact(const PString & v);
340 
341  PString GetSubject() const;
342  void SetSubject(const PString & v);
343 
344  SIPURL GetTo() const;
345  void SetTo(const SIPURL & v);
346 
347  PString GetVia() const;
348  void SetVia(const PString & v);
349 
350  bool GetViaList(PStringList & v) const;
351  void SetViaList(const PStringList & v);
352 
353  PString GetFirstVia() const;
355 
356  SIPURL GetReferTo() const;
357  void SetReferTo(const PString & r);
358 
359  SIPURL GetReferredBy() const;
360  void SetReferredBy(const PString & r);
361 
362  PINDEX GetContentLength() const;
363  void SetContentLength(PINDEX v);
364  PBoolean IsContentLengthPresent() const;
365 
366  PString GetCSeq() const;
367  void SetCSeq(const PString & v);
368 
369  PString GetDate() const;
370  void SetDate(const PString & v);
371  void SetDate(const PTime & t);
372  void SetDate(void); // set to current date
373 
374  unsigned GetExpires(unsigned dflt = UINT_MAX) const;// returns default value if not found
375  void SetExpires(unsigned v);
376 
377  unsigned GetMaxForwards() const;
378  void SetMaxForwards(PINDEX v);
379 
380  unsigned GetMinExpires() const;
381  void SetMinExpires(PINDEX v);
382 
383  PString GetProxyAuthenticate() const;
384  void SetProxyAuthenticate(const PString & v);
385 
386  PString GetRoute() const;
387  bool GetRoute(SIPURLList & proxies) const;
388  void SetRoute(const PString & v);
389  void SetRoute(const SIPURLList & proxies);
390 
391  PString GetRecordRoute() const;
392  bool GetRecordRoute(SIPURLList & proxies, bool reversed) const;
393  void SetRecordRoute(const PString & v);
394  void SetRecordRoute(const SIPURLList & proxies);
395 
396  unsigned GetCSeqIndex() const { return GetCSeq().AsUnsigned(); }
397 
398  PStringSet GetRequire() const;
399  void SetRequire(const PStringSet & v);
400  void AddRequire(const PString & v);
401 
402  PStringSet GetSupported() const;
403  void SetSupported(const PStringSet & v);
404  void AddSupported(const PString & v);
405 
406  PStringSet GetUnsupported() const;
407  void SetUnsupported(const PStringSet & v);
408  void AddUnsupported(const PString & v);
409 
410  PString GetEvent() const;
411  void SetEvent(const PString & v);
412 
413  PCaselessString GetSubscriptionState(PStringToString & info) const;
414  void SetSubscriptionState(const PString & v);
415 
416  PString GetUserAgent() const;
417  void SetUserAgent(const PString & v);
418 
419  PString GetOrganization() const;
420  void SetOrganization(const PString & v);
421 
422  void GetProductInfo(OpalProductInfo & info) const;
423  void SetProductInfo(const PString & ua, const OpalProductInfo & info);
424 
425  PString GetWWWAuthenticate() const;
426  void SetWWWAuthenticate(const PString & v);
427 
428  PString GetSIPIfMatch() const;
429  void SetSIPIfMatch(const PString & v);
430 
431  PString GetSIPETag() const;
432  void SetSIPETag(const PString & v);
433 
434  void GetAlertInfo(PString & info, int & appearance) const;
435  void SetAlertInfo(const PString & info, int appearance);
436 
437  PString GetCallInfo() const;
438 
439  PString GetAllowEvents() const;
440  void SetAllowEvents(const PString & v);
441  void SetAllowEvents(const PStringSet & list);
442 
446  const PString & fieldName,
447  const PString & paramName,
448  const PString & defaultValue = PString::Empty()
449  ) const { return ExtractFieldParameter((*this)(fieldName), paramName, defaultValue); }
450 
456  const PString & fieldName,
457  const PString & paramName,
458  const PString & newValue
459  ) { SetAt(fieldName, InsertFieldParameter((*this)(fieldName), paramName, newValue)); }
460 
463  static PString ExtractFieldParameter(
464  const PString & fieldValue,
465  const PString & paramName,
466  const PString & defaultValue = PString::Empty()
467  );
468 
473  static PString InsertFieldParameter(
474  const PString & fieldValue,
475  const PString & paramName,
476  const PString & newValue
477  );
478 
479  protected:
480  PStringSet GetTokenSet(const char * field) const;
481  void AddTokenSet(const char * field, const PString & token);
482  void SetTokenSet(const char * field, const PStringSet & tokens);
483 
486 };
487 
488 
490 // SIPAuthentication
491 
492 typedef PHTTPClientAuthentication SIPAuthentication;
493 
494 class SIPAuthenticator : public PHTTPClientAuthentication::AuthObject
495 {
496  public:
497  SIPAuthenticator(SIP_PDU & pdu);
498  virtual PMIMEInfo & GetMIME();
499  virtual PString GetURI();
500  virtual PString GetEntityBody();
501  virtual PString GetMethod();
502 
503  protected:
505 };
506 
507 
508 
510 // SIP_PDU
511 
517 class SIP_PDU : public PSafeObject
518 {
519  PCLASSINFO(SIP_PDU, PSafeObject);
520  public:
521  enum Methods {
537  };
538 
539  enum StatusCodes {
549 
555 
558 
564 
597 
605 
610 
612  };
613 
614  static PString GetStatusCodeDescription(int code);
615  friend ostream & operator<<(ostream & strm, StatusCodes status);
616 
617  SIP_PDU(
618  Methods method = SIP_PDU::NumMethods,
619  const OpalTransportPtr & transport = NULL,
620  const PString & transactionID = PString::Empty()
621  );
622 
626  SIP_PDU(
627  const SIP_PDU & request,
628  StatusCodes code,
629  const SDPSessionDescription * sdp = NULL
630  );
631 
632  SIP_PDU(const SIP_PDU &);
633  SIP_PDU & operator=(const SIP_PDU &);
634  ~SIP_PDU();
635 
636  void PrintOn(
637  ostream & strm
638  ) const;
639 
640  void InitialiseHeaders(
641  const SIPURL & dest,
642  const SIPURL & to,
643  const SIPURL & from,
644  const PString & callID,
645  unsigned cseq
646  );
647  void InitialiseHeaders(
648  SIPDialogContext & dialog,
649  unsigned cseq = 0
650  );
651  void InitialiseHeaders(
652  SIPConnection & connection,
653  unsigned cseq = 0
654  );
655  void InitialiseHeaders(
656  const SIP_PDU & request
657  );
658 
663  bool SetRoute(const SIPURLList & routeSet);
664  bool SetRoute(const SIPURL & proxy);
665 
668  void SetAllow(unsigned bitmask);
669 
672  StatusCodes Read();
674  istream & strm,
675  bool truncated
676  );
677 
680  virtual bool Send();
681 
684  bool SendResponse(
685  StatusCodes code
686  );
687 
691  void Build(PString & pduStr, PINDEX & pduLen);
692 
693  const PString & GetTransactionID() const { return m_transactionID; }
694 
695  Methods GetMethod() const { return m_method; }
698  const SIPURL & GetURI() const { return m_uri; }
699  void SetURI(const SIPURL & newuri) { m_uri = newuri; }
700  unsigned GetVersionMajor() const { return m_versionMajor; }
701  unsigned GetVersionMinor() const { return m_versionMinor; }
702  void SetCSeq(unsigned cseq);
703  const PString & GetEntityBody() const { return m_entityBody; }
704  void SetEntityBody(const PString & body) { m_entityBody = body; }
705  void SetEntityBody();
706  const PString & GetInfo() const { return m_info; }
707  void SetInfo(const PString & info) { m_info = info; }
708  const SIPMIMEInfo & GetMIME() const { return m_mime; }
709  SIPMIMEInfo & GetMIME() { return m_mime; }
710  SDPSessionDescription * GetSDP() { return m_SDP; }
711  void SetSDP(SDPSessionDescription * sdp);
712  bool DecodeSDP(SIPEndPoint & endpoint, const OpalMediaFormatList & masterList);
713  bool IsContentSDP(bool emptyOK = false) const;
714 
715  const PString & GetExternalTransportAddress() const { return m_externalTransportAddress; }
717  void SetTransport(const OpalTransportPtr & transport);
718 
719  protected:
720  void CalculateVia();
721  StatusCodes InternalSend(bool canDoTCP);
722 
723  Methods m_method; // Request type, ==NumMethods for Response
725  SIPURL m_uri; // display name & URI, no tag
726  unsigned m_versionMajor;
727  unsigned m_versionMinor;
728  PString m_info;
730  PString m_entityBody;
732 
733  SDPSessionDescription * m_SDP;
734 
738 };
739 
740 
741 PQUEUE(SIP_PDU_Queue, SIP_PDU);
742 
743 
744 #if PTRACING
745 ostream & operator<<(ostream & strm, SIP_PDU::Methods method);
746 #endif
747 
748 
750 // SIPDialogContext
751 
755 {
756  public:
758  SIPDialogContext(const SIPMIMEInfo & mime);
759 
760  PString AsString() const;
761  bool FromString(
762  const PString & str
763  );
764 
765  const PString & GetCallID() const { return m_callId; }
766  void SetCallID(const PString & id) { m_callId = id; }
767 
768  const SIPURL & GetRequestURI() const { return m_requestURI; }
769  void SetRequestURI(const SIPURL & url);
770 
771  const PString & GetLocalTag() const { return m_localTag; }
772  void SetLocalTag(const PString & tag) { m_localTag = tag; }
773 
774  const SIPURL & GetLocalURI() const { return m_localURI; }
775  void SetLocalURI(const SIPURL & url);
776 
777  const PString & GetRemoteTag() const { return m_remoteTag; }
778  void SetRemoteTag(const PString & tag) { m_remoteTag = tag; }
779 
780  const SIPURL & GetRemoteURI() const { return m_remoteURI; }
781  void SetRemoteURI(const SIPURL & url);
782 
783  const SIPURLList & GetRouteSet() const { return m_routeSet; }
784  void SetRouteSet(const PString & str) { m_routeSet.FromString(str); }
785 
786  const SIPURL & GetProxy() const { return m_proxy; }
787  void SetProxy(const SIPURL & proxy, bool addToRouteSet);
788 
789  void Update(const SIP_PDU & response);
790 
791  unsigned GetNextCSeq();
792  void IncrementCSeq(unsigned inc) { m_lastSentCSeq += inc; }
793 
794  bool IsDuplicateCSeq(unsigned sequenceNumber);
795 
796  bool IsEstablished() const
797  {
798  return !m_callId.IsEmpty() &&
799  !m_requestURI.IsEmpty() &&
800  !m_localTag.IsEmpty() &&
801  !m_remoteTag.IsEmpty();
802  }
803 
804  OpalTransportAddress GetRemoteTransportAddress(PINDEX dnsEntry) const;
805  const PString & GetInterface() const { return m_interface; }
806  void SetInterface(const PString & newInterface) { m_interface = newInterface; }
807 
808  void SetForking(bool f) { m_forking = f; }
809 
810  protected:
811  PString m_callId;
814  PString m_localTag;
816  PString m_remoteTag;
818  unsigned m_lastSentCSeq;
821  bool m_forking;
823  PString m_interface;
824 };
825 
826 
828 
830 {
832  const PString & aor = PString::Empty(),
833  const PString & remote = PString::Empty()
834  );
835 
836  bool Normalise(
837  const PString & defaultUser,
838  const PTimeInterval & defaultExpire
839  );
840 
841  PCaselessString m_remoteAddress;
842  PCaselessString m_localAddress;
843  PCaselessString m_proxyAddress;
844  PCaselessString m_addressOfRecord;
845  PCaselessString m_contactAddress;
846  PCaselessString m_interface;
848  PString m_authID;
849  PString m_password;
850  PString m_realm;
851  unsigned m_expire;
852  unsigned m_restoreTime;
853  PTimeInterval m_minRetryTime;
854  PTimeInterval m_maxRetryTime;
855  void * m_userData;
856 };
857 
858 
859 #if PTRACING
860 ostream & operator<<(ostream & strm, const SIPParameters & params);
861 #endif
862 
863 
865 // Thread pooling stuff
866 //
867 // Timer call back mechanism using PNOTIFIER is too prone to deadlocks, we
868 // want to use the existing thread pool for handling incoming PDUs.
869 
870 class SIPWorkItem : public PObject
871 {
872  PCLASSINFO(SIPWorkItem, PObject);
873  public:
874  SIPWorkItem(SIPEndPoint & ep, const PString & token);
875 
876  virtual void Work() = 0;
877 
878  bool GetTarget(PSafePtr<SIPTransaction> & transaction);
879  bool GetTarget(PSafePtr<SIPConnection> & connection);
880  bool GetTarget(PSafePtr<SIPHandler> & handler);
881 
882  protected:
884  PString m_token;
885 };
886 
887 
888 class SIPThreadPool : public PQueuedThreadPool<SIPWorkItem>
889 {
890  typedef PQueuedThreadPool<SIPWorkItem> BaseClass;
891  PCLASSINFO(SIPThreadPool, BaseClass);
892  public:
893  SIPThreadPool(unsigned maxWorkers, const char * threadName)
894  : BaseClass(maxWorkers, 0, threadName, PThread::HighPriority)
895  {
896  }
897 };
898 
899 
900 template <class Target_T>
902 {
903  PCLASSINFO(SIPTimeoutWorkItem, SIPWorkItem);
904  public:
905  typedef void (Target_T::* Callback)();
906 
907  SIPTimeoutWorkItem(SIPEndPoint & ep, const PString & token, Callback callback)
908  : SIPWorkItem(ep, token)
909  , m_callback(callback)
910  {
911  }
912 
913  virtual void Work()
914  {
915  PSafePtr<Target_T> target;
916  if (GetTarget(target)) {
917  PTRACE_CONTEXT_ID_PUSH_THREAD(target);
918  (target->*m_callback)();
919  PTRACE(4, "SIP\tHandled timeout");
920  }
921  }
922 
923  protected:
925 };
926 
927 
928 template <class Target_T>
929 class SIPPoolTimer : public PPoolTimerArg3<SIPTimeoutWorkItem<Target_T>,
930  SIPEndPoint &,
931  PString,
932  void (Target_T::*)(),
933  SIPWorkItem>
934 {
936  typedef PPoolTimerArg3<Work_T, SIPEndPoint &, PString, void (Target_T::*)(), SIPWorkItem> BaseClass;
937  PCLASSINFO(SIPPoolTimer, BaseClass);
938  private:
939  PString m_token;
940  public:
941  SIPPoolTimer(SIPThreadPool & pool, SIPEndPoint & ep, const PString & token, void (Target_T::* callback)())
942  : BaseClass(pool, ep, token, callback)
943  , m_token(token)
944  {
945  }
946 
947  virtual const char * GetGroup(const Work_T &) const { return m_token; }
948 
950 };
951 
952 
954 // SIPTransaction
955 
957 {
958  public:
960  PSafeObject & object,
961  SIPEndPoint & endpoint
962  );
963  virtual ~SIPTransactionOwner();
964 
965  virtual PString GetAuthID() const = 0;
966  virtual PString GetPassword() const { return PString::Empty(); }
967  virtual unsigned GetAllowedMethods() const;
968 
969  virtual void OnStartTransaction(SIPTransaction & /*transaction*/) { }
970  virtual void OnReceivedResponse(SIPTransaction & transaction, SIP_PDU & response);
971  virtual void OnTransactionFailed(SIPTransaction & transaction);
972 
973  void FinaliseForking(SIPTransaction & transaction, SIP_PDU & response);
975  void AbortPendingTransactions(bool all = true);
976 
978  const OpalTransport::WriteConnectCallback & function
979  );
980 
981  SIP_PDU::StatusCodes SwitchTransportProto(const char * proto, SIP_PDU * pdu);
982 
984 
985  SIPEndPoint & GetEndPoint() const { return m_endpoint; }
987  const SIPURL & GetRequestURI() const { return m_dialog.GetRequestURI(); }
988  const SIPURL & GetRemoteURI() const { return m_dialog.GetRemoteURI(); }
989  const SIPURL & GetProxy() const { return m_dialog.GetProxy(); }
990  const PString & GetInterface() const { return m_dialog.GetInterface(); }
991  PINDEX GetDNSEntry() const { return m_dnsEntry; }
992  SIPAuthentication * GetAuthenticator() const { return m_authentication; }
994  const SIPDialogContext & GetDialog() const { return m_dialog; }
995 
996  protected:
997  PSafeObject & m_object;
999  SIPDialogContext m_dialog; // Not all derived classes use this as a dialog, but many fields useful
1000  PINDEX m_dnsEntry;
1001  SIPAuthentication * m_authentication;
1003 
1004  PSafeList<SIPTransaction> m_transactions;
1005  PMutex m_forkMutex;
1006 
1007  friend class SIPTransaction;
1008 };
1009 
1010 
1012 {
1013  PCLASSINFO(SIPTransactionBase, SIP_PDU);
1014  protected:
1016  Methods method,
1017  const OpalTransportPtr & transport,
1018  const PString & transactionID
1019  ) : SIP_PDU(method, transport, transactionID) { }
1020 
1021  public:
1023  const PString & transactionID
1024  ) { m_transactionID = transactionID; }
1025 
1026  Comparison Compare(
1027  const PObject & other
1028  ) const;
1029 
1030  virtual bool IsTerminated() const { return true; }
1031 };
1032 
1033 
1045 {
1046  PCLASSINFO(SIPTransaction, SIPTransactionBase);
1047  protected:
1049  Methods method,
1050  SIPTransactionOwner * owner,
1051  OpalTransport * transport,
1052  bool deleteOwner = false,
1053  const PString & transactionID = PString::Empty()
1054  );
1055  public:
1056  ~SIPTransaction();
1057 
1058  /* Under some circumstances a new transaction with all the same parameters
1059  but different ID needs to be created, e.g. when get authentication error. */
1060  virtual SIPTransaction * CreateDuplicate() const = 0;
1061 
1062  bool Start();
1063  bool IsTrying() const { return m_state == Trying; }
1064  bool IsProceeding() const { return m_state == Proceeding; }
1065  bool IsInProgress() const { return m_state == Trying || m_state == Proceeding; }
1066  bool IsFailed() const { return m_state > Terminated_Success; }
1067  bool IsCompleted() const { return m_state >= Completed; }
1068  bool IsCanceled() const { return m_state == Cancelling || m_state == Terminated_Cancelled || m_state == Terminated_Aborted; }
1069  bool IsTerminated() const { return m_state >= Terminated_Success; }
1070 
1071  void WaitForCompletion();
1072  PBoolean Cancel();
1073  void Abort();
1074 
1075  virtual PBoolean OnReceivedResponse(SIP_PDU & response);
1076  virtual PBoolean OnCompleted(SIP_PDU & response);
1077 
1078  SIPEndPoint & GetEndPoint() const { return m_owner->GetEndPoint(); }
1079  SIPConnection * GetConnection() const;
1080  PString GetInterface() const { return m_localInterface; }
1081 
1082  static PString GenerateCallID();
1083 
1084  protected:
1085  bool ResendCANCEL();
1086  void SetParameters(const SIPParameters & params);
1087 
1089 
1090  void OnRetry();
1091  void OnTimeout();
1092 
1093  P_DECLARE_TRACED_ENUM(States,
1094  NotStarted,
1095  Trying,
1096  Proceeding,
1097  Cancelling,
1098  Completed,
1099  Terminated_Success,
1100  Terminated_Timeout,
1101  Terminated_RetriesExceeded,
1102  Terminated_TransportError,
1103  Terminated_Cancelled,
1104  Terminated_Aborted
1105  );
1106  virtual void SetTerminated(States newState);
1107 
1110 
1111  PTimeInterval m_retryTimeoutMin;
1112  PTimeInterval m_retryTimeoutMax;
1113 
1114  States m_state;
1115  unsigned m_retry;
1118  PSyncPoint m_completed;
1121 
1122  friend class SIPConnection;
1123 };
1124 
1125 
1126 #define OPAL_PROXY_PARAM "OPAL-proxy"
1127 #define OPAL_LOCAL_ID_PARAM "OPAL-local-id"
1128 #define OPAL_INTERFACE_PARAM "OPAL-interface"
1129 
1130 
1132 // SIPResponse
1133 
1137 {
1138  PCLASSINFO(SIPResponse, SIPTransaction);
1139  public:
1140  SIPResponse(
1141  SIPEndPoint & endpoint,
1142  const SIP_PDU & command,
1143  StatusCodes code
1144  );
1145 
1146  virtual SIPTransaction * CreateDuplicate() const;
1147 
1148  virtual bool Send();
1149 };
1150 
1151 
1153 // SIPInvite
1154 
1161 {
1162  PCLASSINFO(SIPInvite, SIPTransaction);
1163  public:
1164  SIPInvite(
1165  SIPConnection & connection,
1166  OpalTransport * transport = NULL
1167  );
1168 
1169  virtual SIPTransaction * CreateDuplicate() const;
1170 
1171  virtual PBoolean OnReceivedResponse(SIP_PDU & response);
1172 
1174 };
1175 
1176 
1178 
1179 /* This is the ACK request sent when receiving a response to an outgoing
1180  * INVITE.
1181  */
1182 class SIPAck : public SIP_PDU
1183 {
1184  PCLASSINFO(SIPAck, SIP_PDU);
1185  public:
1186  SIPAck(
1187  const SIPTransaction & invite,
1188  const SIP_PDU & response
1189  );
1190 
1191  virtual SIPTransaction * CreateDuplicate() const;
1192 };
1193 
1194 
1196 
1197 /* This is a BYE request
1198  */
1199 class SIPBye : public SIPTransaction
1200 {
1201  PCLASSINFO(SIPBye, SIPTransaction);
1202  public:
1203  SIPBye(
1204  SIPEndPoint & endpoint,
1205  SIPDialogContext & dialog
1206  );
1207  SIPBye(
1208  SIPConnection & conn
1209  );
1210 
1211  virtual SIPTransaction * CreateDuplicate() const;
1212 };
1213 
1214 
1216 
1218 {
1219  PCLASSINFO(SIPRegister, SIPTransaction);
1220  public:
1221  P_DECLARE_TRACED_ENUM(CompatibilityModes,
1222  e_FullyCompliant,
1225  e_CannotRegisterMultipleContacts,
1229  e_CannotRegisterPrivateContacts,
1233  e_HasApplicationLayerGateway,
1237  e_RFC5626
1240  );
1241 
1243  struct Params : public SIPParameters {
1246  , m_compatibility(SIPRegister::e_FullyCompliant)
1247  , m_instanceId(NULL)
1248  { }
1249 
1250  Params(const Params & param)
1251  : SIPParameters(param)
1254  , m_instanceId(param.m_instanceId)
1255  { }
1256 
1257  PCaselessString & m_registrarAddress; // For backward compatibility
1258  CompatibilityModes m_compatibility;
1259  PGloballyUniqueID m_instanceId;
1260  };
1261 
1262  SIPRegister(
1263  SIPTransactionOwner & owner,
1264  OpalTransport & transport,
1265  const PString & callId,
1266  unsigned cseq,
1267  const Params & params
1268  );
1269 
1270  virtual SIPTransaction * CreateDuplicate() const;
1271 };
1272 
1273 
1274 #if PTRACING
1275 ostream & operator<<(ostream & strm, SIPRegister::CompatibilityModes mode);
1276 ostream & operator<<(ostream & strm, const SIPRegister::Params & params);
1277 #endif
1278 
1279 
1281 
1283 {
1284  PCLASSINFO(SIPSubscribe, SIPTransaction);
1285  public:
1294 
1296 
1297  Watcher = 0x8000,
1298 
1302 
1304  };
1306 
1307  class EventPackage : public PCaselessString
1308  {
1309  PCLASSINFO(EventPackage, PCaselessString);
1310  public:
1312  explicit EventPackage(const PString & str) : PCaselessString(str) { }
1313  explicit EventPackage(const char * str) : PCaselessString(str) { }
1314 
1316  EventPackage & operator=(const PString & str) { PCaselessString::operator=(str); return *this; }
1317  EventPackage & operator=(const char * str) { PCaselessString::operator=(str); return *this; }
1318 
1319  bool operator==(PredefinedPackages pkg) const { return Compare(EventPackage(pkg)) == EqualTo; }
1320  bool operator==(const PString & str) const { return Compare(str) == EqualTo; }
1321  bool operator==(const char * cstr) const { return InternalCompare(0, P_MAX_INDEX, cstr) == EqualTo; }
1322  virtual Comparison InternalCompare(PINDEX offset, PINDEX length, const char * cstr) const;
1323 
1324  bool IsWatcher() const;
1325  };
1326 
1335  void * m_userData;
1336  friend ostream & operator<<(ostream & strm, const SubscriptionStatus & status);
1337  };
1338 
1341  SIPSubscribeHandler & handler,
1342  SIPEndPoint & ep,
1343  SIP_PDU & request,
1344  SIP_PDU & response
1345  );
1346 
1347 #if P_EXPAT
1348  bool LoadAndValidate(
1349  PXML & xml,
1350  const PXML::ValidationInfo * validator,
1351  PXML::Options options = PXML::WithNS
1352  );
1353 #endif
1354 
1355  bool SendResponse(
1357  const char * extra = NULL
1358  );
1359 
1365  };
1366 
1367  struct Params : public SIPParameters
1368  {
1371  , m_eventPackage(pkg)
1372  , m_eventList(false)
1373  { }
1374 
1375  Params(const Params & param)
1376  : SIPParameters(param)
1379  , m_eventList(param.m_eventList)
1380  , m_contentType(param.m_contentType)
1382  , m_onNotify(param.m_onNotify)
1383  { }
1384 
1385  PCaselessString & m_agentAddress; // For backward compatibility
1387  bool m_eventList; // Enable RFC4662
1388  PCaselessString m_contentType; // May be \n separated list of types
1389 
1390  PNotifierTemplate<const SubscriptionStatus &> m_onSubcribeStatus;
1391  PNotifierTemplate<NotifyCallbackInfo &> m_onNotify;
1392  };
1393 
1394  SIPSubscribe(
1395  SIPTransactionOwner & owner,
1396  OpalTransport & transport,
1397  SIPDialogContext & dialog,
1398  const Params & params
1399  );
1400 
1401  virtual SIPTransaction * CreateDuplicate() const;
1402 };
1403 
1404 
1405 #if PTRACING
1406 ostream & operator<<(ostream & strm, const SIPSubscribe::Params & params);
1407 #endif
1408 
1409 
1411 
1412 
1414 
1415 class SIPHandler;
1416 
1417 class SIPEventPackageHandler : public PObject
1418 {
1419  unsigned m_expectedSequenceNumber;
1420 
1421 public:
1422  SIPEventPackageHandler() : m_expectedSequenceNumber(UINT_MAX) { }
1423 
1425  virtual PCaselessString GetContentType() const = 0;
1426  virtual bool ValidateContentType(const PString & type, const SIPMIMEInfo & mime);
1427  virtual bool ValidateNotificationSequence(SIPSubscribeHandler & handler, unsigned newSequenceNumber, bool fullUpdate);
1428  virtual void OnReceivedNOTIFY(SIPSubscribe::NotifyCallbackInfo & notifyInfo) = 0;
1429  virtual PString OnSendNOTIFY(SIPHandler & /*handler*/, const PObject * /*body*/) { return PString::Empty(); }
1430 
1432 };
1433 
1434 
1435 typedef PFactory<SIPEventPackageHandler, SIPEventPackage> SIPEventPackageFactory;
1436 
1437 
1439 
1441 {
1442  PCLASSINFO(SIPNotify, SIPTransaction);
1443  public:
1444  SIPNotify(
1445  SIPTransactionOwner & owner,
1446  OpalTransport & transport,
1447  SIPDialogContext & dialog,
1448  const SIPEventPackage & eventPackage,
1449  const PString & state,
1450  const PString & body
1451  );
1452 
1453  virtual SIPTransaction * CreateDuplicate() const;
1454 };
1455 
1456 
1458 
1460 {
1461  PCLASSINFO(SIPPublish, SIPTransaction);
1462  public:
1463  SIPPublish(
1464  SIPTransactionOwner & owner,
1465  OpalTransport & transport,
1466  const PString & id,
1467  const PString & sipIfMatch,
1468  const SIPSubscribe::Params & params,
1469  const PString & body
1470  );
1471 
1472  virtual SIPTransaction * CreateDuplicate() const;
1473 };
1474 
1475 
1477 
1478 class SIPRefer : public SIPTransaction
1479 {
1480  PCLASSINFO(SIPRefer, SIPTransaction);
1481  public:
1482  SIPRefer(
1483  SIPConnection & connection,
1484  const SIPURL & referTo,
1485  const SIPURL & referred_by,
1486  bool referSub
1487  );
1488 
1489  virtual SIPTransaction * CreateDuplicate() const;
1490 };
1491 
1492 
1494 
1495 /* This is not a generic NOTIFY PDU, but the minimal one
1496  * that gets sent when receiving a REFER
1497  */
1499 {
1500  PCLASSINFO(SIPReferNotify, SIPTransaction);
1501  public:
1503  SIPConnection & connection,
1504  StatusCodes code
1505  );
1506 
1507  virtual SIPTransaction * CreateDuplicate() const;
1508 };
1509 
1510 
1512 
1513 /* This is a MESSAGE PDU, with a body
1514  */
1516 {
1517  PCLASSINFO(SIPMessage, SIPTransaction);
1518  public:
1519  struct Params : public SIPParameters
1520  {
1522  : m_contentType("text/plain;charset=UTF-8")
1523  {
1524  m_expire = 3600; // Try to get mesage through for an hour
1525  }
1526 
1527  PCaselessString m_contentType;
1528  PString m_id;
1529  PString m_body;
1530  PAtomicInteger::IntegerType m_messageId;
1531  };
1532 
1533  SIPMessage(
1534  SIPTransactionOwner & owner,
1535  OpalTransport & transport,
1536  const Params & params
1537  );
1538  SIPMessage(
1539  SIPConnection & connection,
1540  const Params & params
1541  );
1542 
1543  virtual SIPTransaction * CreateDuplicate() const;
1544 
1545  const Params & GetParameters() const { return m_parameters; }
1546  const SIPURL & GetLocalAddress() const { return m_localAddress; }
1547 
1548  private:
1549  void Construct(const Params & params);
1550 
1551  Params m_parameters;
1552  SIPURL m_localAddress;
1553 };
1554 
1555 
1557 
1558 /* This is an OPTIONS request
1559  */
1561 {
1562  PCLASSINFO(SIPOptions, SIPTransaction);
1563 
1564  public:
1565  struct Params : public SIPParameters
1566  {
1568  : m_acceptContent("application/sdp, application/media_control+xml, application/dtmf, application/dtmf-relay")
1569  {
1570  }
1571 
1572  PCaselessString m_acceptContent;
1573  PCaselessString m_contentType;
1574  PString m_body;
1575  };
1576 
1577  SIPOptions(
1578  SIPEndPoint & endpoint,
1579  const Params & params
1580  );
1581  SIPOptions(
1582  SIPConnection & conn,
1583  const Params & params
1584  );
1585 
1586  virtual SIPTransaction * CreateDuplicate() const;
1587 
1588  protected:
1589  void Construct(const Params & params);
1590 };
1591 
1592 
1594 
1595 /* This is an INFO request
1596  */
1597 class SIPInfo : public SIPTransaction
1598 {
1599  PCLASSINFO(SIPInfo, SIPTransaction);
1600 
1601  public:
1602  struct Params
1603  {
1604  Params(const PString & contentType = PString::Empty(),
1605  const PString & body = PString::Empty())
1606  : m_contentType(contentType)
1607  , m_body(body)
1608  {
1609  }
1610 
1611  PCaselessString m_contentType;
1612  PString m_body;
1613  };
1614 
1615  SIPInfo(
1616  SIPConnection & conn,
1617  const Params & params
1618  );
1619 
1620  virtual SIPTransaction * CreateDuplicate() const;
1621 };
1622 
1623 
1625 
1626 /* This is a PING PDU, with a body
1627  */
1628 class SIPPing : public SIPTransaction
1629 {
1630  PCLASSINFO(SIPPing, SIPTransaction);
1631 
1632  public:
1633  SIPPing(
1634  SIPTransactionOwner & owner,
1635  OpalTransport & transport,
1636  const SIPURL & address
1637  );
1638 
1639  virtual SIPTransaction * CreateDuplicate() const;
1640 };
1641 
1642 
1644 
1645 /* This is a PRACK PDU
1646  */
1647 class SIPPrack : public SIPTransaction
1648 {
1649  PCLASSINFO(SIPPrack, SIPTransaction);
1650 
1651  public:
1652  SIPPrack(
1653  SIPConnection & conn,
1654  OpalTransport & transport,
1655  const PString & rack
1656  );
1657 
1658  virtual SIPTransaction * CreateDuplicate() const;
1659 };
1660 
1661 
1662 #endif // OPAL_SIP
1663 
1664 #endif // OPAL_SIP_SIPPDU_H
1665 
1666 
1667 // End of File ///////////////////////////////////////////////////////////////