1 /**
2  * yatesip.h
3  * Yet Another SIP Stack
4  * This file is part of the YATE Project http://YATE.null.ro
5  *
6  * Yet Another Telephony Engine - a fully featured software PBX and IVR
7  * Copyright (C) 2004-2014 Null Team
8  *
9  * This software is distributed under multiple licenses;
10  * see the COPYING file in the main directory for licensing
11  * information for this specific distribution.
12  *
13  * This use of this software may be subject to additional restrictions.
14  * See the LEGAL file in the main directory for details.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #ifndef __YATESIP_H
22 #define __YATESIP_H
23 
24 #include <yateclass.h>
25 #include <yatemime.h>
26 
27 #ifdef _WINDOWS
28 
29 #ifdef LIBYSIP_EXPORTS
30 #define YSIP_API __declspec(dllexport)
31 #else
32 #ifndef LIBYSIP_STATIC
33 #define YSIP_API __declspec(dllimport)
34 #endif
35 #endif
36 
37 #endif /* _WINDOWS */
38 
39 #ifndef YSIP_API
40 #define YSIP_API
41 #endif
42 
43 /**
44  * Holds all Telephony Engine related classes.
45  */
46 namespace TelEngine {
47 
48 /**
49  * Token table containing default human readable responses for answer codes
50  */
51 extern YSIP_API TokenDict* SIPResponses;
52 
53 class SIPEngine;
54 class SIPEvent;
55 
56 class YSIP_API SIPParty : public RefObject
57 {
58 public:
59     SIPParty(Mutex* mutex = 0);
60     SIPParty(bool reliable, Mutex* mutex = 0);
61     virtual ~SIPParty();
62     /**
63      * Transmit an event
64      * @param event Evend to send
65      * @return False on fatal failure (subsequent send would fail again)
66      */
67     virtual bool transmit(SIPEvent* event) = 0;
68     virtual const char* getProtoName() const = 0;
69     virtual bool setParty(const URI& uri) = 0;
70     virtual void* getTransport() = 0;
71     void setAddr(const String& addr, int port, bool local);
72     void getAddr(String& addr, int& port, bool local);
73     inline void appendAddr(String& buf, bool local, bool unsafe = true) {
74 	    Lock lock(unsafe ? m_mutex : 0);
75 	    if (local)
76 		SocketAddr::appendTo(buf,m_local,m_localPort);
77 	    else
78 		SocketAddr::appendTo(buf,m_party,m_partyPort);
79 	}
mutex()80     inline Mutex* mutex()
81 	{ return m_mutex; }
getLocalAddr()82     inline const String& getLocalAddr() const
83 	{ return m_local; }
getPartyAddr()84     inline const String& getPartyAddr() const
85 	{ return m_party; }
getLocalPort()86     inline int getLocalPort() const
87 	{ return m_localPort; }
getPartyPort()88     inline int getPartyPort() const
89 	{ return m_partyPort; }
isReliable()90     inline bool isReliable() const
91 	{ return m_reliable; }
92 protected:
93     Mutex* m_mutex;
94     bool m_reliable;
95     String m_local;
96     String m_party;
97     int m_localPort;
98     int m_partyPort;
99 };
100 
101 /**
102  * Command Sequence Number generator
103  * @short SIP CSeq generator
104  */
105 class YSIP_API SIPSequence : public RefObject, public Mutex
106 {
107 public:
108     /**
109      * Constructor
110      * @param cseq Sequence number to start
111      */
112     inline SIPSequence(int32_t cseq = -1)
113 	: Mutex(false,"CSeq"), m_cseq(cseq)
114 	{ }
115 
116     /**
117      * Get the last number generated by this sequence
118      * @return Last generated CSeq value between 0 and 2^31-1, negative if not initialized
119      */
getLastCSeq()120     inline int32_t getLastCSeq() const
121 	{ return m_cseq; }
122 
123     /**
124      * Create a CSeq value suitable for use in a new request
125      * @return New CSeq value between 1 and 2^31-1
126      */
getNextCSeq()127     inline int32_t getNextCSeq()
128 	{ Lock mylock(this); return (++m_cseq > 0) ? m_cseq : (m_cseq = 1); }
129 
130     /**
131      * Set the Command Sequence number
132      * @param cseq New sequence number to start from
133      */
setCSeq(int32_t cseq)134     inline void setCSeq(int32_t cseq)
135 	{ m_cseq = cseq; }
136 
137 private:
138     int32_t m_cseq;
139 };
140 
141 /**
142  * An object that holds the sip message parsed into this library model.
143  * This class can be used to parse a sip message from a text buffer, or it
144  * can be used to create a text buffer from a sip message.
145  * @short A container and parser for SIP messages
146  */
147 class YSIP_API SIPMessage : public RefObject
148 {
149 public:
150     /**
151      * Various message flags
152      */
153     enum Flags {
154 	Defaults          =      0,
155 	NotReqRport       = 0x0001,
156 	NotAddAllow       = 0x0002,
157 	NotAddAgent       = 0x0004,
158 	RportAfterBranch  = 0x0008,
159 	NotSetRport       = 0x0010,
160 	NotSetReceived    = 0x0020,
161 	NoConnReuse       = 0x0040,      // Don't add 'alias' parameter to Via header (reliable only)
162 	NoTagFailure      = 0x0080,      // Don't add a To tag for 3xx/4xx/5xx/6xx answers
163     };
164 
165     /**
166      * Copy constructor
167      */
168     SIPMessage(const SIPMessage& original);
169 
170     /**
171      * Creates a new, empty, outgoing SIPMessage.
172      */
173     SIPMessage(const char* _method, const char* _uri, const char* _version = "SIP/2.0");
174 
175     /**
176      * Creates a new SIPMessage from parsing a text buffer.
177      * @param ep Party to set in message
178      * @param buf Buffer to parse
179      * @param len Optional buffer length
180      * @param bodyLen Pointer to body length to be set if the message was received
181      *  on a stream transport. If not 0 the buffer must contain the message
182      *  without its body
183      */
184     SIPMessage(SIPParty* ep, const char* buf, int len = -1, unsigned int* bodyLen = 0);
185 
186     /**
187      * Creates a new SIPMessage as answer to another message.
188      */
189     SIPMessage(const SIPMessage* message, int _code, const char* _reason = 0);
190 
191     /**
192      * Creates an ACK message from an original message and a response.
193      */
194     SIPMessage(const SIPMessage* original, const SIPMessage* answer);
195 
196     /**
197      * Destroy the message and all
198      */
199     virtual ~SIPMessage();
200 
201     /**
202      * Construct a new SIP message by parsing a text buffer
203      * @param ep Party to set in message
204      * @param buf Buffer to parse
205      * @param len Optional buffer length
206      * @param bodyLen Pointer to body length to be set if the message was received
207      *  on a stream transport. If not 0 the buffer must contain the message
208      *  without its body
209      * @return A pointer to a valid new message or NULL
210      */
211     static SIPMessage* fromParsing(SIPParty* ep, const char* buf, int len = -1,
212 	unsigned int* bodyLen = 0);
213 
214     /**
215      * Build message's body. Reset it before.
216      * This method should be called after parsing a partial message (headers only)
217      * @param buf Buffer to parse
218      * @param len Optional buffer length
219      */
220     void buildBody(const char* buf, int len = -1);
221 
222     /**
223      * Complete missing fields with defaults taken from a SIP engine
224      * @param engine Pointer to the SIP engine to use for extra parameters
225      * @param user Username to set in the From header instead of that in rURI
226      * @param domain Domain to use in From instead of the local IP address
227      * @param dlgTag Value of dialog tag parameter to set in To header
228      * @param flags Miscellaneous completion flags, -1 to take them from engine
229      */
230     void complete(SIPEngine* engine, const char* user = 0, const char* domain = 0, const char* dlgTag = 0, int flags = -1);
231 
232     /**
233      * Copy an entire header line (including all parameters) from another message
234      * @param message Pointer to the message to copy the header from
235      * @param name Name of the header to copy
236      * @param newName New name to force in headers, NULL to just copy
237      * @return True if the header was found and copied
238      */
239     bool copyHeader(const SIPMessage* message, const char* name, const char* newName = 0);
240 
241     /**
242      * Copy multiple header lines (including all parameters) from another message
243      * @param message Pointer to the message to copy the header from
244      * @param name Name of the headers to copy
245      * @param newName New name to force in headers, NULL to just copy
246      * @return Number of headers found and copied
247      */
248     int copyAllHeaders(const SIPMessage* message, const char* name, const char* newName = 0);
249 
250     /**
251      * Get the endpoint this message uses
252      * @return Pointer to the endpoint of this message
253      */
getParty()254     inline SIPParty* getParty() const
255 	{ return m_ep; }
256 
257     /**
258      * Set the endpoint this message uses
259      * @param ep Pointer to the endpoint of this message
260      */
261     void setParty(SIPParty* ep = 0);
262 
263     /**
264      * Check if this message is valid as result of the parsing
265      */
isValid()266     inline bool isValid() const
267 	{ return m_valid; }
268 
269     /**
270      * Check if this message is an answer or a request
271      */
isAnswer()272     inline bool isAnswer() const
273 	{ return m_answer; }
274 
275     /**
276      * Check if this message is an outgoing message
277      * @return True if this message should be sent to remote
278      */
isOutgoing()279     inline bool isOutgoing() const
280 	{ return m_outgoing; }
281 
282     /**
283      * Check if this message is an ACK message
284      * @return True if this message has an ACK method
285      */
isACK()286     inline bool isACK() const
287 	{ return m_ack; }
288 
289     /**
290      * Check if this message is handled by a reliable protocol
291      * @return True if a reliable protocol (TCP, SCTP) is used
292      */
isReliable()293     inline bool isReliable() const
294 	{ return m_ep ? m_ep->isReliable() : false; }
295 
296     /**
297      * Get the Command Sequence number from this message
298      * @return Number part of CSEQ in this message
299      */
getCSeq()300     inline int32_t getCSeq() const
301 	{ return m_cseq; }
302 
303     /**
304      * Set the Command Sequence number for this message
305      * @param cseq Sequence number for this message
306      */
setCSeq(int32_t cseq)307     inline void setCSeq(int32_t cseq)
308 	{ m_cseq = cseq; }
309 
310     /**
311      * Get the last flags used by this message
312      * @return Flags last used, ORed together
313      */
getFlags()314     inline int getFlags() const
315 	{ return m_flags; }
316 
317     /**
318      * Get value of flag that specifies the message is not to be sent on wire
319      * @return The value of the flag
320      */
dontSend()321     inline bool dontSend() const
322 	{ return m_dontSend; }
323 
324     /**
325      * Set flag that specifies the message is not to be sent on wire
326      * @param val Value of the flag to send
327      */
dontSend(bool val)328     inline void dontSend(bool val)
329 	{ m_dontSend = val; }
330     /**
331      * Find a header line by name
332      * @param name Name of the header to locate
333      * @return A pointer to the first matching header line or 0 if not found
334      */
335     const MimeHeaderLine* getHeader(const char* name) const;
336 
337     /**
338      * Find the last header line that matches a given name name
339      * @param name Name of the header to locate
340      * @return A pointer to the last matching header line or 0 if not found
341      */
342     const MimeHeaderLine* getLastHeader(const char* name) const;
343 
344     /**
345      * Count the header lines matching a specific name
346      * @param name Name of the header to locate
347      * @return Number of matching header lines
348      */
349     int countHeaders(const char* name) const;
350 
351     /**
352      * Find a header parameter by name
353      * @param name Name of the header to locate
354      * @param param Name of the parameter to locate in the tag
355      * @param last Find the last header with that name instead of first
356      * @return A pointer to the first matching header line or 0 if not found
357      */
358     const NamedString* getParam(const char* name, const char* param, bool last = false) const;
359 
360     /**
361      * Get a string value (without parameters) from a header line
362      * @param name Name of the header to locate
363      * @param last Find the last header with that name instead of first
364      * @return The value hold in the header or an empty String
365      */
366     const String& getHeaderValue(const char* name, bool last = false) const;
367 
368     /**
369      * Get a string value from a parameter in a header line
370      * @param name Name of the header to locate
371      * @param param Name of the parameter to locate in the tag
372      * @param last Find the last header with that name instead of first
373      * @return The value hold in the parameter or an empty String
374      */
375     const String& getParamValue(const char* name, const char* param, bool last = false) const;
376 
377     /**
378      * Append a new header line constructed from name and content
379      * @param name Name of the header to add
380      * @param value Content of the new header line
381      */
382     inline void addHeader(const char* name, const char* value = 0)
383 	{ header.append(new MimeHeaderLine(name,value)); }
384 
385     /**
386      * Append an already constructed header line
387      * @param line Header line to add
388      */
addHeader(MimeHeaderLine * line)389     inline void addHeader(MimeHeaderLine* line)
390 	{ header.append(line); }
391 
392     /**
393      * Clear all header lines that match a name
394      * @param name Name of the header to clear
395      */
396     void clearHeaders(const char* name);
397 
398     /**
399      * Set a header line constructed from name and content
400      */
401     inline void setHeader(const char* name, const char* value = 0)
402 	{ clearHeaders(name); addHeader(name,value); }
403 
404     /**
405      * Construct a new authorization line based on credentials and challenge
406      * @param username User account name
407      * @param password Clear text password for the account
408      * @param meth Method to include in the authorization digest
409      * @param uri URI to include in the authorization digest
410      * @param proxy Set to true to authenticate to a proxy, false to a server
411      * @param engine Optional engine processing this message
412      * @return A new authorization line to be used in a new transaction
413      */
414     MimeAuthLine* buildAuth(const String& username, const String& password,
415 	const String& meth, const String& uri, bool proxy = false, SIPEngine* engine = 0) const;
416 
417     /**
418      * Construct a new authorization line based on this answer and original message
419      * @param original Origianl outgoing message
420      * @param engine Optional engine processing this message
421      * @return A new authorization line to be used in a new transaction
422      */
423     MimeAuthLine* buildAuth(const SIPMessage& original, SIPEngine* engine = 0) const;
424 
425     /**
426      * Prepare the message for automatic client transaction authentication.
427      * @param username Username for auto authentication
428      * @param password Password for auto authentication
429      */
430     inline void setAutoAuth(const char* username = 0, const char* password = 0)
431 	{ m_authUser = username; m_authPass = password; }
432 
433     /**
434      * Retrieve the username to be used for auto authentication
435      * @return Username for auto authentication
436      */
getAuthUsername()437     inline const String& getAuthUsername() const
438 	{ return m_authUser; }
439 
440     /**
441      * Retrieve the password to be used for auto authentication
442      * @return Password for auto authentication
443      */
getAuthPassword()444     inline const String& getAuthPassword() const
445 	{ return m_authPass; }
446 
447     /**
448      * Extract routes from Record-Route: headers
449      * @return A list of MimeHeaderLine representing SIP routes
450      */
451     ObjList* getRoutes() const;
452 
453     /**
454      * Add Route: headers to an outgoing message
455      * @param routes List of MimeHeaderLine representing SIP routes
456      */
457     void addRoutes(const ObjList* routes);
458 
459     /**
460      * Get the Command Sequence Number generator
461      * @return Pointer to the CSeq generator of this message
462      */
getSequence()463     inline SIPSequence* getSequence() const
464 	{ return m_seq; }
465 
466     /**
467      * Set the Command Sequence Number generator
468      * @param seq Pointer to the new CSeq generator of this message
469      */
setSequence(SIPSequence * seq)470     inline void setSequence(SIPSequence* seq)
471 	{ m_seq = seq; }
472 
473     /**
474      * Creates a binary buffer from a SIPMessage.
475      */
476     const DataBlock& getBuffer() const;
477 
478     /**
479      * Creates a text buffer from the headers.
480      */
481     const String& getHeaders() const;
482 
483     /**
484      * Set a new body for this message
485      */
486     void setBody(MimeBody* newbody = 0);
487 
488     /**
489      * Get trace ID of the message
490      * @return The trace ID
491      */
traceId()492     const String& traceId() const
493         { return msgTraceId; }
494 
495     /**
496      * Sip Version
497      */
498     String version;
499 
500     /**
501      * This holds the method name of the message.
502      */
503     String method;
504 
505     /**
506      * URI of the request
507      */
508     String uri;
509 
510     /**
511      * Status code
512      */
513     int code;
514 
515     /**
516      * Reason Phrase
517      */
518     String reason;
519 
520     /**
521      * All the headers should be in this list.
522      */
523     ObjList header;
524 
525     /**
526      * All the body related things should be here, including the entire body and
527      * the parsed body.
528      */
529     MimeBody* body;
530 
531     /**
532      * Trace ID of the message
533      */
534     String msgTraceId;
535 
536     /**
537      * Message print in debug
538      */
539     bool msgPrint;
540 
541 protected:
542     bool parse(const char* buf, int len, unsigned int* bodyLen);
543     bool parseFirst(String& line);
544     SIPParty* m_ep;
545     RefPointer<SIPSequence> m_seq;
546     bool m_valid;
547     bool m_answer;
548     bool m_outgoing;
549     bool m_ack;
550     int32_t m_cseq;
551     int m_flags;
552     mutable String m_string;
553     mutable DataBlock m_data;
554     String m_authUser;
555     String m_authPass;
556     bool m_dontSend;
557 private:
558     SIPMessage(); // no, thanks
559 };
560 
561 /**
562  * A class to store information required to identify a dialog
563  * @short SIP Dialog object
564  */
565 class YSIP_API SIPDialog : public String
566 {
567 public:
568     /**
569      * Default constructor, build an empty SIP dialog
570      */
SIPDialog()571     inline SIPDialog()
572 	: remoteCSeq(-1)
573 	{ }
574 
575     /**
576      * Copy constructor
577      * @param original Original SIP dialog to copy
578      */
579     SIPDialog(const SIPDialog& original);
580 
581     /**
582      * Constructor from a SIP message
583      * @param message SIP message to copy the dialog information from
584      */
585     explicit SIPDialog(const SIPMessage& message);
586 
587     /**
588      * Constructor from a Call ID, leaves URIs and tags empty
589      * @param callid Call ID to insert in the dialog
590      */
SIPDialog(const String & callid)591     inline explicit SIPDialog(const String& callid)
592 	: String(callid), remoteCSeq(-1)
593 	{ }
594 
595     /**
596      * Assignment from another dialog
597      * @param original Original SIP dialog to copy
598      * @return Reference to this SIP dialog
599      */
600     SIPDialog& operator=(const SIPDialog& original);
601 
602     /**
603      * Assignment from a SIP message
604      * @param message SIP message to copy the dialog information from
605      * @return Reference to this SIP dialog
606      */
607     SIPDialog& operator=(const SIPMessage& message);
608 
609     /**
610      * Assignment from a Call ID, URIs and tags are cleared
611      * @param callid Call ID to copy to the dialog
612      * @return Reference to this SIP dialog
613      */
614     SIPDialog& operator=(const String& callid);
615 
616     /**
617      * SIP dialog matching check
618      * @param other Other dialog to compare to
619      * @param ignoreURIs True to ignore local and remote URIs when comparing
620      * @return True if the two dialogs match
621      */
622     bool matches(const SIPDialog& other, bool ignoreURIs) const;
623 
624     /**
625      * Dialog equality comparation, suitable for RFC 2543
626      * @param other Other dialog to compare to
627      * @return True if the two dialogs are equal
628      */
629     inline bool operator==(const SIPDialog& other) const
630 	{ return matches(other,false); }
631 
632     /**
633      * Dialog inequality comparation, suitable for RFC 2543
634      * @param other Other dialog to compare to
635      * @return True if the two dialogs are different
636      */
637     inline bool operator!=(const SIPDialog& other) const
638 	{ return !matches(other,false); }
639 
640     /**
641      * Dialog equality comparation, suitable for RFC 3261
642      * @param other Other dialog to compare to
643      * @return True if the two dialogs match (ignoring local and remote URIs)
644      */
645     inline bool operator&=(const SIPDialog& other) const
646 	{ return matches(other,true); }
647 
648     /**
649      * Dialog inequality comparation, suitable for RFC 3261
650      * @param other Other dialog to compare to
651      * @return True if the two dialogs do not match (ignoring local and remote URIs)
652      */
653     inline bool operator|=(const SIPDialog& other) const
654 	{ return !matches(other,true); }
655 
656     /**
657      * Get the From URI from the dialog
658      * @param outgoing True if getting the URI for an outgoing transaction
659      * @return Reference to the From URI in dialog
660      */
fromURI(bool outgoing)661     inline const String& fromURI(bool outgoing) const
662 	{ return outgoing ? localURI : remoteURI; }
663 
664     /**
665      * Get the From tag from the dialog
666      * @param outgoing True if getting the tag for an outgoing transaction
667      * @return Reference to the From URI tag in dialog
668      */
fromTag(bool outgoing)669     inline const String& fromTag(bool outgoing) const
670 	{ return outgoing ? localTag : remoteTag; }
671 
672     /**
673      * Get the To URI from the dialog
674      * @param outgoing True if getting the URI for an outgoing transaction
675      * @return Reference to the To URI in dialog
676      */
toURI(bool outgoing)677     inline const String& toURI(bool outgoing) const
678 	{ return outgoing ? remoteURI : localURI; }
679 
680     /**
681      * Get the To tag from the dialog
682      * @param outgoing True if getting the tag for an outgoing transaction
683      * @return Reference to the To URI tag in dialog
684      */
toTag(bool outgoing)685     inline const String& toTag(bool outgoing) const
686 	{ return outgoing ? remoteTag : localTag; }
687 
688     /**
689      * Get the Command Sequence Number generator
690      * @return Pointer to the CSeq generator of this dialog
691      */
getSequence()692     inline SIPSequence* getSequence() const
693 	{ return m_seq; }
694 
695     /**
696      * Set the Command Sequence Number generator
697      * @param seq Pointer to the new CSeq generator of this dialog
698      */
setSequence(SIPSequence * seq)699     inline void setSequence(SIPSequence* seq)
700 	{ m_seq = seq; }
701 
702     /**
703      * Set a new Command Sequence generator
704      * @param cseq New sequence number to start from
705      */
706     void setCSeq(int32_t cseq);
707 
708     /**
709      * Get the last number generated by this dialog
710      * @return Last generated CSeq value between 0 and 2^31-1, negative if no generator
711      */
getLastCSeq()712     inline int32_t getLastCSeq() const
713 	{ return m_seq ? m_seq->getLastCSeq() : -1; }
714 
715     /**
716      * Create a CSeq value suitable for use in a new request
717      * @return New CSeq value between 1 and 2^31-1, negative if no generator
718      */
getNextCSeq()719     inline int32_t getNextCSeq()
720 	{ return m_seq ? m_seq->getNextCSeq() : -1; }
721 
722     /**
723      * Adjust the last seen remote CSeq
724      * @param cseq Remote sequence number
725      * @return True if remote sequence was adjusted
726      */
adjustCSeq(int cseq)727     inline bool adjustCSeq(int cseq)
728 	{ return (cseq > remoteCSeq) && ((remoteCSeq = cseq) >= 0); }
729 
730     /**
731      * Adjust the last seen remote CSeq from a SIP message
732      * @param message Pointer to received SIP message
733      * @return True if remote sequence was adjusted
734      */
adjustCSeq(const SIPMessage * message)735     inline bool adjustCSeq(const SIPMessage* message)
736 	{ return message && adjustCSeq(message->getCSeq()); }
737 
738     /**
739      * Local URI of the dialog
740      */
741     String localURI;
742 
743     /**
744      * Tag parameter of the local URI
745      */
746     String localTag;
747 
748     /**
749      * Remote URI of the dialog
750      */
751     String remoteURI;
752 
753     /**
754      * Tag parameter of the remote URI
755      */
756     String remoteTag;
757 
758     /**
759      * Last seen Command Sequence Number
760      */
761     int remoteCSeq;
762 
763 protected:
764     RefPointer<SIPSequence> m_seq;
765 };
766 
767 /**
768  * All informaton related to a SIP transaction, starting with 1st message
769  * @short A class holding one SIP transaction
770  */
771 class YSIP_API SIPTransaction : public RefObject
772 {
773 public:
774     /**
775      * Current state of the transaction
776      */
777     enum State {
778 	// Invalid state - before constructor or after destructor
779 	Invalid,
780 
781 	// Initial state - after the initial message was inserted
782 	Initial,
783 
784 	// Trying state - got the message but no decision made yet
785 	Trying,
786 
787 	// Process state - while locally processing the event
788 	Process,
789 
790 	// Retrans state - retransmits latest message until getting ACK
791 	Retrans,
792 
793 	// Finish state - transmits the last message on client retransmission
794 	Finish,
795 
796 	// Cleared state - removed from engine, awaiting destruction
797 	Cleared
798     };
799 
800     /**
801      * Possible return values from @ref processMessage()
802      */
803     enum Processed {
804 	// Not matched at all
805 	NoMatch,
806 
807 	// Belongs to another dialog - probably result of a fork
808 	NoDialog,
809 
810 	// Matched to transaction/dialog and processed
811 	Matched
812     };
813 
814     /**
815      * Constructor from first message
816      * @param message A pointer to the initial message, should not be used
817      *  afterwards as the transaction takes ownership
818      * @param engine A pointer to the SIP engine this transaction belongs
819      * @param outgoing True if this transaction is for an outgoing request
820      * @param autoChangeParty Optional pointer to auto change party flag (use engine's flag if missing)
821      */
822     SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outgoing = true,
823 	bool* autoChangeParty = 0);
824 
825     /**
826      * Copy constructor to be used with forked INVITEs
827      * @param original Original transaction that is to be copied
828      * @param tag Dialog tag for the new transaction
829      */
830     SIPTransaction(const SIPTransaction& original, const String& tag);
831 
832     /**
833      * Destructor - clears all held objects
834      */
835     virtual ~SIPTransaction();
836 
837     /**
838      * Get the name of a transaction state
839      */
840     static const char* stateName(int state);
841 
842     /**
843      * The current state of the transaction
844      * @return The current state as one of the State enums
845      */
getState()846     inline int getState() const
847 	{ return m_state; }
848 
849     /**
850      * Check if the transaction is active for the upper layer
851      * @return True if the transaction is active, false if it finished
852      */
isActive()853     inline bool isActive() const
854 	{ return (Invalid < m_state) && (m_state < Finish); }
855 
856     /**
857      * The first message that created this transaction
858      */
initialMessage()859     inline const SIPMessage* initialMessage() const
860 	{ return m_firstMessage; }
861 
862     /**
863      * The last message (re)sent by this transaction
864      */
latestMessage()865     inline const SIPMessage* latestMessage() const
866 	{ return m_lastMessage; }
867 
868     /**
869      * The most recent message handled by this transaction
870      */
recentMessage()871     inline const SIPMessage* recentMessage() const
872 	{ return m_lastMessage ? m_lastMessage : m_firstMessage; }
873 
874     /**
875      * The SIPEngine this transaction belongs to
876      */
getEngine()877     inline SIPEngine* getEngine() const
878 	{ return m_engine; }
879 
880     /**
881      * Check if this transaction was initiated by the remote peer or locally
882      * @return True if the transaction was created by an outgoing message
883      */
isOutgoing()884     inline bool isOutgoing() const
885 	{ return m_outgoing; }
886 
887     /**
888      * Check if this transaction was initiated locally or by the remote peer
889      * @return True if the transaction was created by an incoming message
890      */
isIncoming()891     inline bool isIncoming() const
892 	{ return !m_outgoing; }
893 
894     /**
895      * Check if this transaction is an INVITE transaction or not
896      * @return True if the transaction is an INVITE
897      */
isInvite()898     inline bool isInvite() const
899 	{ return m_invite; }
900 
901     /**
902      * Check if this transaction is handled by a reliable protocol
903      * @return True if a reliable protocol (TCP, SCTP) is used
904      */
isReliable()905     inline bool isReliable() const
906 	{ return m_firstMessage ? m_firstMessage->isReliable() : false; }
907 
908     /**
909      * The SIP method this transaction handles
910      */
getMethod()911     inline const String& getMethod() const
912 	{ return m_firstMessage ? m_firstMessage->method : String::empty(); }
913 
914     /**
915      * The SIP URI this transaction handles
916      */
getURI()917     inline const String& getURI() const
918 	{ return m_firstMessage ? m_firstMessage->uri : String::empty(); }
919 
920     /**
921      * The Via branch that may uniquely identify this transaction
922      * @return The branch parameter taken from the Via header
923      */
getBranch()924     inline const String& getBranch() const
925 	{ return m_branch; }
926 
927     /**
928      * The call ID may identify this transaction
929      * @return The Call-ID parameter taken from the message
930      */
getCallID()931     inline const String& getCallID() const
932 	{ return m_callid; }
933 
934     /**
935      * The dialog tag that may identify this transaction
936      * @return The dialog tag parameter
937      */
getDialogTag()938     inline const String& getDialogTag() const
939 	{ return m_tag; }
940 
941     /**
942      * Set a new dialog tag, optionally build a random one
943      * @param tag New dialog tag, a null string will build a random tag
944      */
945     void setDialogTag(const char* tag = 0);
946 
947     /**
948      * Set the (re)transmission flag that allows the latest outgoing message
949      *  to be send over the wire
950      */
setTransmit()951     inline void setTransmit()
952 	{ m_transmit = true; }
953 
954     /**
955      * Change transaction status to Cleared
956      * This method is not thread safe
957      */
setCleared()958     inline void setCleared()
959 	{ changeState(Cleared); }
960 
961     /**
962      * Get the transmission attempts count for non-reliable transports
963      * @return Current number of transmission attempts
964      */
getTransCount()965     inline unsigned int getTransCount() const
966 	{ return m_transCount; }
967 
968     /**
969      * Set the number of transmission attempts for non-reliable transports
970      * @param count Transmission attempts, clamped between 2 and 10, negative values ignored
971      */
972     void setTransCount(int count);
973 
974     /**
975      * Get the automatic UAC 2xx ACK generation flag
976      * @return True if an ACK will be generated automatically for 2xx answers
977      */
autoAck()978     inline bool autoAck() const
979 	{ return m_autoAck; }
980 
981     /**
982      * Set the automatic UAC 2xx ACK generation flag
983      * @param setAuto True to automatically generate the ACK when receiving a 2xx answer
984      */
autoAck(bool setAuto)985     inline void autoAck(bool setAuto)
986 	{ m_autoAck = setAuto; }
987 
988     /**
989      * Send back an authentication required response
990      * @param realm Authentication realm to send in the answer
991      * @param domain Domain for which it will authenticate
992      * @param stale True if the previous password is valid but nonce is too old
993      * @param proxy True to authenticate as proxy, false as user agent
994      */
995     void requestAuth(const String& realm, const String& domain, bool stale, bool proxy = false);
996 
997     /**
998      * Detect the proper credentials for any user in the engine
999      * @param user String to store the authenticated user name or user to
1000      *  look for (if not null on entry)
1001      * @param proxy True to authenticate as proxy, false as user agent
1002      * @param userData Pointer to an optional object that is passed back to @ref SIPEngine::checkUser
1003      * @return Age of the nonce if user matches, negative for a failure
1004      */
1005     int authUser(String& user, bool proxy = false, GenObject* userData = 0);
1006 
1007     /**
1008      * Check if a message belongs to this transaction and process it if so
1009      * @param message A pointer to the message to check, should not be used
1010      *  afterwards if this method returned Matched
1011      * @param branch The branch parameter extracted from first Via header
1012      * @return Matched if the message was handled by this transaction, in
1013      *  which case it takes ownership over the message
1014      */
1015     virtual Processed processMessage(SIPMessage* message, const String& branch);
1016 
1017     /**
1018      * Process a message belonging to this transaction
1019      * @param message A pointer to the message to process, the caller must
1020      *  make sure it belongs to this transaction
1021      */
1022     virtual void processMessage(SIPMessage* message);
1023 
1024     /**
1025      * Get an event for this transaction if any is available.
1026      * It provides default handling for invalid states, otherwise calls
1027      *  the more specific protected version.
1028      * You may override this method if you need processing of invalid states.
1029      * @param pendingOnly True to only return outgoing and pending events
1030      * @param time Time to use in timeouts, zero to use system time
1031      * @return A newly allocated event or NULL if none is needed
1032      */
1033     virtual SIPEvent* getEvent(bool pendingOnly = false, u_int64_t time = 0);
1034 
1035     /**
1036      * Checks if a response message can be sent
1037      * @return True if the transaction can send a response message
1038      */
1039     bool setResponse() const;
1040 
1041     /**
1042      * Creates and transmits a final response message
1043      * @param code Response code to send
1044      * @param reason Human readable reason text (optional)
1045      * @return True if the message was queued for transmission
1046      */
1047     bool setResponse(int code, const char* reason = 0);
1048 
1049     /**
1050      * Transmits a final response message
1051      */
1052     void setResponse(SIPMessage* message);
1053 
1054     /**
1055      * Retrieve the latest response code
1056      * @return Code of most recent response, zero if none is known
1057      */
getResponseCode()1058     inline int getResponseCode() const
1059 	{ return m_response; }
1060 
1061     /**
1062      * Transmit an ACK message in UAC mode
1063      * @param ackBody Optional ACK message body, consumed by the method
1064      * @return True if state was correct and the message was queued for transmission
1065      */
1066     bool setAcknowledge(MimeBody* ackBody = 0);
1067 
1068     /**
1069      * Message send failure notification
1070      * @param msg Failed message
1071      */
1072     void msgTransmitFailed(SIPMessage* msg);
1073 
1074     /**
1075      * Set an arbitrary pointer as user specific data
1076      */
setUserData(void * data)1077     inline void setUserData(void* data)
1078 	{ m_private = data; }
1079 
1080     /**
1081      * Return the opaque user data
1082      */
getUserData()1083     inline void* getUserData() const
1084 	{ return m_private; }
1085 
1086     /**
1087      * Silent this transaction
1088      */
1089     void setSilent();
1090 
1091     /**
1092      * Trace ID of the transaction
1093      * @return Trace ID associated with this transaction
1094      */
traceId()1095     const String& traceId() const
1096         { return m_traceId; }
1097 
1098 protected:
1099     /**
1100      * Constructor from previous auto authenticated transaction. This is used only internally
1101      * @param original Original transaction that failed authentication
1102      * @param answer SIP answer that creates the new transaction
1103      */
1104     SIPTransaction(SIPTransaction& original, SIPMessage* answer);
1105 
1106     /**
1107      * Pre-destruction notification used to clean up the transaction
1108      */
1109     virtual void destroyed();
1110 
1111     /**
1112      * Attempt to perform automatic client transaction authentication
1113      * @param answer SIP answer that creates the new transaction
1114      * @return True if current client processing must be abandoned
1115      */
1116     bool tryAutoAuth(SIPMessage* answer);
1117 
1118     /**
1119      * Get an event only for client transactions
1120      * @param state The current state of the transaction
1121      * @param timeout If timeout occured, number of remaining timeouts,
1122      *  otherwise -1
1123      * @return A newly allocated event or NULL if none is needed
1124      */
1125     virtual SIPEvent* getClientEvent(int state, int timeout);
1126 
1127     /**
1128      * Get an event only for server transactions.
1129      * @param state The current state of the transaction
1130      * @param timeout If timeout occured, number of remaining timeouts,
1131      *  otherwise -1
1132      * @return A newly allocated event or NULL if none is needed
1133      */
1134     virtual SIPEvent* getServerEvent(int state, int timeout);
1135 
1136     /**
1137      * Process only the messages for client transactions
1138      * @param message A pointer to the message to process, should not be used
1139      *  afterwards if this method returned True
1140      * @param state The current state of the transaction
1141      */
1142     virtual void processClientMessage(SIPMessage* message, int state);
1143 
1144     /**
1145      * Process only the messages for server transactions
1146      * @param message A pointer to the message to process, should not be used
1147      *  afterwards if this method returned True
1148      * @param state The current state of the transaction
1149      */
1150     virtual void processServerMessage(SIPMessage* message, int state);
1151 
1152     /**
1153      * Change the transaction state
1154      * @param newstate The desired new state
1155      * @return True if state change occured
1156      */
1157     bool changeState(int newstate);
1158 
1159     /**
1160      * Set the latest message sent by this transaction
1161      * @param message Pointer to the latest message
1162      */
1163     void setLatestMessage(SIPMessage* message = 0);
1164 
1165     /**
1166      * Store a pending event to be picked up at the next @ref getEvent() call
1167      * @param event Event to store
1168      * @param replace True to replace any existing pending event
1169      */
1170     void setPendingEvent(SIPEvent* event = 0, bool replace = false);
1171 
1172     /**
1173      * Check if there is a pending event waiting
1174      * @return True is there is a pending event
1175      */
isPendingEvent()1176     inline bool isPendingEvent() const
1177 	{ return (m_pending != 0); }
1178 
1179     /**
1180      * Set a repetitive timeout
1181      * @param delay How often (in microseconds) to fire the timeout
1182      * @param count How many times to keep firing the timeout
1183      */
1184     void setTimeout(u_int64_t delay = 0, unsigned int count = 1);
1185 
1186     bool m_outgoing;
1187     bool m_invite;
1188     bool m_transmit;
1189     int m_state;
1190     int m_response;
1191     unsigned int m_transCount;
1192     unsigned int m_timeouts;
1193     u_int64_t m_delay;
1194     u_int64_t m_timeout;
1195     SIPMessage* m_firstMessage;
1196     SIPMessage* m_lastMessage;
1197     SIPEvent* m_pending;
1198     SIPEngine* m_engine;
1199     String m_branch;
1200     String m_callid;
1201     String m_tag;
1202     void *m_private;
1203     bool m_autoChangeParty;
1204     bool m_autoAck;
1205     bool m_silent;
1206     String m_traceId;
1207 };
1208 
1209 /**
1210  * This object is an event that will be taken from SIPEngine
1211  * @short A SIP event as retrieved from engine
1212  */
1213 class YSIP_API SIPEvent
1214 {
1215     friend class SIPTransaction;
1216 public:
1217 
SIPEvent()1218     SIPEvent()
1219 	: m_message(0), m_transaction(0), m_state(SIPTransaction::Invalid)
1220 	{ }
1221 
1222     SIPEvent(SIPMessage* message, SIPTransaction* transaction = 0);
1223 
1224     ~SIPEvent();
1225 
1226     /**
1227      * Get the SIP engine this event belongs to, if any
1228      * @return Pointer to owning SIP engine or NULL
1229      */
getEngine()1230     inline SIPEngine* getEngine() const
1231 	{ return m_transaction ? m_transaction->getEngine() : 0; }
1232 
1233     /**
1234      * Get the SIP message this event is supposed to handle
1235      * @return Pointer to SIP message causing the event
1236      */
getMessage()1237     inline SIPMessage* getMessage() const
1238 	{ return m_message; }
1239 
1240     /**
1241      * Get the SIP transaction that generated the event, if any
1242      * @return Pointer to owning SIP transaction or NULL
1243      */
getTransaction()1244     inline SIPTransaction* getTransaction() const
1245 	{ return m_transaction; }
1246 
1247     /**
1248      * Check if the message is an outgoing message
1249      * @return True if the message should be sent to remote
1250      */
isOutgoing()1251     inline bool isOutgoing() const
1252 	{ return m_message && m_message->isOutgoing(); }
1253 
1254     /**
1255      * Check if the message is an incoming message
1256      * @return True if the message is coming from remote
1257      */
isIncoming()1258     inline bool isIncoming() const
1259 	{ return m_message && !m_message->isOutgoing(); }
1260 
1261     /**
1262      * Get the pointer to the endpoint this event uses
1263      */
getParty()1264     inline SIPParty* getParty() const
1265 	{ return m_message ? m_message->getParty() : 0; }
1266 
1267     /**
1268      * Return the opaque user data stored in the transaction
1269      */
getUserData()1270     inline void* getUserData() const
1271 	{ return m_transaction ? m_transaction->getUserData() : 0; }
1272 
1273     /**
1274      * The state of the transaction when the event was generated
1275      */
getState()1276     inline int getState() const
1277 	{ return m_state; }
1278 
1279     /**
1280      * Check if the transaction was active when the event was generated
1281      * @return True if the transaction was active, false if it finished
1282      */
isActive()1283     inline bool isActive() const
1284 	{ return (SIPTransaction::Invalid < m_state) && (m_state < SIPTransaction::Finish); }
1285 
1286     /**
1287      * Retrieve the trace ID associated with this event
1288      * @return The trace ID, it can be empty.
1289      */
traceId()1290     inline const String& traceId() const
1291         { return m_transaction ? m_transaction->traceId() : String::empty(); }
1292 
1293 protected:
1294     SIPMessage* m_message;
1295     SIPTransaction* m_transaction;
1296     int m_state;
1297 };
1298 
1299 /**
1300  * The SIP engine holds common methods and the list of current transactions
1301  * @short The SIP engine and transaction list
1302  */
1303 class YSIP_API SIPEngine : public DebugEnabler, public Mutex
1304 {
1305 public:
1306     /**
1307      * Create the SIP Engine
1308      */
1309     SIPEngine(const char* userAgent = 0);
1310 
1311     /**
1312      * Destroy the SIP Engine
1313      */
1314     virtual ~SIPEngine();
1315 
1316     /**
1317      * Build a new SIPParty for a message
1318      * @param message Pointer to the message to build the party
1319      * @return True on success, false if party could not be built
1320      */
1321     virtual bool buildParty(SIPMessage* message) = 0;
1322 
1323     /**
1324      * Allocate a new trace ID. If tracing is not active, string will not be modified
1325      * @param id String where to put allocated ID.
1326      */
1327     virtual void allocTraceId(String& id) = 0;
1328 
1329     /**
1330      * Print a SIP message only if it has a trace ID
1331      * @param message The message to print
1332      * @param incoming True if the message is incoming
1333      */
1334     virtual void traceMsg(SIPMessage* message, bool incoming = true) = 0;
1335 
1336     /**
1337      * Check user credentials for validity
1338      * @param username User account name
1339      * @param realm Authentication realm
1340      * @param nonce Authentication opaque nonce generated by the server
1341      * @param method Method of the SIP message that is being authenticated
1342      * @param uri URI of the SIP message that is being authenticated
1343      * @param response Response computed by the authenticated entity
1344      * @param message Message that is to be authenticated
1345      * @param authLine Extra credentials line to validate
1346      * @param userData Pointer to an optional object passed from @ref authUser
1347      * @return True if valid user/password, false if verification failed
1348      */
1349     virtual bool checkUser(String& username, const String& realm, const String& nonce,
1350 	const String& method, const String& uri, const String& response,
1351 	const SIPMessage* message, const MimeHeaderLine* authLine, GenObject* userData);
1352 
1353     /**
1354      * Authenticate a message by other means than user credentials. By default
1355      *  it calls @ref checkUser with empty user credential fields
1356      * @param noUser No plausible user credentials were detected so far
1357      * @param username User account name
1358      * @param message Message that is to be authenticated
1359      * @param authLine Extra credentials line to validate
1360      * @param userData Pointer to an optional object passed from @ref authUser
1361      * @return True if message is authenticated, false if verification failed
1362      */
1363     virtual bool checkAuth(bool noUser, String& username, const SIPMessage* message,
1364 	const MimeHeaderLine* authLine, GenObject* userData);
1365 
1366     /**
1367      * Detect the proper credentials for any user in the engine
1368      * @param message Pointer to the message to check
1369      * @param user String to store the authenticated user name or user to
1370      *  look for (if not null on entry)
1371      * @param proxy True to authenticate as proxy, false as user agent
1372      * @param userData Pointer to an optional object that is passed back to @ref checkUser
1373      * @return Age of the nonce if user matches, negative for a failure
1374      */
1375     int authUser(const SIPMessage* message, String& user, bool proxy = false, GenObject* userData = 0);
1376 
1377     /**
1378      * Add a message into the transaction list
1379      * @param ep Party of the received message
1380      * @param buf A buffer containing the SIP message text
1381      * @param len The length of the message or -1 to interpret as C string
1382      * @return Pointer to the transaction or NULL if message was invalid
1383      */
1384     SIPTransaction* addMessage(SIPParty* ep, const char* buf, int len = -1);
1385 
1386     /**
1387      * Add a message into the transaction list
1388      * This method is thread safe
1389      * @param message A parsed SIP message to add to the transactions
1390      * @param autoChangeParty Optional auto change party to set in transaction if a new one is created
1391      * @return Pointer to the transaction or NULL if message was invalid
1392      */
1393     SIPTransaction* addMessage(SIPMessage* message, bool* autoChangeParty = 0);
1394 
1395     /**
1396      * Get a SIPEvent from the queue.
1397      * This method mainly looks into the transaction list and get all kind of
1398      * events, like an incoming request (INVITE, REGISTRATION), a timer, an
1399      * outgoing message.
1400      * This method is thread safe
1401      */
1402     SIPEvent *getEvent();
1403 
1404     /**
1405      * This method should be called very often to get the events from the list and
1406      * to send them to processEvent method.
1407      * @return True if some events were processed this turn
1408      */
1409     bool process();
1410 
1411     /**
1412      * Default handling for events.
1413      * This method should be overriden for what you need and at the end you
1414      * should call this default one
1415      * This method is thread safe
1416      */
1417     virtual void processEvent(SIPEvent *event);
1418 
1419     /**
1420      * Handle answers that create new dialogs for an outgoing INVITE
1421      * @param answer The message that creates the INVITE fork
1422      * @param trans One of the transactions part of the same INVITE
1423      * @return Pointer to new transaction or NULL if message is ignored
1424      */
1425     virtual SIPTransaction* forkInvite(SIPMessage* answer, SIPTransaction* trans);
1426 
1427     /**
1428      * Get the timeout to be used for transactions involving human interaction.
1429      * The default implementation returns the proxy INVITE timeout (timer C = 3 minutes)
1430      *  minus the INVITE response retransmit interval (timer T2 = 4 seconds)
1431      * @return Duration of the timeout in microseconds
1432      */
1433     virtual u_int64_t getUserTimeout() const;
1434 
1435     /**
1436      * Get the length of a timer
1437      * @param which A one-character constant that selects which timer to return
1438      * @param reliable Whether we request the timer value for a reliable protocol
1439      * @return Duration of the selected timer or 0 if invalid
1440      */
1441     u_int64_t getTimer(char which, bool reliable = false) const;
1442 
1443     /**
1444      * Get the number of times to send a SIP request.
1445      * This value applies only when retransmission is required
1446      * @return The number of times to send a SIP request
1447      */
getReqTransCount()1448     inline unsigned int getReqTransCount() const
1449 	{ return m_reqTransCount; }
1450 
1451     /**
1452      * Get the number of times to send a response to a SIP request.
1453      * This value applies only when retransmission is required
1454      * @return The number of times to send a response to a SIP request
1455      */
getRspTransCount()1456     inline unsigned int getRspTransCount() const
1457 	{ return m_rspTransCount; }
1458 
1459     /**
1460      * Get the default value of the Max-Forwards header for this engine
1461      * @return The maximum number of hops the request is allowed to pass
1462      */
getMaxForwards()1463     inline unsigned int getMaxForwards() const
1464 	{ return m_maxForwards; }
1465 
1466     /**
1467      * Get the User agent for this SIP engine
1468      */
getUserAgent()1469     inline const String& getUserAgent() const
1470 	{ return m_userAgent; }
1471 
1472     /**
1473      * Get the Command Sequence Number generator
1474      * @return Pointer to the CSeq generator of this engine
1475      */
getSequence()1476     inline SIPSequence* getSequence() const
1477 	{ return m_seq; }
1478 
1479     /**
1480      * Get a CSeq value suitable for use in a new request
1481      * @return New CSeq value
1482      */
getNextCSeq()1483     inline int32_t getNextCSeq()
1484 	{ return m_seq->getNextCSeq(); }
1485 
1486     /**
1487      * Check if the engine is set up for lazy "100 Trying" messages
1488      * @return True if the first 100 message is to be skipped for non-INVITE
1489      */
lazyTrying()1490     inline bool lazyTrying() const
1491 	{ return m_lazyTrying; }
1492 
1493     /**
1494      * Set the lazy "100 Trying" messages flag
1495      * @param lazy100 True to not send the 1st 100 message for non-INVITE
1496      */
lazyTrying(bool lazy100)1497     inline void lazyTrying(bool lazy100)
1498 	{ m_lazyTrying = lazy100; }
1499 
1500     /**
1501      * Retrieve various flags for this engine
1502      * @return Value of flags ORed together
1503      */
flags()1504     inline int flags() const
1505 	{ return m_flags; }
1506 
1507     /**
1508      * Check if message party should be changed from latest dialog party
1509      * @return Value of auto change party option
1510      */
autoChangeParty()1511     inline bool autoChangeParty() const
1512 	{ return m_autoChangeParty; }
1513 
1514     /**
1515      * Get an authentication nonce
1516      * @param nonce String reference to fill with the current nonce
1517      */
1518     void nonceGet(String& nonce);
1519 
1520     /**
1521      * Get the age of an authentication nonce
1522      * @param nonce String nonce to check for validity and age
1523      * @return Age of the nonce in seconds, negative for invalid
1524      */
1525     long nonceAge(const String& nonce);
1526 
1527     /**
1528      * Get a nonce count
1529      * @param nc String reference to fill with new nonce count
1530      */
1531     void ncGet(String& nc);
1532 
1533     /**
1534      * Build an authentication response
1535      * @param username User account name
1536      * @param realm Authentication realm
1537      * @param passwd Account password
1538      * @param nonce Authentication opaque nonce generated by the server
1539      * @param method Method of the SIP message that is being authenticated
1540      * @param uri URI of the SIP message that is being authenticated
1541      * @param response String to store the computed response
1542      * @param qop Optional quality of protection type (set in list name) and parameters
1543      */
1544     static void buildAuth(const String& username, const String& realm, const String& passwd,
1545 	const String& nonce, const String& method, const String& uri, String& response,
1546 	const NamedList& qop = NamedList::empty());
1547 
1548     /**
1549      * Build an authentication response from already hashed components
1550      * @param hash_a1 MD5 digest of username:realm:password
1551      * @param nonce Authentication opaque nonce generated by the server
1552      * @param hash_a2 MD5 digest of method:uri
1553      * @param response String to store the computed response
1554      */
1555     static void buildAuth(const String& hash_a1, const String& nonce, const String& hash_a2,
1556 	String& response);
1557 
1558     /**
1559      * Check if a method is in the allowed methods list
1560      * @param method Uppercase name of the method to check
1561      * @return True if the method should be allowed processing
1562      */
1563     bool isAllowed(const char* method) const;
1564 
1565     /**
1566      * Add a method to the allowed methods list
1567      * @param method Uppercase name of the method to add
1568      */
1569     void addAllowed(const char* method);
1570 
1571     /**
1572      * Get all the allowed methods
1573      * @return Comma separated list of allowed methods
1574      */
getAllowed()1575     inline const String& getAllowed() const
1576 	{ return m_allowed; }
1577 
1578     /**
1579      * Remove a transaction from the list without dereferencing it
1580      * @param transaction Pointer to transaction to remove
1581      */
remove(SIPTransaction * transaction)1582     inline void remove(SIPTransaction* transaction)
1583 	{ lock(); m_transList.remove(transaction,false); unlock(); }
1584 
1585     /**
1586      * Append a transaction to the end of the list
1587      * @param transaction Pointer to transaction to append
1588      */
append(SIPTransaction * transaction)1589     inline void append(SIPTransaction* transaction)
1590 	{ lock(); m_transList.append(transaction); unlock(); }
1591 
1592     /**
1593      * Insert a transaction at the start of the list
1594      * @param transaction Pointer to transaction to insert
1595      */
insert(SIPTransaction * transaction)1596     inline void insert(SIPTransaction* transaction)
1597 	{ lock(); m_transList.insert(transaction); unlock(); }
1598 
1599     /**
1600      * Get the number of active SIP transactions
1601      * @return Count of transactions in the list
1602      */
transactionCount()1603     inline unsigned int transactionCount()
1604 	{ Lock mylock(this); return m_transList.count(); }
1605 
1606 protected:
1607     /**
1608      * The list that holds all the SIP transactions.
1609      */
1610     ObjList m_transList;
1611 
1612     u_int64_t m_t1;
1613     u_int64_t m_t4;
1614     int m_reqTransCount;
1615     int m_rspTransCount;
1616     unsigned int m_maxForwards;
1617     int m_flags;
1618     bool m_lazyTrying;
1619     String m_userAgent;
1620     String m_allowed;
1621     RefPointer<SIPSequence> m_seq;
1622     u_int32_t m_nc;
1623     String m_nonce;
1624     String m_nonce_secret;
1625     u_int32_t m_nonce_time;
1626     Mutex m_nonce_mutex;
1627     bool m_autoChangeParty;
1628 };
1629 
1630 }
1631 
1632 #endif /* __YATESIP_H */
1633 
1634 /* vi: set ts=8 sw=4 sts=4 noet: */
1635