OPAL  Version 3.12.9
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: 31196 $
28  * $Author: rjongbloed $
29  * $Date: 2014-01-16 09:40:45 +1100 (Thu, 16 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/buildopts.h>
40 
41 #if OPAL_SIP
42 
43 #include <ptclib/mime.h>
44 #include <ptclib/url.h>
45 #include <ptclib/http.h>
46 #include <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;
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; }
711  void SetSDP(SDPSessionDescription * sdp);
712  bool DecodeSDP(SIPEndPoint & endpoint, const OpalMediaFormatList & masterList);
713 
714  const PString & GetExternalTransportAddress() const { return m_externalTransportAddress; }
716  void SetTransport(const OpalTransportPtr & transport);
717 
718  protected:
719  void CalculateVia();
720  StatusCodes InternalSend(bool canDoTCP);
721 
722  Methods m_method; // Request type, ==NumMethods for Response
724  SIPURL m_uri; // display name & URI, no tag
725  unsigned m_versionMajor;
726  unsigned m_versionMinor;
727  PString m_info;
729  PString m_entityBody;
731 
733 
737 };
738 
739 
740 PQUEUE(SIP_PDU_Queue, SIP_PDU);
741 
742 
743 #if PTRACING
744 ostream & operator<<(ostream & strm, SIP_PDU::Methods method);
745 #endif
746 
747 
749 // SIPDialogContext
750 
754 {
755  public:
757  SIPDialogContext(const SIPMIMEInfo & mime);
758 
759  PString AsString() const;
760  bool FromString(
761  const PString & str
762  );
763 
764  const PString & GetCallID() const { return m_callId; }
765  void SetCallID(const PString & id) { m_callId = id; }
766 
767  const SIPURL & GetRequestURI() const { return m_requestURI; }
768  void SetRequestURI(const SIPURL & url);
769 
770  const PString & GetLocalTag() const { return m_localTag; }
771  void SetLocalTag(const PString & tag) { m_localTag = tag; }
772 
773  const SIPURL & GetLocalURI() const { return m_localURI; }
774  void SetLocalURI(const SIPURL & url);
775 
776  const PString & GetRemoteTag() const { return m_remoteTag; }
777  void SetRemoteTag(const PString & tag) { m_remoteTag = tag; }
778 
779  const SIPURL & GetRemoteURI() const { return m_remoteURI; }
780  void SetRemoteURI(const SIPURL & url);
781 
782  const SIPURLList & GetRouteSet() const { return m_routeSet; }
783  void SetRouteSet(const PString & str) { m_routeSet.FromString(str); }
784 
785  const SIPURL & GetProxy() const { return m_proxy; }
786  void SetProxy(const SIPURL & proxy, bool addToRouteSet);
787 
788  void Update(const SIP_PDU & response);
789 
790  unsigned GetNextCSeq();
791  void IncrementCSeq(unsigned inc) { m_lastSentCSeq += inc; }
792 
793  bool IsDuplicateCSeq(unsigned sequenceNumber);
794 
795  bool IsEstablished() const
796  {
797  return !m_callId.IsEmpty() &&
798  !m_requestURI.IsEmpty() &&
799  !m_localTag.IsEmpty() &&
800  !m_remoteTag.IsEmpty();
801  }
802 
803  OpalTransportAddress GetRemoteTransportAddress(PINDEX dnsEntry) const;
804  const PString & GetInterface() const { return m_interface; }
805  void SetInterface(const PString & newInterface) { m_interface = newInterface; }
806 
807  void SetForking(bool f) { m_forking = f; }
808 
809  protected:
810  PString m_callId;
813  PString m_localTag;
815  PString m_remoteTag;
817  unsigned m_lastSentCSeq;
820  bool m_forking;
822  PString m_interface;
823 };
824 
825 
827 
829 {
831  const PString & aor = PString::Empty(),
832  const PString & remote = PString::Empty()
833  );
834 
835  bool Normalise(
836  const PString & defaultUser,
837  const PTimeInterval & defaultExpire
838  );
839 
840  PCaselessString m_remoteAddress;
841  PCaselessString m_localAddress;
842  PCaselessString m_proxyAddress;
843  PCaselessString m_addressOfRecord;
844  PCaselessString m_contactAddress;
845  PCaselessString m_interface;
847  PString m_authID;
848  PString m_password;
849  PString m_realm;
850  unsigned m_expire;
851  unsigned m_restoreTime;
852  PTimeInterval m_minRetryTime;
853  PTimeInterval m_maxRetryTime;
854  void * m_userData;
855 };
856 
857 
858 #if PTRACING
859 ostream & operator<<(ostream & strm, const SIPParameters & params);
860 #endif
861 
862 
864 // Thread pooling stuff
865 //
866 // Timer call back mechanism using PNOTIFIER is too prone to deadlocks, we
867 // want to use the existing thread pool for handling incoming PDUs.
868 
869 class SIPWorkItem : public PObject
870 {
871  PCLASSINFO(SIPWorkItem, PObject);
872  public:
873  SIPWorkItem(SIPEndPoint & ep, const PString & token);
874 
875  virtual void Work() = 0;
876 
877  bool GetTarget(PSafePtr<SIPTransaction> & transaction);
878  bool GetTarget(PSafePtr<SIPConnection> & connection);
879  bool GetTarget(PSafePtr<SIPHandler> & handler);
880 
881  protected:
883  PString m_token;
884 };
885 
886 
887 class SIPThreadPool : public PQueuedThreadPool<SIPWorkItem>
888 {
889  typedef PQueuedThreadPool<SIPWorkItem> BaseClass;
890  PCLASSINFO(SIPThreadPool, BaseClass);
891  public:
892  SIPThreadPool(unsigned maxWorkers, const char * threadName)
893  : BaseClass(maxWorkers, 0, threadName, PThread::HighPriority)
894  {
895  }
896 };
897 
898 
899 template <class Target_T>
901 {
902  PCLASSINFO(SIPTimeoutWorkItem, SIPWorkItem);
903  public:
904  typedef void (Target_T::* Callback)();
905 
906  SIPTimeoutWorkItem(SIPEndPoint & ep, const PString & token, Callback callback)
907  : SIPWorkItem(ep, token)
908  , m_callback(callback)
909  {
910  }
911 
912  virtual void Work()
913  {
914  PSafePtr<Target_T> target;
915  if (GetTarget(target)) {
916  PTRACE_CONTEXT_ID_PUSH_THREAD(target);
917  (target->*m_callback)();
918  PTRACE(4, "SIP\tHandled timeout");
919  }
920  }
921 
922  protected:
924 };
925 
926 
927 template <class Target_T>
928 class SIPPoolTimer : public PPoolTimerArg3<SIPTimeoutWorkItem<Target_T>,
929  SIPEndPoint &,
930  PString,
931  void (Target_T::*)(),
932  SIPWorkItem>
933 {
935  typedef PPoolTimerArg3<Work_T, SIPEndPoint &, PString, void (Target_T::*)(), SIPWorkItem> BaseClass;
936  PCLASSINFO(SIPPoolTimer, BaseClass);
937  private:
938  PString m_token;
939  public:
940  SIPPoolTimer(SIPThreadPool & pool, SIPEndPoint & ep, const PString & token, void (Target_T::* callback)())
941  : BaseClass(pool, ep, token, callback)
942  , m_token(token)
943  {
944  }
945 
946  virtual const char * GetGroup(const Work_T &) const { return m_token; }
947 
949 };
950 
951 
953 // SIPTransaction
954 
956 {
957  public:
959  PSafeObject & object,
960  SIPEndPoint & endpoint
961  );
962  virtual ~SIPTransactionOwner();
963 
964  virtual PString GetAuthID() const = 0;
965  virtual PString GetPassword() const { return PString::Empty(); }
966  virtual unsigned GetAllowedMethods() const;
967 
968  virtual void OnStartTransaction(SIPTransaction & /*transaction*/) { }
969  virtual void OnReceivedResponse(SIPTransaction & transaction, SIP_PDU & response);
970  virtual void OnTransactionFailed(SIPTransaction & transaction);
971 
972  void FinaliseForking(SIPTransaction & transaction, SIP_PDU & response);
974  void AbortPendingTransactions(bool all = true);
975 
977  const OpalTransport::WriteConnectCallback & function
978  );
979 
980  SIP_PDU::StatusCodes SwitchTransportProto(const char * proto, SIP_PDU * pdu);
981 
983 
984  SIPEndPoint & GetEndPoint() const { return m_endpoint; }
986  const SIPURL & GetRequestURI() const { return m_dialog.GetRequestURI(); }
987  const SIPURL & GetRemoteURI() const { return m_dialog.GetRemoteURI(); }
988  const SIPURL & GetProxy() const { return m_dialog.GetProxy(); }
989  const PString & GetInterface() const { return m_dialog.GetInterface(); }
990  PINDEX GetDNSEntry() const { return m_dnsEntry; }
991  SIPAuthentication * GetAuthenticator() const { return m_authentication; }
993  const SIPDialogContext & GetDialog() const { return m_dialog; }
994 
995  protected:
996  PSafeObject & m_object;
998  SIPDialogContext m_dialog; // Not all derived classes use this as a dialog, but many fields useful
999  PINDEX m_dnsEntry;
1000  SIPAuthentication * m_authentication;
1002 
1003  PSafeList<SIPTransaction> m_transactions;
1004  PMutex m_forkMutex;
1005 
1006  friend class SIPTransaction;
1007 };
1008 
1009 
1011 {
1012  PCLASSINFO(SIPTransactionBase, SIP_PDU);
1013  protected:
1015  Methods method,
1016  const OpalTransportPtr & transport,
1017  const PString & transactionID
1018  ) : SIP_PDU(method, transport, transactionID) { }
1019 
1020  public:
1022  const PString & transactionID
1023  ) { m_transactionID = transactionID; }
1024 
1025  Comparison Compare(
1026  const PObject & other
1027  ) const;
1028 
1029  virtual bool IsTerminated() const { return true; }
1030 };
1031 
1032 
1044 {
1045  PCLASSINFO(SIPTransaction, SIPTransactionBase);
1046  protected:
1048  Methods method,
1049  SIPTransactionOwner * owner,
1050  OpalTransport * transport,
1051  bool deleteOwner = false,
1052  const PString & transactionID = PString::Empty()
1053  );
1054  public:
1055  ~SIPTransaction();
1056 
1057  /* Under some circumstances a new transaction with all the same parameters
1058  but different ID needs to be created, e.g. when get authentication error. */
1059  virtual SIPTransaction * CreateDuplicate() const = 0;
1060 
1061  bool Start();
1062  bool IsTrying() const { return m_state == Trying; }
1063  bool IsProceeding() const { return m_state == Proceeding; }
1064  bool IsInProgress() const { return m_state == Trying || m_state == Proceeding; }
1065  bool IsFailed() const { return m_state > Terminated_Success; }
1066  bool IsCompleted() const { return m_state >= Completed; }
1067  bool IsCanceled() const { return m_state == Cancelling || m_state == Terminated_Cancelled || m_state == Terminated_Aborted; }
1068  bool IsTerminated() const { return m_state >= Terminated_Success; }
1069 
1070  void WaitForCompletion();
1071  PBoolean Cancel();
1072  void Abort();
1073 
1074  virtual PBoolean OnReceivedResponse(SIP_PDU & response);
1075  virtual PBoolean OnCompleted(SIP_PDU & response);
1076 
1077  SIPEndPoint & GetEndPoint() const { return m_owner->GetEndPoint(); }
1078  SIPConnection * GetConnection() const;
1079  PString GetInterface() const { return m_localInterface; }
1080 
1081  static PString GenerateCallID();
1082 
1083  protected:
1084  bool ResendCANCEL();
1085  void SetParameters(const SIPParameters & params);
1086 
1088 
1089  void OnRetry();
1090  void OnTimeout();
1091 
1092  P_DECLARE_TRACED_ENUM(States,
1093  NotStarted,
1094  Trying,
1095  Proceeding,
1096  Cancelling,
1097  Completed,
1098  Terminated_Success,
1099  Terminated_Timeout,
1100  Terminated_RetriesExceeded,
1101  Terminated_TransportError,
1102  Terminated_Cancelled,
1103  Terminated_Aborted
1104  );
1105  virtual void SetTerminated(States newState);
1106 
1109 
1110  PTimeInterval m_retryTimeoutMin;
1111  PTimeInterval m_retryTimeoutMax;
1112 
1113  States m_state;
1114  unsigned m_retry;
1117  PSyncPoint m_completed;
1120 
1121  friend class SIPConnection;
1122 };
1123 
1124 
1125 #define OPAL_PROXY_PARAM "OPAL-proxy"
1126 #define OPAL_LOCAL_ID_PARAM "OPAL-local-id"
1127 #define OPAL_INTERFACE_PARAM "OPAL-interface"
1128 
1129 
1131 // SIPResponse
1132 
1136 {
1137  PCLASSINFO(SIPResponse, SIPTransaction);
1138  public:
1139  SIPResponse(
1140  SIPEndPoint & endpoint,
1141  const SIP_PDU & command,
1142  StatusCodes code
1143  );
1144 
1145  virtual SIPTransaction * CreateDuplicate() const;
1146 
1147  virtual bool Send();
1148 };
1149 
1150 
1152 // SIPInvite
1153 
1160 {
1161  PCLASSINFO(SIPInvite, SIPTransaction);
1162  public:
1163  SIPInvite(
1164  SIPConnection & connection,
1165  OpalTransport * transport = NULL
1166  );
1167 
1168  virtual SIPTransaction * CreateDuplicate() const;
1169 
1170  virtual PBoolean OnReceivedResponse(SIP_PDU & response);
1171 
1173 };
1174 
1175 
1177 
1178 /* This is the ACK request sent when receiving a response to an outgoing
1179  * INVITE.
1180  */
1181 class SIPAck : public SIP_PDU
1182 {
1183  PCLASSINFO(SIPAck, SIP_PDU);
1184  public:
1185  SIPAck(
1186  const SIPTransaction & invite,
1187  const SIP_PDU & response
1188  );
1189 
1190  virtual SIPTransaction * CreateDuplicate() const;
1191 };
1192 
1193 
1195 
1196 /* This is a BYE request
1197  */
1198 class SIPBye : public SIPTransaction
1199 {
1200  PCLASSINFO(SIPBye, SIPTransaction);
1201  public:
1202  SIPBye(
1203  SIPEndPoint & endpoint,
1204  SIPDialogContext & dialog
1205  );
1206  SIPBye(
1207  SIPConnection & conn
1208  );
1209 
1210  virtual SIPTransaction * CreateDuplicate() const;
1211 };
1212 
1213 
1215 
1217 {
1218  PCLASSINFO(SIPRegister, SIPTransaction);
1219  public:
1220  P_DECLARE_TRACED_ENUM(CompatibilityModes,
1221  e_FullyCompliant,
1224  e_CannotRegisterMultipleContacts,
1228  e_CannotRegisterPrivateContacts,
1232  e_HasApplicationLayerGateway,
1236  e_RFC5626
1239  );
1240 
1242  struct Params : public SIPParameters {
1245  , m_compatibility(SIPRegister::e_FullyCompliant)
1246  , m_instanceId(NULL)
1247  { }
1248 
1249  Params(const Params & param)
1250  : SIPParameters(param)
1253  , m_instanceId(param.m_instanceId)
1254  { }
1255 
1256  PCaselessString & m_registrarAddress; // For backward compatibility
1257  CompatibilityModes m_compatibility;
1258  PGloballyUniqueID m_instanceId;
1259  };
1260 
1261  SIPRegister(
1262  SIPTransactionOwner & owner,
1263  OpalTransport & transport,
1264  const PString & callId,
1265  unsigned cseq,
1266  const Params & params
1267  );
1268 
1269  virtual SIPTransaction * CreateDuplicate() const;
1270 };
1271 
1272 
1273 #if PTRACING
1274 ostream & operator<<(ostream & strm, SIPRegister::CompatibilityModes mode);
1275 ostream & operator<<(ostream & strm, const SIPRegister::Params & params);
1276 #endif
1277 
1278 
1280 
1282 {
1283  PCLASSINFO(SIPSubscribe, SIPTransaction);
1284  public:
1293 
1295 
1296  Watcher = 0x8000,
1297 
1301 
1303  };
1305 
1306  class EventPackage : public PCaselessString
1307  {
1308  PCLASSINFO(EventPackage, PCaselessString);
1309  public:
1311  explicit EventPackage(const PString & str) : PCaselessString(str) { }
1312  explicit EventPackage(const char * str) : PCaselessString(str) { }
1313 
1315  EventPackage & operator=(const PString & str) { PCaselessString::operator=(str); return *this; }
1316  EventPackage & operator=(const char * str) { PCaselessString::operator=(str); return *this; }
1317 
1318  bool operator==(PredefinedPackages pkg) const { return Compare(EventPackage(pkg)) == EqualTo; }
1319  bool operator==(const PString & str) const { return Compare(str) == EqualTo; }
1320  bool operator==(const char * cstr) const { return InternalCompare(0, P_MAX_INDEX, cstr) == EqualTo; }
1321  virtual Comparison InternalCompare(PINDEX offset, PINDEX length, const char * cstr) const;
1322 
1323  bool IsWatcher() const;
1324  };
1325 
1334  void * m_userData;
1335  };
1336 
1339  SIPSubscribeHandler & handler,
1340  SIPEndPoint & ep,
1341  SIP_PDU & request,
1342  SIP_PDU & response
1343  );
1344 
1345 #if P_EXPAT
1346  bool LoadAndValidate(
1347  PXML & xml,
1348  const PXML::ValidationInfo * validator,
1349  PXML::Options options = PXML::WithNS
1350  );
1351 #endif
1352 
1353  bool SendResponse(
1355  const char * extra = NULL
1356  );
1357 
1363  };
1364 
1365  struct Params : public SIPParameters
1366  {
1369  , m_eventPackage(pkg)
1370  , m_eventList(false)
1371  { }
1372 
1373  Params(const Params & param)
1374  : SIPParameters(param)
1377  , m_eventList(param.m_eventList)
1378  , m_contentType(param.m_contentType)
1380  , m_onNotify(param.m_onNotify)
1381  { }
1382 
1383  PCaselessString & m_agentAddress; // For backward compatibility
1385  bool m_eventList; // Enable RFC4662
1386  PCaselessString m_contentType; // May be \n separated list of types
1387 
1388  PNotifierTemplate<const SubscriptionStatus &> m_onSubcribeStatus;
1389  PNotifierTemplate<NotifyCallbackInfo &> m_onNotify;
1390  };
1391 
1392  SIPSubscribe(
1393  SIPTransactionOwner & owner,
1394  OpalTransport & transport,
1395  SIPDialogContext & dialog,
1396  const Params & params
1397  );
1398 
1399  virtual SIPTransaction * CreateDuplicate() const;
1400 };
1401 
1402 
1403 #if PTRACING
1404 ostream & operator<<(ostream & strm, const SIPSubscribe::Params & params);
1405 #endif
1406 
1407 
1409 
1410 
1412 
1413 class SIPHandler;
1414 
1415 class SIPEventPackageHandler : public PObject
1416 {
1417  unsigned m_expectedSequenceNumber;
1418 
1419 public:
1420  SIPEventPackageHandler() : m_expectedSequenceNumber(UINT_MAX) { }
1421 
1423  virtual PCaselessString GetContentType() const = 0;
1424  virtual bool ValidateContentType(const PString & type, const SIPMIMEInfo & mime);
1425  virtual bool ValidateNotificationSequence(SIPSubscribeHandler & handler, unsigned newSequenceNumber, bool fullUpdate);
1426  virtual void OnReceivedNOTIFY(SIPSubscribe::NotifyCallbackInfo & notifyInfo) = 0;
1427  virtual PString OnSendNOTIFY(SIPHandler & /*handler*/, const PObject * /*body*/) { return PString::Empty(); }
1428 
1430 };
1431 
1432 
1433 typedef PFactory<SIPEventPackageHandler, SIPEventPackage> SIPEventPackageFactory;
1434 
1435 
1437 
1439 {
1440  PCLASSINFO(SIPNotify, SIPTransaction);
1441  public:
1442  SIPNotify(
1443  SIPTransactionOwner & owner,
1444  OpalTransport & transport,
1445  SIPDialogContext & dialog,
1446  const SIPEventPackage & eventPackage,
1447  const PString & state,
1448  const PString & body
1449  );
1450 
1451  virtual SIPTransaction * CreateDuplicate() const;
1452 };
1453 
1454 
1456 
1458 {
1459  PCLASSINFO(SIPPublish, SIPTransaction);
1460  public:
1461  SIPPublish(
1462  SIPTransactionOwner & owner,
1463  OpalTransport & transport,
1464  const PString & id,
1465  const PString & sipIfMatch,
1466  const SIPSubscribe::Params & params,
1467  const PString & body
1468  );
1469 
1470  virtual SIPTransaction * CreateDuplicate() const;
1471 };
1472 
1473 
1475 
1476 class SIPRefer : public SIPTransaction
1477 {
1478  PCLASSINFO(SIPRefer, SIPTransaction);
1479  public:
1480  SIPRefer(
1481  SIPConnection & connection,
1482  const SIPURL & referTo,
1483  const SIPURL & referred_by,
1484  bool referSub
1485  );
1486 
1487  virtual SIPTransaction * CreateDuplicate() const;
1488 };
1489 
1490 
1492 
1493 /* This is not a generic NOTIFY PDU, but the minimal one
1494  * that gets sent when receiving a REFER
1495  */
1497 {
1498  PCLASSINFO(SIPReferNotify, SIPTransaction);
1499  public:
1501  SIPConnection & connection,
1502  StatusCodes code
1503  );
1504 
1505  virtual SIPTransaction * CreateDuplicate() const;
1506 };
1507 
1508 
1510 
1511 /* This is a MESSAGE PDU, with a body
1512  */
1514 {
1515  PCLASSINFO(SIPMessage, SIPTransaction);
1516  public:
1517  struct Params : public SIPParameters
1518  {
1520  : m_contentType("text/plain;charset=UTF-8")
1521  {
1522  m_expire = 3600; // Try to get mesage through for an hour
1523  }
1524 
1525  PCaselessString m_contentType;
1526  PString m_id;
1527  PString m_body;
1528  PAtomicInteger::IntegerType m_messageId;
1529  };
1530 
1531  SIPMessage(
1532  SIPTransactionOwner & owner,
1533  OpalTransport & transport,
1534  const Params & params
1535  );
1536  SIPMessage(
1537  SIPConnection & connection,
1538  const Params & params
1539  );
1540 
1541  virtual SIPTransaction * CreateDuplicate() const;
1542 
1543  const Params & GetParameters() const { return m_parameters; }
1544  const SIPURL & GetLocalAddress() const { return m_localAddress; }
1545 
1546  private:
1547  void Construct(const Params & params);
1548 
1549  Params m_parameters;
1550  SIPURL m_localAddress;
1551 };
1552 
1553 
1555 
1556 /* This is an OPTIONS request
1557  */
1559 {
1560  PCLASSINFO(SIPOptions, SIPTransaction);
1561 
1562  public:
1563  struct Params : public SIPParameters
1564  {
1566  : m_acceptContent("application/sdp, application/media_control+xml, application/dtmf, application/dtmf-relay")
1567  {
1568  }
1569 
1570  PCaselessString m_acceptContent;
1571  PCaselessString m_contentType;
1572  PString m_body;
1573  };
1574 
1575  SIPOptions(
1576  SIPEndPoint & endpoint,
1577  const Params & params
1578  );
1579  SIPOptions(
1580  SIPConnection & conn,
1581  const Params & params
1582  );
1583 
1584  virtual SIPTransaction * CreateDuplicate() const;
1585 
1586  protected:
1587  void Construct(const Params & params);
1588 };
1589 
1590 
1592 
1593 /* This is an INFO request
1594  */
1595 class SIPInfo : public SIPTransaction
1596 {
1597  PCLASSINFO(SIPInfo, SIPTransaction);
1598 
1599  public:
1600  struct Params
1601  {
1602  Params(const PString & contentType = PString::Empty(),
1603  const PString & body = PString::Empty())
1604  : m_contentType(contentType)
1605  , m_body(body)
1606  {
1607  }
1608 
1609  PCaselessString m_contentType;
1610  PString m_body;
1611  };
1612 
1613  SIPInfo(
1614  SIPConnection & conn,
1615  const Params & params
1616  );
1617 
1618  virtual SIPTransaction * CreateDuplicate() const;
1619 };
1620 
1621 
1623 
1624 /* This is a PING PDU, with a body
1625  */
1626 class SIPPing : public SIPTransaction
1627 {
1628  PCLASSINFO(SIPPing, SIPTransaction);
1629 
1630  public:
1631  SIPPing(
1632  SIPTransactionOwner & owner,
1633  OpalTransport & transport,
1634  const SIPURL & address
1635  );
1636 
1637  virtual SIPTransaction * CreateDuplicate() const;
1638 };
1639 
1640 
1642 
1643 /* This is a PRACK PDU
1644  */
1645 class SIPPrack : public SIPTransaction
1646 {
1647  PCLASSINFO(SIPPrack, SIPTransaction);
1648 
1649  public:
1650  SIPPrack(
1651  SIPConnection & conn,
1652  OpalTransport & transport,
1653  const PString & rack
1654  );
1655 
1656  virtual SIPTransaction * CreateDuplicate() const;
1657 };
1658 
1659 
1660 #endif // OPAL_SIP
1661 
1662 #endif // OPAL_SIP_SIPPDU_H
1663 
1664 
1665 // End of File ///////////////////////////////////////////////////////////////