1 /**
2  * transaction.cpp
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 #include <yatesip.h>
22 
23 #include <string.h>
24 #include <stdlib.h>
25 
26 
27 using namespace TelEngine;
28 
29 // Constructor from new message
SIPTransaction(SIPMessage * message,SIPEngine * engine,bool outgoing,bool * autoChangeParty)30 SIPTransaction::SIPTransaction(SIPMessage* message, SIPEngine* engine, bool outgoing,
31     bool* autoChangeParty)
32     : m_outgoing(outgoing), m_invite(false), m_transmit(false), m_state(Invalid),
33       m_response(0), m_timeouts(0), m_timeout(0),
34       m_firstMessage(message), m_lastMessage(0), m_pending(0), m_engine(engine), m_private(0),
35       m_autoChangeParty(autoChangeParty ? *autoChangeParty : engine->autoChangeParty()),
36       m_autoAck(true), m_silent(false)
37 {
38     DDebug(getEngine(),DebugAll,"SIPTransaction::SIPTransaction(%p,%p,%d) [%p]",
39 	message,engine,outgoing,this);
40     if (m_firstMessage) {
41 	m_firstMessage->ref();
42 
43 	const NamedString* ns = message->getParam("Via","branch",true);
44 	if (ns)
45 	    m_branch = *ns;
46 	if (!m_branch.startsWith("z9hG4bK"))
47 	    m_branch.clear();
48 	ns = message->getParam("To","tag");
49 	if (ns)
50 	    m_tag = *ns;
51 
52 	const MimeHeaderLine* hl = message->getHeader("Call-ID");
53 	if (hl)
54 	    m_callid = *hl;
55 
56 	if (!m_outgoing && m_firstMessage->getParty()) {
57 	    // adjust the address where we send the answers
58 	    hl = message->getHeader("Via");
59 	    if (hl) {
60 		URI uri(*hl);
61 		// skip over protocol/version/transport
62 		uri >> "/" >> "/" >> " ";
63 		uri.trimBlanks();
64 		uri = "sip:" + uri;
65 		m_firstMessage->getParty()->setParty(uri);
66 	    }
67 	}
68     }
69     m_invite = (getMethod() == YSTRING("INVITE"));
70     m_state = Initial;
71     m_transCount = outgoing ? m_engine->getReqTransCount() : m_engine->getRspTransCount();
72     if (!outgoing) {
73 	m_engine->allocTraceId(m_traceId);
74 	m_firstMessage->msgTraceId = m_traceId;
75 	m_engine->traceMsg(m_firstMessage,true);
76     }
77     else
78       m_traceId = m_firstMessage->msgTraceId;
79     m_engine->append(this);
80 }
81 
82 // Constructor from original and authentication requesting answer
SIPTransaction(SIPTransaction & original,SIPMessage * answer)83 SIPTransaction::SIPTransaction(SIPTransaction& original, SIPMessage* answer)
84     : m_outgoing(true), m_invite(original.m_invite), m_transmit(false), m_state(Process),
85       m_response(original.m_response), m_transCount(original.m_transCount),
86       m_timeouts(0), m_timeout(0),
87       m_firstMessage(original.m_firstMessage), m_lastMessage(original.m_lastMessage),
88       m_pending(0), m_engine(original.m_engine),
89       m_branch(original.m_branch), m_callid(original.m_callid), m_tag(original.m_tag),
90       m_private(0), m_autoChangeParty(original.m_autoChangeParty),
91       m_autoAck(original.m_autoAck), m_silent(original.m_silent), m_traceId(original.traceId())
92 {
93     DDebug(getEngine(),DebugAll,"SIPTransaction::SIPTransaction(&%p,%p) [%p]",
94 	&original,answer,this);
95 
96     SIPMessage* msg = new SIPMessage(*original.m_firstMessage);
97     MimeAuthLine* auth = answer->buildAuth(*original.m_firstMessage,m_engine);
98     m_firstMessage->setAutoAuth();
99     msg->complete(m_engine);
100     msg->addHeader(auth);
101     const NamedString* ns = msg->getParam("Via","branch",true);
102     if (ns)
103 	original.m_branch = *ns;
104     else
105 	original.m_branch.clear();
106     ns = msg->getParam("To","tag");
107     if (ns)
108 	original.m_tag = *ns;
109     else
110 	original.m_tag.clear();
111     original.m_firstMessage = msg;
112     original.m_lastMessage = 0;
113 
114 #ifdef SIP_ACK_AFTER_NEW_INVITE
115     // if this transaction is an INVITE and we append it to the list its
116     //  ACK will be sent after the new INVITE which is legal but "unnatural"
117     // some SIP endpoints seem to assume things about transactions
118     m_engine->append(this);
119 #else
120     // insert this transaction rather than appending it
121     // this way we get a chance to send one ACK before a new INVITE
122     // note that there is no guarantee because of the possibility of the
123     //  packets getting lost and retransmitted or to use a different route
124     m_engine->insert(this);
125 #endif
126 }
127 
128 // Constructor from original and forked dialog tag
SIPTransaction(const SIPTransaction & original,const String & tag)129 SIPTransaction::SIPTransaction(const SIPTransaction& original, const String& tag)
130     : m_outgoing(true), m_invite(original.m_invite), m_transmit(false), m_state(Process),
131       m_response(original.m_response), m_transCount(original.m_transCount),
132       m_timeouts(0), m_timeout(0),
133       m_firstMessage(original.m_firstMessage), m_lastMessage(0),
134       m_pending(0), m_engine(original.m_engine),
135       m_branch(original.m_branch), m_callid(original.m_callid), m_tag(tag),
136       m_private(0), m_autoChangeParty(original.m_autoChangeParty),
137       m_autoAck(original.m_autoAck), m_silent(original.m_silent), m_traceId(original.traceId())
138 {
139     if (m_firstMessage)
140 	m_firstMessage->ref();
141 
142 #ifdef SIP_PRESERVE_TRANSACTION_ORDER
143     // new transactions at the end, preserve "natural" order
144     m_engine->append(this);
145 #else
146     // put new transactions first - faster to match new messages
147     m_engine->insert(this);
148 #endif
149 }
150 
~SIPTransaction()151 SIPTransaction::~SIPTransaction()
152 {
153 #ifdef DEBUG
154     Debugger debug(DebugAll,"SIPTransaction::~SIPTransaction()"," [%p]",this);
155 #endif
156     setPendingEvent(0,true);
157     TelEngine::destruct(m_lastMessage);
158     TelEngine::destruct(m_firstMessage);
159 }
160 
destroyed()161 void SIPTransaction::destroyed()
162 {
163     DDebug(getEngine(),DebugAll,"SIPTransaction::destroyed() [%p]",this);
164     m_state = Invalid;
165     m_engine->remove(this);
166     setPendingEvent(0,true);
167 }
168 
stateName(int state)169 const char* SIPTransaction::stateName(int state)
170 {
171     switch (state) {
172 	case Invalid:
173 	    return "Invalid";
174 	case Initial:
175 	    return "Initial";
176 	case Trying:
177 	    return "Trying";
178 	case Process:
179 	    return "Process";
180 	case Retrans:
181 	    return "Retrans";
182 	case Finish:
183 	    return "Finish";
184 	case Cleared:
185 	    return "Cleared";
186 	default:
187 	    return "Undefined";
188     }
189 }
190 
changeState(int newstate)191 bool SIPTransaction::changeState(int newstate)
192 {
193     if ((newstate < 0) || (newstate == m_state))
194 	return false;
195     if (m_state == Invalid) {
196 	TraceDebugObj(this,getEngine(),DebugWarn,"SIPTransaction is already invalid [%p]",this);
197 	return false;
198     }
199     DDebug(getEngine(),DebugAll,"SIPTransaction state changed from %s to %s [%p]",
200 	stateName(m_state),stateName(newstate),this);
201     m_state = newstate;
202     return true;
203 }
204 
setDialogTag(const char * tag)205 void SIPTransaction::setDialogTag(const char* tag)
206 {
207     if (null(tag)) {
208 	if (m_tag.null())
209 	    m_tag = (int)Random::random();
210     }
211     else
212 	m_tag = tag;
213 }
214 
setLatestMessage(SIPMessage * message)215 void SIPTransaction::setLatestMessage(SIPMessage* message)
216 {
217     if (m_lastMessage == message)
218 	return;
219     DDebug(getEngine(),DebugAll,"SIPTransaction latest message changing from %p %d to %p %d [%p]",
220 	m_lastMessage, m_lastMessage ? m_lastMessage->code : 0,
221 	message, message ? message->code : 0, this);
222     if (m_lastMessage)
223 	m_lastMessage->deref();
224     m_lastMessage = message;
225     if (m_lastMessage) {
226 	m_lastMessage->ref();
227 	if (message->isAnswer()) {
228 	    m_response = message->code;
229 	    if ((m_response > 100) && ((m_response < 300)
230 		    || !(m_engine->flags() & SIPMessage::NoTagFailure)))
231 		setDialogTag();
232 	}
233 	message->complete(m_engine,0,0,m_tag);
234     }
235 }
236 
setPendingEvent(SIPEvent * event,bool replace)237 void SIPTransaction::setPendingEvent(SIPEvent* event, bool replace)
238 {
239     if (m_pending)
240 	if (replace) {
241 	    delete m_pending;
242 	    m_pending = event;
243 	}
244 	else
245 	    delete event;
246     else
247 	m_pending = event;
248 }
249 
setTransCount(int count)250 void SIPTransaction::setTransCount(int count)
251 {
252     if (count < 0)
253 	return;
254     else if (count < 2)
255 	m_transCount = 2;
256     else if (count > 10)
257 	m_transCount = 10;
258     else
259 	m_transCount = count;
260 }
261 
setTimeout(u_int64_t delay,unsigned int count)262 void SIPTransaction::setTimeout(u_int64_t delay, unsigned int count)
263 {
264     m_timeouts = count;
265     m_delay = delay;
266     m_timeout = (count && delay) ? Time::now() + delay : 0;
267 #ifdef DEBUG
268     if (m_timeout)
269 	TraceDebugObj(this,getEngine(),DebugAll,"SIPTransaction new %d timeouts initially " FMT64U " usec apart [%p]",
270 	    m_timeouts,m_delay,this);
271 #endif
272 }
273 
getEvent(bool pendingOnly,u_int64_t time)274 SIPEvent* SIPTransaction::getEvent(bool pendingOnly, u_int64_t time)
275 {
276     SIPEvent *e = 0;
277 
278     if (m_pending) {
279 	if (m_silent)
280 	    delete m_pending;
281 	else
282 	    e = m_pending;
283 	m_pending = 0;
284 	return e;
285     }
286 
287     if (m_transmit) {
288 	m_transmit = false;
289 	if (m_silent)
290 	    return 0;
291 	return new SIPEvent(m_lastMessage ? m_lastMessage : m_firstMessage,this);
292     }
293 
294     if (pendingOnly)
295 	return 0;
296 
297     int timeout = -1;
298     if (m_timeout) {
299 	if (!time)
300 	    time = Time::now();
301 	if (time >= m_timeout) {
302 	    timeout = --m_timeouts;
303 	    m_delay *= 2; // exponential back-off
304 	    m_timeout = (m_timeouts) ? time + m_delay : 0;
305 	    DDebug(getEngine(),DebugAll,"SIPTransaction fired timer #%d [%p]",timeout,this);
306 	}
307     }
308 
309     e = isOutgoing() ? getClientEvent(m_state,timeout) : getServerEvent(m_state,timeout);
310     if (e) {
311 	if (!m_silent)
312 	    return e;
313 	delete e;
314 	return 0;
315     }
316 
317     // do some common default processing
318     switch (m_state) {
319 	case Retrans:
320 	    if (timeout < 0)
321 		break;
322 	    if (timeout && m_lastMessage && !m_silent)
323 		e = new SIPEvent(m_lastMessage,this);
324 	    // fall through because we recheck the timeout
325 	case Finish:
326 	    if (timeout)
327 		break;
328 	    changeState(Cleared);
329 	    // fall through so we don't wait another turn for processing
330 	case Cleared:
331 	    setTimeout();
332 	    if (!m_silent)
333 		e = new SIPEvent(m_firstMessage,this);
334 	    else
335 		e = new SIPEvent(0,this);
336 	    // make sure we don't get trough this one again
337 	    changeState(Invalid);
338 	    return e;
339 	case Invalid:
340 	    TraceDebugObj(this,getEngine(),DebugFail,"SIPTransaction::getEvent in invalid state [%p]",this);
341 	    break;
342     }
343     return e;
344 }
345 
setResponse(SIPMessage * message)346 void SIPTransaction::setResponse(SIPMessage* message)
347 {
348     if (m_outgoing) {
349 	TraceDebugObj(this,getEngine(),DebugWarn,"SIPTransaction::setResponse(%p) in client mode [%p]",message,this);
350 	return;
351     }
352     Lock lock(m_engine);
353     setLatestMessage(message);
354     setTransmit();
355     if (message && (message->code >= 200)) {
356 	if (isInvite()) {
357 	    // we need to actively retransmit this message
358 	    // RFC3261 17.2.1: non 2xx are not retransmitted on reliable transports
359 	    if (changeState(Retrans)) {
360 		bool reliable = message->getParty() && message->getParty()->isReliable();
361 		bool retrans = !reliable || message->code < 300;
362 		setTimeout(m_engine->getTimer(retrans ? 'G' : 'H',reliable),
363 		    retrans ? getTransCount() : 1);
364 	    }
365 	}
366 	else {
367 	    // just wait and reply to retransmits
368 	    if (changeState(Finish))
369 		setTimeout(m_engine->getTimer('J'));
370 	}
371     }
372     // extend timeout for provisional messages, use proxy timeout (maximum)
373     else if (message && (message->code > 100))
374 	setTimeout(m_engine->getTimer('C'));
375 }
376 
setResponse() const377 bool SIPTransaction::setResponse() const
378 {
379     if (m_outgoing)
380 	return false;
381     switch (m_state) {
382 	case Initial:
383 	case Trying:
384 	case Process:
385 	    return true;
386     }
387     return false;
388 }
389 
setResponse(int code,const char * reason)390 bool SIPTransaction::setResponse(int code, const char* reason)
391 {
392     if (m_outgoing) {
393 	TraceDebugObj(this,getEngine(),DebugWarn,"SIPTransaction::setResponse(%d,'%s') in client mode [%p]",code,reason,this);
394 	return false;
395     }
396     if (!setResponse()) {
397 	DDebug(getEngine(),DebugInfo,"SIPTransaction ignoring setResponse(%d) in state %s [%p]",
398 	    code,stateName(m_state),this);
399 	return false;
400     }
401     if (!reason)
402 	reason = lookup(code,SIPResponses,"Unknown Reason Code");
403     SIPMessage* msg = new SIPMessage(m_firstMessage, code, reason);
404     setResponse(msg);
405     msg->deref();
406     return true;
407 }
408 
setAcknowledge(MimeBody * ackBody)409 bool SIPTransaction::setAcknowledge(MimeBody* ackBody)
410 {
411     if (!(m_outgoing && m_lastMessage && m_lastMessage->isAnswer()
412 	    && ((Process == m_state) || (Retrans == m_state)))) {
413 	TelEngine::destruct(ackBody);
414 	return false;
415     }
416     m_autoAck = true;
417     // build and send the ACK
418     SIPMessage* m = new SIPMessage(m_firstMessage,m_lastMessage);
419     if (m_autoChangeParty && m_lastMessage->getParty())
420 	m->setParty(m_lastMessage->getParty());
421     m->setBody(ackBody);
422     setLatestMessage(m);
423     m_lastMessage->deref();
424     setTransmit();
425     if (changeState(Finish)) {
426 	setTimeout(m_engine->getTimer('H'));
427 	return true;
428     }
429     return false;
430 }
431 
requestAuth(const String & realm,const String & domain,bool stale,bool proxy)432 void SIPTransaction::requestAuth(const String& realm, const String& domain, bool stale, bool proxy)
433 {
434     if (m_outgoing) {
435 	TraceDebugObj(this,getEngine(),DebugWarn,"SIPTransaction::requestAuth() in client mode [%p]",this);
436 	return;
437     }
438     switch (m_state) {
439 	case Invalid:
440 	case Retrans:
441 	case Finish:
442 	case Cleared:
443 	    DDebug(getEngine(),DebugInfo,"SIPTransaction ignoring requestAuth() in state %s [%p]",
444 		stateName(m_state),this);
445 	    return;
446     }
447     int code = proxy ? 407 : 401;
448     const char* hdr = proxy ? "Proxy-Authenticate" : "WWW-Authenticate";
449     SIPMessage* msg = new SIPMessage(m_firstMessage, code, lookup(code,SIPResponses));
450     if (realm) {
451 	String tmp;
452 	tmp << "Digest realm=" << MimeHeaderLine::quote(realm);
453 	MimeHeaderLine* line = new MimeHeaderLine(hdr,tmp,',');
454 	if (domain)
455 	    line->setParam(" domain",MimeHeaderLine::quote(domain));
456 	m_engine->nonceGet(tmp);
457 	line->setParam(" nonce",MimeHeaderLine::quote(tmp));
458 	line->setParam(" stale",stale ? "TRUE" : "FALSE");
459 	line->setParam(" algorithm","MD5");
460 	msg->addHeader(line);
461     }
462     setResponse(msg);
463     msg->deref();
464 }
465 
authUser(String & user,bool proxy,GenObject * userData)466 int SIPTransaction::authUser(String& user, bool proxy, GenObject* userData)
467 {
468     if (!(m_engine && m_firstMessage))
469 	return -1;
470     return m_engine->authUser(m_firstMessage, user, proxy, userData);
471 }
472 
processMessage(SIPMessage * message,const String & branch)473 SIPTransaction::Processed SIPTransaction::processMessage(SIPMessage* message, const String& branch)
474 {
475     if (!(message && m_firstMessage))
476 	return NoMatch;
477     XDebug(getEngine(),DebugAll,"SIPTransaction::processMessage(%p,'%s') [%p]",
478 	message,branch.c_str(),this);
479     if (branch) {
480 	if (branch != m_branch) {
481 	    // different branch is allowed only for ACK in incoming INVITE...
482 	    if (!(isInvite() && isIncoming() && message->isACK()))
483 		return NoMatch;
484 	    // ...and if also matches the CSeq, Call-ID and To: tag
485 	    if ((m_firstMessage->getCSeq() != message->getCSeq()) ||
486 		(getCallID() != message->getHeaderValue("Call-ID")) ||
487 		(getDialogTag() != message->getParamValue("To","tag")))
488 		return NoMatch;
489 	    // ...and only if we sent a 200 response...
490 	    if (!m_lastMessage || ((m_lastMessage->code / 100) != 2))
491 #ifdef SIP_STRICT
492 		return NoMatch;
493 #else
494 		TraceDebugObj(this,getEngine(),DebugNote,"Received non-branch ACK to non-2xx response! (sender bug)");
495 #endif
496 	    DDebug(getEngine(),DebugAll,"SIPTransaction found non-branch ACK response to our 2xx");
497 	}
498 	else if (getMethod() != message->method) {
499 	    if (!(isIncoming() && isInvite() && message->isACK()))
500 		return NoMatch;
501 	    if (!m_lastMessage || ((m_lastMessage->code / 100) == 2))
502 #ifdef SIP_STRICT
503 		return NoMatch;
504 #else
505 		TraceDebugObj(this,getEngine(),DebugNote,"Received branch ACK to 2xx response! (sender bug)");
506 #endif
507 	}
508     }
509     else {
510 	if (getMethod() != message->method) {
511 	    if (!(isIncoming() && isInvite() && message->isACK()))
512 		return NoMatch;
513 	}
514 	if ((m_firstMessage->getCSeq() != message->getCSeq()) ||
515 	    (getCallID() != message->getHeaderValue("Call-ID")) ||
516 	    (m_firstMessage->getHeaderValue("From") != message->getHeaderValue("From")) ||
517 	    (m_firstMessage->getHeaderValue("To") != message->getHeaderValue("To")))
518 	    return NoMatch;
519 	// allow braindamaged UAs that send answers with no Via line
520 	if (m_firstMessage->getHeader("Via") && message->getHeader("Via") &&
521 	    (m_firstMessage->getHeaderValue("Via",true) != message->getHeaderValue("Via",true)))
522 	    return NoMatch;
523 	// extra checks are to be made for ACK only
524 	if (message->isACK()) {
525 	    if (getDialogTag() != message->getParamValue("To","tag"))
526 		return NoMatch;
527 	    // use a while so we can either break or return
528 	    while (getURI() != message->uri) {
529 #ifndef SIP_STRICT
530 		// hack to match URIs with lost tags. Cisco sucks. Period.
531 		String tmp = getURI();
532 		int sc = tmp.find(';');
533 		if (sc > 0) {
534 		    tmp.assign(tmp,sc);
535 		    if (tmp == message->uri) {
536 			TraceDebugObj(this,getEngine(),DebugMild,"Received no-branch ACK with lost URI tags! (sender bug)");
537 			break;
538 		    }
539 		}
540 		// now try to match only the user part - Cisco strikes again...
541 		sc = tmp.find('@');
542 		if (sc > 0) {
543 		    tmp.assign(tmp,sc);
544 		    sc = message->uri.find('@');
545 		    if ((sc > 0) && (tmp == message->uri.substr(0,sc))) {
546 			TraceDebugObj(this,getEngine(),DebugMild,"Received no-branch ACK with only user matching! (sender bug)");
547 			break;
548 		    }
549 		}
550 #endif
551 		return NoMatch;
552 	    }
553 	}
554     }
555     if (!message->getParty())
556 	message->setParty(m_firstMessage->getParty());
557     if (isOutgoing() != message->isAnswer()) {
558 	DDebug(getEngine(),DebugAll,"SIPTransaction ignoring retransmitted %s %p '%s' in [%p]",
559 	    message->isAnswer() ? "answer" : "request",
560 	    message,message->method.c_str(),this);
561 	return NoMatch;
562     }
563     DDebug(getEngine(),DebugAll,"SIPTransaction processing %s %p '%s' %d in [%p]",
564 	message->isAnswer() ? "answer" : "request",
565 	message,message->method.c_str(),message->code,this);
566 
567     if (message->isAnswer()) {
568 	const NamedString* ns = message->getParam("To","tag");
569 	if (m_tag.null()) {
570 	    if (ns) {
571 		if (message->code > 100) {
572 		    // establish the dialog
573 		    m_tag = *ns;
574 		    DDebug(getEngine(),DebugInfo,"SIPTransaction found dialog tag '%s' [%p]",
575 			m_tag.c_str(),this);
576 		}
577 		else
578 		    TraceDebugObj(this,getEngine(),DebugMild,"Received To tag in 100 answer! (sender bug)");
579 	    }
580 	}
581 	else if (!ns) {
582 	    // we have a dialog and the message has not - ignore it
583 	    // as we would be unable to CANCEL it anyway
584 	    return NoMatch;
585 	}
586 	else if (m_tag != *ns) {
587 	    // we have a dialog established and this message is out of it
588 	    if (!isInvite())
589 		return NoMatch;
590 	    if (message->code < 400)
591 		// for 1/2/3xx answers to INVITE discriminate forked for later processing
592 		return NoDialog;
593 	    // we must answer any 4/5/6xx - and we're supposed to receive only one
594 	    DDebug(getEngine(),DebugInfo,"SIPTransaction changing dialog tag '%s' -> '%s' in %u answer [%p]",
595 		m_tag.c_str(),ns->c_str(),message->code,this);
596 	    m_tag = *ns;
597 	}
598     }
599 
600     processMessage(message);
601     return Matched;
602 }
603 
processMessage(SIPMessage * message)604 void SIPTransaction::processMessage(SIPMessage* message)
605 {
606     message->msgTraceId = m_traceId;
607     if (!message->isOutgoing())
608 	getEngine()->traceMsg(message,true);
609     if (isOutgoing())
610 	processClientMessage(message,m_state);
611     else
612 	processServerMessage(message,m_state);
613 }
614 
processClientMessage(SIPMessage * message,int state)615 void SIPTransaction::processClientMessage(SIPMessage* message, int state)
616 {
617     bool final = message->code >= 200;
618     switch (state) {
619 	case Trying:
620 	    setTimeout(m_engine->getTimer(isInvite() ? 'B' : 'F'));
621 	    changeState(Process);
622 	    m_response = message->code;
623 	    if (m_response == 100)
624 		break;
625 	    // fall trough for non-100 answers
626 	case Process:
627 	    if (message->code <= 100)
628 		break;
629 	    setLatestMessage(message);
630 	    if (tryAutoAuth(message))
631 		break;
632 	    if (m_invite && !final)
633 		// use the human interaction timeout in INVITEs
634 		setTimeout(m_engine->getUserTimeout());
635 	    m_response = message->code;
636 	    setPendingEvent(new SIPEvent(message,this),final);
637 	    if (final) {
638 		setTimeout();
639 		if (isInvite()) {
640 		    if ((message->code / 100) != 2)
641 			m_autoAck = true;
642 		    if (m_autoAck)
643 			setAcknowledge();
644 		    else
645 			changeState(Retrans);
646 		}
647 		else
648 		    changeState(Cleared);
649 	    }
650 	    break;
651 	case Finish:
652 	    if (m_lastMessage && m_lastMessage->isACK() && final)
653 		setTransmit();
654 	    break;
655     }
656 }
657 
getClientEvent(int state,int timeout)658 SIPEvent* SIPTransaction::getClientEvent(int state, int timeout)
659 {
660     SIPEvent *e = 0;
661     switch (state) {
662 	case Initial:
663 	    e = new SIPEvent(m_firstMessage,this);
664 	    if (changeState(Trying)) {
665 		bool reliable = e->getParty() && e->getParty()->isReliable();
666 		if (!reliable)
667 		    setTimeout(m_engine->getTimer(isInvite() ? 'A' : 'E'),getTransCount());
668 		else
669 		    setTimeout(m_engine->getTimer(isInvite() ? 'B' : 'F',true),1);
670 	    }
671 	    break;
672 	case Trying:
673 	    if (timeout < 0)
674 		break;
675 	    if (timeout)
676 		setTransmit();
677 	    else {
678 		m_response = 408;
679 		changeState(Cleared);
680 	    }
681 	    break;
682 	case Process:
683 	    if (timeout == 0) {
684 		m_response = 408;
685 		changeState(Cleared);
686 	    }
687 	    break;
688     }
689     return e;
690 }
691 
processServerMessage(SIPMessage * message,int state)692 void SIPTransaction::processServerMessage(SIPMessage* message, int state)
693 {
694     switch (state) {
695 	case Trying:
696 	case Process:
697 	    setTransmit();
698 	    break;
699 	case Finish:
700 	case Retrans:
701 	    if (message->isACK()) {
702 		setTimeout();
703 		setPendingEvent(new SIPEvent(message,this));
704 		changeState(Cleared);
705 	    }
706 	    else
707 		setTransmit();
708 	    break;
709     }
710 }
711 
getServerEvent(int state,int timeout)712 SIPEvent* SIPTransaction::getServerEvent(int state, int timeout)
713 {
714     SIPEvent *e = 0;
715     switch (state) {
716 	case Initial:
717 	    if (!( (m_firstMessage->getCSeq() >= 0) &&
718 		m_firstMessage->getHeader("Call-ID") &&
719 		m_firstMessage->getHeader("From") &&
720 		m_firstMessage->getHeader("To") ))
721 		setResponse(400);
722 	    else if (!m_engine->isAllowed(m_firstMessage->method))
723 		setResponse(501);
724 	    else {
725 		setResponse(100);
726 		// if engine is set up lazy skip first 100 transmission
727 		if (!isInvite() && m_engine && m_engine->lazyTrying())
728 		    m_transmit = false;
729 		changeState(Trying);
730 		break;
731 	    }
732 	    e = new SIPEvent(m_lastMessage,this);
733 	    m_transmit = false;
734 	    changeState(Invalid);
735 	    break;
736 	case Trying:
737 	    e = new SIPEvent(m_firstMessage,this);
738 	    changeState(Process);
739 	    // the absolute maximum timeout as we have to accomodate proxies
740 	    setTimeout(m_engine->getTimer('C'));
741 	    break;
742 	case Process:
743 	    if (timeout < 0)
744 		break;
745 	    if (timeout && m_lastMessage)
746 		e = new SIPEvent(m_lastMessage,this);
747 	    if (timeout)
748 		break;
749 	    setResponse(408);
750 	    e = new SIPEvent(m_lastMessage,this);
751 	    break;
752 	case Retrans:
753 	    if (isInvite() && (timeout == 0)) {
754 		// we didn't got an ACK so declare timeout
755 		m_response = 408;
756 		changeState(Cleared);
757 	    }
758 	    break;
759     }
760     return e;
761 }
762 
763 // Event transmission failed notification
msgTransmitFailed(SIPMessage * msg)764 void SIPTransaction::msgTransmitFailed(SIPMessage* msg)
765 {
766     if (!msg)
767 	return;
768     Lock lock(getEngine());
769     DDebug(getEngine(),DebugNote,
770 	"SIPTransaction send failed state=%s msg=%p first=%p last=%p [%p]",
771 	stateName(m_state),msg,m_firstMessage,m_lastMessage,this);
772     // Do nothing in termination states
773     if (m_state == Invalid || m_state == Finish || m_state == Cleared)
774 	return;
775     if (isOutgoing()) {
776 	if (m_state == Trying) {
777 	    if (msg != m_firstMessage)
778 		return;
779 	    // Reliable transport: terminate now
780 	    // Non reliable: terminate if this is the last attempt
781 	    if ((msg->getParty() && msg->getParty()->isReliable()) ||
782 		    m_timeouts >= getTransCount()) {
783 		TraceDebugObj(this,getEngine(),DebugInfo,
784 		    "SIPTransaction send failed state=%s: clearing [%p]",
785 		    stateName(m_state),this);
786 		m_response = 500;
787 		changeState(Cleared);
788 		return;
789 	    }
790 	}
791 	else if (m_state == Initial || msg != m_lastMessage)
792 	    return;
793     }
794     else {
795 	// Incoming
796 	if (msg != m_lastMessage)
797 	    return;
798     }
799     // Avoid party retry
800     TraceDebugObj(this,getEngine(),DebugAll,
801 	"SIPTransaction send failed state=%s resetting msg %p party [%p]",
802 	stateName(m_state),msg,this);
803     msg->setParty();
804 }
805 
tryAutoAuth(SIPMessage * answer)806 bool SIPTransaction::tryAutoAuth(SIPMessage* answer)
807 {
808     if ((answer->code != 401) && (answer->code != 407))
809 	return false;
810     if (m_firstMessage->getAuthUsername().null())
811 	return false;
812     setTimeout();
813     SIPTransaction* tr = new SIPTransaction(*this,answer);
814     changeState(Initial);
815     tr->processClientMessage(answer,Process);
816     return true;
817 }
818 
setSilent()819 void SIPTransaction::setSilent()
820 {
821     m_silent = true;
822     DDebug(getEngine(),DebugAll,"SIPTransaction silenced in state=%s [%p]",stateName(m_state),this);
823 }
824 
825 /* vi: set ts=8 sw=4 sts=4 noet: */
826