OPAL  Version 3.12.5
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: 30138 $
28  * $Author: rjongbloed $
29  * $Date: 2013-07-08 22:10:17 -0500 (Mon, 08 Jul 2013) $
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 
257 
258 
260 // SIPMIMEInfo
261 
292 class SIPMIMEInfo : public PMIMEInfo
293 {
294  PCLASSINFO(SIPMIMEInfo, PMIMEInfo);
295  public:
296  SIPMIMEInfo(bool compactForm = false);
297 
298  virtual void PrintOn(ostream & strm) const;
299  virtual bool InternalAddMIME(const PString & fieldName, const PString & fieldValue);
300 
301  void SetCompactForm(bool form) { compactForm = form; }
302 
303  PCaselessString GetContentType(bool includeParameters = false) const;
304  void SetContentType(const PString & v);
305 
306  PCaselessString GetContentEncoding() const;
307  void SetContentEncoding(const PString & v);
308 
309  SIPURL GetFrom() const;
310  void SetFrom(const SIPURL & v);
311 
313  void SetPAssertedIdentity(const PString & v);
314 
316  void SetPPreferredIdentity(const PString & v);
317 
318  PString GetAccept() const;
319  void SetAccept(const PString & v);
320 
321  PString GetAcceptEncoding() const;
322  void SetAcceptEncoding(const PString & v);
323 
324  PString GetAcceptLanguage() const;
325  void SetAcceptLanguage(const PString & v);
326 
327  PString GetAllow() const;
328  unsigned GetAllowBitMask() const;
329  void SetAllow(const PString & v);
330 
331  PString GetCallID() const;
332  void SetCallID(const PString & v);
333 
334  SIPURL GetContact() const;
335  bool GetContacts(SIPURLList & contacts) const;
336  void SetContact(const PString & v);
337 
338  PString GetSubject() const;
339  void SetSubject(const PString & v);
340 
341  SIPURL GetTo() const;
342  void SetTo(const SIPURL & v);
343 
344  PString GetVia() const;
345  void SetVia(const PString & v);
346 
347  bool GetViaList(PStringList & v) const;
348  void SetViaList(const PStringList & v);
349 
350  PString GetFirstVia() const;
352 
353  SIPURL GetReferTo() const;
354  void SetReferTo(const PString & r);
355 
356  SIPURL GetReferredBy() const;
357  void SetReferredBy(const PString & r);
358 
359  PINDEX GetContentLength() const;
360  void SetContentLength(PINDEX v);
361  PBoolean IsContentLengthPresent() const;
362 
363  PString GetCSeq() const;
364  void SetCSeq(const PString & v);
365 
366  PString GetDate() const;
367  void SetDate(const PString & v);
368  void SetDate(const PTime & t);
369  void SetDate(void); // set to current date
370 
371  unsigned GetExpires(unsigned dflt = UINT_MAX) const;// returns default value if not found
372  void SetExpires(unsigned v);
373 
374  unsigned GetMaxForwards() const;
375  void SetMaxForwards(PINDEX v);
376 
377  unsigned GetMinExpires() const;
378  void SetMinExpires(PINDEX v);
379 
380  PString GetProxyAuthenticate() const;
381  void SetProxyAuthenticate(const PString & v);
382 
383  PString GetRoute() const;
384  bool GetRoute(SIPURLList & proxies) const;
385  void SetRoute(const PString & v);
386  void SetRoute(const SIPURLList & proxies);
387 
388  PString GetRecordRoute() const;
389  bool GetRecordRoute(SIPURLList & proxies, bool reversed) const;
390  void SetRecordRoute(const PString & v);
391  void SetRecordRoute(const SIPURLList & proxies);
392 
393  unsigned GetCSeqIndex() const { return GetCSeq().AsUnsigned(); }
394 
395  PStringSet GetRequire() const;
396  void SetRequire(const PStringSet & v);
397  void AddRequire(const PString & v);
398 
399  PStringSet GetSupported() const;
400  void SetSupported(const PStringSet & v);
401  void AddSupported(const PString & v);
402 
403  PStringSet GetUnsupported() const;
404  void SetUnsupported(const PStringSet & v);
405  void AddUnsupported(const PString & v);
406 
407  PString GetEvent() const;
408  void SetEvent(const PString & v);
409 
410  PCaselessString GetSubscriptionState(PStringToString & info) const;
411  void SetSubscriptionState(const PString & v);
412 
413  PString GetUserAgent() const;
414  void SetUserAgent(const PString & v);
415 
416  PString GetOrganization() const;
417  void SetOrganization(const PString & v);
418 
419  void GetProductInfo(OpalProductInfo & info) const;
420  void SetProductInfo(const PString & ua, const OpalProductInfo & info);
421 
422  PString GetWWWAuthenticate() const;
423  void SetWWWAuthenticate(const PString & v);
424 
425  PString GetSIPIfMatch() const;
426  void SetSIPIfMatch(const PString & v);
427 
428  PString GetSIPETag() const;
429  void SetSIPETag(const PString & v);
430 
431  void GetAlertInfo(PString & info, int & appearance) const;
432  void SetAlertInfo(const PString & info, int appearance);
433 
434  PString GetCallInfo() const;
435 
436  PString GetAllowEvents() const;
437  void SetAllowEvents(const PString & v);
438  void SetAllowEvents(const PStringSet & list);
439 
443  const PString & fieldName,
444  const PString & paramName,
445  const PString & defaultValue = PString::Empty()
446  ) const { return ExtractFieldParameter((*this)(fieldName), paramName, defaultValue); }
447 
453  const PString & fieldName,
454  const PString & paramName,
455  const PString & newValue
456  ) { SetAt(fieldName, InsertFieldParameter((*this)(fieldName), paramName, newValue)); }
457 
460  static PString ExtractFieldParameter(
461  const PString & fieldValue,
462  const PString & paramName,
463  const PString & defaultValue = PString::Empty()
464  );
465 
470  static PString InsertFieldParameter(
471  const PString & fieldValue,
472  const PString & paramName,
473  const PString & newValue
474  );
475 
476  protected:
477  PStringSet GetTokenSet(const char * field) const;
478  void AddTokenSet(const char * field, const PString & token);
479  void SetTokenSet(const char * field, const PStringSet & tokens);
480 
483 };
484 
485 
487 // SIPAuthentication
488 
489 typedef PHTTPClientAuthentication SIPAuthentication;
490 
491 class SIPAuthenticator : public PHTTPClientAuthentication::AuthObject
492 {
493  public:
494  SIPAuthenticator(SIP_PDU & pdu);
495  virtual PMIMEInfo & GetMIME();
496  virtual PString GetURI();
497  virtual PString GetEntityBody();
498  virtual PString GetMethod();
499 
500  protected:
502 };
503 
504 
505 
507 // SIP_PDU
508 
514 class SIP_PDU : public PSafeObject
515 {
516  PCLASSINFO(SIP_PDU, PSafeObject);
517  public:
518  enum Methods {
534  };
535 
536  enum StatusCodes {
546 
552 
555 
561 
594 
602 
607 
609  };
610 
611  static PString GetStatusCodeDescription(int code);
612  friend ostream & operator<<(ostream & strm, StatusCodes status);
613 
614  SIP_PDU(
615  Methods method = SIP_PDU::NumMethods,
616  const OpalTransportPtr & transport = NULL,
617  const PString & transactionID = PString::Empty()
618  );
619 
623  SIP_PDU(
624  const SIP_PDU & request,
625  StatusCodes code,
626  const SDPSessionDescription * sdp = NULL
627  );
628 
629  SIP_PDU(const SIP_PDU &);
630  SIP_PDU & operator=(const SIP_PDU &);
631  ~SIP_PDU();
632 
633  void PrintOn(
634  ostream & strm
635  ) const;
636 
637  void InitialiseHeaders(
638  const SIPURL & dest,
639  const SIPURL & to,
640  const SIPURL & from,
641  const PString & callID,
642  unsigned cseq
643  );
644  void InitialiseHeaders(
645  SIPDialogContext & dialog,
646  unsigned cseq = 0
647  );
648  void InitialiseHeaders(
649  SIPConnection & connection,
650  unsigned cseq = 0
651  );
652  void InitialiseHeaders(
653  const SIP_PDU & request
654  );
655 
660  bool SetRoute(const SIPURLList & routeSet);
661  bool SetRoute(const SIPURL & proxy);
662 
665  void SetAllow(unsigned bitmask);
666 
669  StatusCodes Read();
671  istream & strm,
672  bool truncated
673  );
674 
677  virtual bool Send();
678 
681  bool SendResponse(
682  StatusCodes code
683  );
684 
688  void Build(PString & pduStr, PINDEX & pduLen);
689 
690  const PString & GetTransactionID() const { return m_transactionID; }
691 
692  Methods GetMethod() const { return m_method; }
695  const SIPURL & GetURI() const { return m_uri; }
696  void SetURI(const SIPURL & newuri) { m_uri = newuri; }
697  unsigned GetVersionMajor() const { return m_versionMajor; }
698  unsigned GetVersionMinor() const { return m_versionMinor; }
699  void SetCSeq(unsigned cseq);
700  const PString & GetEntityBody() const { return m_entityBody; }
701  void SetEntityBody(const PString & body) { m_entityBody = body; }
702  void SetEntityBody();
703  const PString & GetInfo() const { return m_info; }
704  void SetInfo(const PString & info) { m_info = info; }
705  const SIPMIMEInfo & GetMIME() const { return m_mime; }
706  SIPMIMEInfo & GetMIME() { return m_mime; }
708  void SetSDP(SDPSessionDescription * sdp);
709  bool DecodeSDP(const OpalMediaFormatList & masterList);
710 
711  const PString & GetExternalTransportAddress() const { return m_externalTransportAddress; }
713 
714  protected:
715  void CalculateVia();
716  StatusCodes InternalSend(bool canDoTCP);
717 
718  Methods m_method; // Request type, ==NumMethods for Response
720  SIPURL m_uri; // display name & URI, no tag
721  unsigned m_versionMajor;
722  unsigned m_versionMinor;
723  PString m_info;
725  PString m_entityBody;
727 
729 
733 };
734 
735 
736 PQUEUE(SIP_PDU_Queue, SIP_PDU);
737 
738 
739 #if PTRACING
740 ostream & operator<<(ostream & strm, SIP_PDU::Methods method);
741 #endif
742 
743 
745 // SIPDialogContext
746 
750 {
751  public:
753  SIPDialogContext(const SIPMIMEInfo & mime);
754 
755  PString AsString() const;
756  bool FromString(
757  const PString & str
758  );
759 
760  const PString & GetCallID() const { return m_callId; }
761  void SetCallID(const PString & id) { m_callId = id; }
762 
763  const SIPURL & GetRequestURI() const { return m_requestURI; }
764  void SetRequestURI(const SIPURL & url);
765 
766  const PString & GetLocalTag() const { return m_localTag; }
767  void SetLocalTag(const PString & tag) { m_localTag = tag; }
768 
769  const SIPURL & GetLocalURI() const { return m_localURI; }
770  void SetLocalURI(const SIPURL & url);
771 
772  const PString & GetRemoteTag() const { return m_remoteTag; }
773  void SetRemoteTag(const PString & tag) { m_remoteTag = tag; }
774 
775  const SIPURL & GetRemoteURI() const { return m_remoteURI; }
776  void SetRemoteURI(const SIPURL & url);
777 
778  const SIPURLList & GetRouteSet() const { return m_routeSet; }
779  void SetRouteSet(const PString & str) { m_routeSet.FromString(str); }
780 
781  const SIPURL & GetProxy() const { return m_proxy; }
782  void SetProxy(const SIPURL & proxy, bool addToRouteSet);
783 
784  void Update(const SIP_PDU & response);
785 
786  unsigned GetNextCSeq();
787  void IncrementCSeq(unsigned inc) { m_lastSentCSeq += inc; }
788 
789  bool IsDuplicateCSeq(unsigned sequenceNumber);
790 
791  bool IsEstablished() const
792  {
793  return !m_callId.IsEmpty() &&
794  !m_requestURI.IsEmpty() &&
795  !m_localTag.IsEmpty() &&
796  !m_remoteTag.IsEmpty();
797  }
798 
799  OpalTransportAddress GetRemoteTransportAddress(PINDEX dnsEntry) const;
800  const PString & GetInterface() const { return m_interface; }
801  void SetInterface(const PString & newInterface) { m_interface = newInterface; }
802 
803  void SetForking(bool f) { m_forking = f; }
804 
805  protected:
806  PString m_callId;
809  PString m_localTag;
811  PString m_remoteTag;
813  unsigned m_lastSentCSeq;
816  bool m_forking;
818  PString m_interface;
819 };
820 
821 
823 
825 {
827  const PString & aor = PString::Empty(),
828  const PString & remote = PString::Empty()
829  );
830 
831  bool Normalise(
832  const PString & defaultUser,
833  const PTimeInterval & defaultExpire
834  );
835 
836  PCaselessString m_remoteAddress;
837  PCaselessString m_localAddress;
838  PCaselessString m_proxyAddress;
839  PCaselessString m_addressOfRecord;
840  PCaselessString m_contactAddress;
841  PCaselessString m_interface;
843  PString m_authID;
844  PString m_password;
845  PString m_realm;
846  unsigned m_expire;
847  unsigned m_restoreTime;
848  PTimeInterval m_minRetryTime;
849  PTimeInterval m_maxRetryTime;
850  void * m_userData;
851 };
852 
853 
854 #if PTRACING
855 ostream & operator<<(ostream & strm, const SIPParameters & params);
856 #endif
857 
858 
860 // Thread pooling stuff
861 //
862 // Timer call back mechanism using PNOTIFIER is too prone to deadlocks, we
863 // want to use the existing thread pool for handling incoming PDUs.
864 
865 class SIPWorkItem : public PObject
866 {
867  PCLASSINFO(SIPWorkItem, PObject);
868  public:
869  SIPWorkItem(SIPEndPoint & ep, const PString & token);
870 
871  virtual void Work() = 0;
872 
873  bool GetTarget(PSafePtr<SIPTransaction> & transaction);
874  bool GetTarget(PSafePtr<SIPConnection> & connection);
875  bool GetTarget(PSafePtr<SIPHandler> & handler);
876 
877  protected:
879  PString m_token;
880 };
881 
882 
883 class SIPThreadPool : public PQueuedThreadPool<SIPWorkItem>
884 {
885  typedef PQueuedThreadPool<SIPWorkItem> BaseClass;
886  PCLASSINFO(SIPThreadPool, BaseClass);
887  public:
888  SIPThreadPool(unsigned maxWorkers, const char * threadName)
889  : BaseClass(maxWorkers, 0, threadName, PThread::HighPriority)
890  {
891  }
892 };
893 
894 
895 template <class Target_T>
897 {
898  PCLASSINFO(SIPTimeoutWorkItem, SIPWorkItem);
899  public:
900  typedef void (Target_T::* Callback)();
901 
902  SIPTimeoutWorkItem(SIPEndPoint & ep, const PString & token, Callback callback)
903  : SIPWorkItem(ep, token)
904  , m_callback(callback)
905  {
906  }
907 
908  virtual void Work()
909  {
910  PSafePtr<Target_T> target;
911  if (GetTarget(target)) {
912  PTRACE_CONTEXT_ID_PUSH_THREAD(target);
913  (target->*m_callback)();
914  PTRACE(4, "SIP\tHandled timeout");
915  }
916  }
917 
918  protected:
920 };
921 
922 
923 template <class Target_T>
924 class SIPPoolTimer : public PPoolTimerArg3<SIPTimeoutWorkItem<Target_T>,
925  SIPEndPoint &,
926  PString,
927  void (Target_T::*)(),
928  SIPWorkItem>
929 {
931  typedef PPoolTimerArg3<Work_T, SIPEndPoint &, PString, void (Target_T::*)(), SIPWorkItem> BaseClass;
932  PCLASSINFO(SIPPoolTimer, BaseClass);
933  private:
934  PString m_token;
935  public:
936  SIPPoolTimer(SIPThreadPool & pool, SIPEndPoint & ep, const PString & token, void (Target_T::* callback)())
937  : BaseClass(pool, ep, token, callback)
938  , m_token(token)
939  {
940  }
941 
942  virtual const char * GetGroup(const Work_T &) const { return m_token; }
943 
945 };
946 
947 
949 // SIPTransaction
950 
952 {
953  public:
955  PSafeObject & object,
956  SIPEndPoint & endpoint
957  );
958  virtual ~SIPTransactionOwner();
959 
960  virtual PString GetAuthID() const = 0;
961  virtual PString GetPassword() const { return PString::Empty(); }
962  virtual unsigned GetAllowedMethods() const;
963 
964  virtual void OnStartTransaction(SIPTransaction & /*transaction*/) { }
965  virtual void OnReceivedResponse(SIPTransaction & transaction, SIP_PDU & response);
966  virtual void OnTransactionFailed(SIPTransaction & transaction);
967 
968  void FinaliseForking(SIPTransaction & transaction, SIP_PDU & response);
970  void AbortPendingTransactions(bool all = true);
971 
973  const OpalTransport::WriteConnectCallback & function
974  );
975 
976  SIP_PDU::StatusCodes SwitchTransportProto(const char * proto, OpalTransportPtr * transport);
977 
979 
980  SIPEndPoint & GetEndPoint() const { return m_endpoint; }
982  const SIPURL & GetRequestURI() const { return m_dialog.GetRequestURI(); }
983  const SIPURL & GetRemoteURI() const { return m_dialog.GetRemoteURI(); }
984  const SIPURL & GetProxy() const { return m_dialog.GetProxy(); }
985  const PString & GetInterface() const { return m_dialog.GetInterface(); }
986  PINDEX GetDNSEntry() const { return m_dnsEntry; }
987  SIPAuthentication * GetAuthenticator() const { return m_authentication; }
989  const SIPDialogContext & GetDialog() const { return m_dialog; }
990 
991  protected:
992  PSafeObject & m_object;
994  SIPDialogContext m_dialog; // Not all derived classes use this as a dialog, but many fields useful
995  PINDEX m_dnsEntry;
996  SIPAuthentication * m_authentication;
998 
999  PSafeList<SIPTransaction> m_transactions;
1000  PMutex m_forkMutex;
1001 
1002  friend class SIPTransaction;
1003 };
1004 
1005 
1007 {
1008  PCLASSINFO(SIPTransactionBase, SIP_PDU);
1009  protected:
1011  Methods method,
1012  const OpalTransportPtr & transport,
1013  const PString & transactionID
1014  ) : SIP_PDU(method, transport, transactionID) { }
1015 
1016  public:
1018  const PString & transactionID
1019  ) { m_transactionID = transactionID; }
1020 
1021  Comparison Compare(
1022  const PObject & other
1023  ) const;
1024 
1025  virtual bool IsTerminated() const { return true; }
1026 };
1027 
1028 
1040 {
1041  PCLASSINFO(SIPTransaction, SIPTransactionBase);
1042  protected:
1044  Methods method,
1045  SIPTransactionOwner * owner,
1046  OpalTransport * transport,
1047  bool deleteOwner = false,
1048  const PString & transactionID = PString::Empty()
1049  );
1050  public:
1051  ~SIPTransaction();
1052 
1053  /* Under some circumstances a new transaction with all the same parameters
1054  but different ID needs to be created, e.g. when get authentication error. */
1055  virtual SIPTransaction * CreateDuplicate() const = 0;
1056 
1057  bool Start();
1058  bool IsTrying() const { return m_state == Trying; }
1059  bool IsProceeding() const { return m_state == Proceeding; }
1060  bool IsInProgress() const { return m_state == Trying || m_state == Proceeding; }
1061  bool IsFailed() const { return m_state > Terminated_Success; }
1062  bool IsCompleted() const { return m_state >= Completed; }
1063  bool IsCanceled() const { return m_state == Cancelling || m_state == Terminated_Cancelled || m_state == Terminated_Aborted; }
1064  bool IsTerminated() const { return m_state >= Terminated_Success; }
1065 
1066  void WaitForCompletion();
1067  PBoolean Cancel();
1068  void Abort();
1069 
1070  virtual PBoolean OnReceivedResponse(SIP_PDU & response);
1071  virtual PBoolean OnCompleted(SIP_PDU & response);
1072 
1073  SIPEndPoint & GetEndPoint() const { return m_owner->GetEndPoint(); }
1074  SIPConnection * GetConnection() const;
1075  PString GetInterface() const { return m_localInterface; }
1076 
1077  static PString GenerateCallID();
1078 
1079  protected:
1080  bool ResendCANCEL();
1081  void SetParameters(const SIPParameters & params);
1082 
1084 
1085  void OnRetry();
1086  void OnTimeout();
1087 
1088  P_DECLARE_TRACED_ENUM(States,
1089  NotStarted,
1090  Trying,
1091  Proceeding,
1092  Cancelling,
1093  Completed,
1094  Terminated_Success,
1095  Terminated_Timeout,
1096  Terminated_RetriesExceeded,
1097  Terminated_TransportError,
1098  Terminated_Cancelled,
1099  Terminated_Aborted
1100  );
1101  virtual void SetTerminated(States newState);
1102 
1105 
1106  PTimeInterval m_retryTimeoutMin;
1107  PTimeInterval m_retryTimeoutMax;
1108 
1109  States m_state;
1110  unsigned m_retry;
1113  PSyncPoint m_completed;
1116 
1117  friend class SIPConnection;
1118 };
1119 
1120 
1121 #define OPAL_PROXY_PARAM "OPAL-proxy"
1122 #define OPAL_LOCAL_ID_PARAM "OPAL-local-id"
1123 #define OPAL_INTERFACE_PARAM "OPAL-interface"
1124 
1125 
1127 // SIPResponse
1128 
1132 {
1133  PCLASSINFO(SIPResponse, SIPTransaction);
1134  public:
1135  SIPResponse(
1136  SIPEndPoint & endpoint,
1137  const SIP_PDU & command,
1138  StatusCodes code
1139  );
1140 
1141  virtual SIPTransaction * CreateDuplicate() const;
1142 
1143  virtual bool Send();
1144 };
1145 
1146 
1148 // SIPInvite
1149 
1156 {
1157  PCLASSINFO(SIPInvite, SIPTransaction);
1158  public:
1159  SIPInvite(
1160  SIPConnection & connection,
1161  OpalTransport * transport = NULL
1162  );
1163 
1164  virtual SIPTransaction * CreateDuplicate() const;
1165 
1166  virtual PBoolean OnReceivedResponse(SIP_PDU & response);
1167 
1169 };
1170 
1171 
1173 
1174 /* This is the ACK request sent when receiving a response to an outgoing
1175  * INVITE.
1176  */
1177 class SIPAck : public SIP_PDU
1178 {
1179  PCLASSINFO(SIPAck, SIP_PDU);
1180  public:
1181  SIPAck(
1182  const SIPTransaction & invite,
1183  const SIP_PDU & response
1184  );
1185 
1186  virtual SIPTransaction * CreateDuplicate() const;
1187 };
1188 
1189 
1191 
1192 /* This is a BYE request
1193  */
1194 class SIPBye : public SIPTransaction
1195 {
1196  PCLASSINFO(SIPBye, SIPTransaction);
1197  public:
1198  SIPBye(
1199  SIPEndPoint & endpoint,
1200  SIPDialogContext & dialog
1201  );
1202  SIPBye(
1203  SIPConnection & conn
1204  );
1205 
1206  virtual SIPTransaction * CreateDuplicate() const;
1207 };
1208 
1209 
1211 
1213 {
1214  PCLASSINFO(SIPRegister, SIPTransaction);
1215  public:
1216  P_DECLARE_TRACED_ENUM(CompatibilityModes,
1217  e_FullyCompliant,
1220  e_CannotRegisterMultipleContacts,
1224  e_CannotRegisterPrivateContacts,
1228  e_HasApplicationLayerGateway,
1232  e_RFC5626
1235  );
1236 
1238  struct Params : public SIPParameters {
1241  , m_compatibility(SIPRegister::e_FullyCompliant)
1242  , m_instanceId(NULL)
1243  { }
1244 
1245  Params(const Params & param)
1246  : SIPParameters(param)
1249  , m_instanceId(param.m_instanceId)
1250  { }
1251 
1252  PCaselessString & m_registrarAddress; // For backward compatibility
1253  CompatibilityModes m_compatibility;
1254  PGloballyUniqueID m_instanceId;
1255  };
1256 
1257  SIPRegister(
1258  SIPTransactionOwner & owner,
1259  OpalTransport & transport,
1260  const PString & callId,
1261  unsigned cseq,
1262  const Params & params
1263  );
1264 
1265  virtual SIPTransaction * CreateDuplicate() const;
1266 };
1267 
1268 
1269 #if PTRACING
1270 ostream & operator<<(ostream & strm, SIPRegister::CompatibilityModes mode);
1271 ostream & operator<<(ostream & strm, const SIPRegister::Params & params);
1272 #endif
1273 
1274 
1276 
1278 {
1279  PCLASSINFO(SIPSubscribe, SIPTransaction);
1280  public:
1289 
1291 
1292  Watcher = 0x8000,
1293 
1297 
1299  };
1301 
1302  class EventPackage : public PCaselessString
1303  {
1304  PCLASSINFO(EventPackage, PCaselessString);
1305  public:
1307  explicit EventPackage(const PString & str) : PCaselessString(str) { }
1308  explicit EventPackage(const char * str) : PCaselessString(str) { }
1309 
1311  EventPackage & operator=(const PString & str) { PCaselessString::operator=(str); return *this; }
1312  EventPackage & operator=(const char * str) { PCaselessString::operator=(str); return *this; }
1313 
1314  bool operator==(PredefinedPackages pkg) const { return Compare(EventPackage(pkg)) == EqualTo; }
1315  bool operator==(const PString & str) const { return Compare(str) == EqualTo; }
1316  bool operator==(const char * cstr) const { return InternalCompare(0, P_MAX_INDEX, cstr) == EqualTo; }
1317  virtual Comparison InternalCompare(PINDEX offset, PINDEX length, const char * cstr) const;
1318 
1319  bool IsWatcher() const;
1320  };
1321 
1330  void * m_userData;
1331  };
1332 
1335  SIPSubscribeHandler & handler,
1336  SIPEndPoint & ep,
1337  SIP_PDU & request,
1338  SIP_PDU & response
1339  );
1340 
1341 #if P_EXPAT
1342  bool LoadAndValidate(
1343  PXML & xml,
1344  const PXML::ValidationInfo * validator,
1345  PXML::Options options = PXML::WithNS
1346  );
1347 #endif
1348 
1349  bool SendResponse(
1351  const char * extra = NULL
1352  );
1353 
1359  };
1360 
1361  struct Params : public SIPParameters
1362  {
1365  , m_eventPackage(pkg)
1366  , m_eventList(false)
1367  { }
1368 
1369  Params(const Params & param)
1370  : SIPParameters(param)
1373  , m_eventList(param.m_eventList)
1374  , m_contentType(param.m_contentType)
1376  , m_onNotify(param.m_onNotify)
1377  { }
1378 
1379  PCaselessString & m_agentAddress; // For backward compatibility
1381  bool m_eventList; // Enable RFC4662
1382  PCaselessString m_contentType; // May be \n separated list of types
1383 
1384  PNotifierTemplate<const SubscriptionStatus &> m_onSubcribeStatus;
1385  PNotifierTemplate<NotifyCallbackInfo &> m_onNotify;
1386  };
1387 
1388  SIPSubscribe(
1389  SIPTransactionOwner & owner,
1390  OpalTransport & transport,
1391  SIPDialogContext & dialog,
1392  const Params & params
1393  );
1394 
1395  virtual SIPTransaction * CreateDuplicate() const;
1396 };
1397 
1398 
1399 #if PTRACING
1400 ostream & operator<<(ostream & strm, const SIPSubscribe::Params & params);
1401 #endif
1402 
1403 
1405 
1406 
1408 
1409 class SIPHandler;
1410 
1411 class SIPEventPackageHandler : public PObject
1412 {
1413  unsigned m_expectedSequenceNumber;
1414 
1415 public:
1416  SIPEventPackageHandler() : m_expectedSequenceNumber(UINT_MAX) { }
1417 
1419  virtual PCaselessString GetContentType() const = 0;
1420  virtual bool ValidateContentType(const PString & type, const SIPMIMEInfo & mime);
1421  virtual bool ValidateNotificationSequence(SIPSubscribeHandler & handler, unsigned newSequenceNumber, bool fullUpdate);
1422  virtual void OnReceivedNOTIFY(SIPSubscribe::NotifyCallbackInfo & notifyInfo) = 0;
1423  virtual PString OnSendNOTIFY(SIPHandler & /*handler*/, const PObject * /*body*/) { return PString::Empty(); }
1424 
1426 };
1427 
1428 
1429 typedef PFactory<SIPEventPackageHandler, SIPEventPackage> SIPEventPackageFactory;
1430 
1431 
1433 
1435 {
1436  PCLASSINFO(SIPNotify, SIPTransaction);
1437  public:
1438  SIPNotify(
1439  SIPTransactionOwner & owner,
1440  OpalTransport & transport,
1441  SIPDialogContext & dialog,
1442  const SIPEventPackage & eventPackage,
1443  const PString & state,
1444  const PString & body
1445  );
1446 
1447  virtual SIPTransaction * CreateDuplicate() const;
1448 };
1449 
1450 
1452 
1454 {
1455  PCLASSINFO(SIPPublish, SIPTransaction);
1456  public:
1457  SIPPublish(
1458  SIPTransactionOwner & owner,
1459  OpalTransport & transport,
1460  const PString & id,
1461  const PString & sipIfMatch,
1462  const SIPSubscribe::Params & params,
1463  const PString & body
1464  );
1465 
1466  virtual SIPTransaction * CreateDuplicate() const;
1467 };
1468 
1469 
1471 
1472 class SIPRefer : public SIPTransaction
1473 {
1474  PCLASSINFO(SIPRefer, SIPTransaction);
1475  public:
1476  SIPRefer(
1477  SIPConnection & connection,
1478  const SIPURL & referTo,
1479  const SIPURL & referred_by,
1480  bool referSub
1481  );
1482 
1483  virtual SIPTransaction * CreateDuplicate() const;
1484 };
1485 
1486 
1488 
1489 /* This is not a generic NOTIFY PDU, but the minimal one
1490  * that gets sent when receiving a REFER
1491  */
1493 {
1494  PCLASSINFO(SIPReferNotify, SIPTransaction);
1495  public:
1497  SIPConnection & connection,
1498  StatusCodes code
1499  );
1500 
1501  virtual SIPTransaction * CreateDuplicate() const;
1502 };
1503 
1504 
1506 
1507 /* This is a MESSAGE PDU, with a body
1508  */
1510 {
1511  PCLASSINFO(SIPMessage, SIPTransaction);
1512  public:
1513  struct Params : public SIPParameters
1514  {
1516  : m_contentType("text/plain;charset=UTF-8")
1517  {
1518  m_expire = 3600; // Try to get mesage through for an hour
1519  }
1520 
1521  PCaselessString m_contentType;
1522  PString m_id;
1523  PString m_body;
1524  PAtomicInteger::IntegerType m_messageId;
1525  };
1526 
1527  SIPMessage(
1528  SIPTransactionOwner & owner,
1529  OpalTransport & transport,
1530  const Params & params
1531  );
1532  SIPMessage(
1533  SIPConnection & connection,
1534  const Params & params
1535  );
1536 
1537  virtual SIPTransaction * CreateDuplicate() const;
1538 
1539  const Params & GetParameters() const { return m_parameters; }
1540  const SIPURL & GetLocalAddress() const { return m_localAddress; }
1541 
1542  private:
1543  void Construct(const Params & params);
1544 
1545  Params m_parameters;
1546  SIPURL m_localAddress;
1547 };
1548 
1549 
1551 
1552 /* This is an OPTIONS request
1553  */
1555 {
1556  PCLASSINFO(SIPOptions, SIPTransaction);
1557 
1558  public:
1559  struct Params : public SIPParameters
1560  {
1562  : m_acceptContent("application/sdp, application/media_control+xml, application/dtmf, application/dtmf-relay")
1563  {
1564  }
1565 
1566  PCaselessString m_acceptContent;
1567  PCaselessString m_contentType;
1568  PString m_body;
1569  };
1570 
1571  SIPOptions(
1572  SIPEndPoint & endpoint,
1573  const Params & params
1574  );
1575  SIPOptions(
1576  SIPConnection & conn,
1577  const Params & params
1578  );
1579 
1580  virtual SIPTransaction * CreateDuplicate() const;
1581 
1582  protected:
1583  void Construct(const Params & params);
1584 };
1585 
1586 
1588 
1589 /* This is an INFO request
1590  */
1591 class SIPInfo : public SIPTransaction
1592 {
1593  PCLASSINFO(SIPInfo, SIPTransaction);
1594 
1595  public:
1596  struct Params
1597  {
1598  Params(const PString & contentType = PString::Empty(),
1599  const PString & body = PString::Empty())
1600  : m_contentType(contentType)
1601  , m_body(body)
1602  {
1603  }
1604 
1605  PCaselessString m_contentType;
1606  PString m_body;
1607  };
1608 
1609  SIPInfo(
1610  SIPConnection & conn,
1611  const Params & params
1612  );
1613 
1614  virtual SIPTransaction * CreateDuplicate() const;
1615 };
1616 
1617 
1619 
1620 /* This is a PING PDU, with a body
1621  */
1622 class SIPPing : public SIPTransaction
1623 {
1624  PCLASSINFO(SIPPing, SIPTransaction);
1625 
1626  public:
1627  SIPPing(
1628  SIPTransactionOwner & owner,
1629  OpalTransport & transport,
1630  const SIPURL & address
1631  );
1632 
1633  virtual SIPTransaction * CreateDuplicate() const;
1634 };
1635 
1636 
1638 
1639 /* This is a PRACK PDU
1640  */
1641 class SIPPrack : public SIPTransaction
1642 {
1643  PCLASSINFO(SIPPrack, SIPTransaction);
1644 
1645  public:
1646  SIPPrack(
1647  SIPConnection & conn,
1648  OpalTransport & transport,
1649  const PString & rack
1650  );
1651 
1652  virtual SIPTransaction * CreateDuplicate() const;
1653 };
1654 
1655 
1656 #endif // OPAL_SIP
1657 
1658 #endif // OPAL_SIP_SIPPDU_H
1659 
1660 
1661 // End of File ///////////////////////////////////////////////////////////////