reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
RequestContext.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5#include <iostream>
6#include <utility>
7
8#include "repro/Proxy.hxx"
16#include "rutil/Inserter.hxx"
17#include "rutil/Logger.hxx"
18
23
24// Remove warning about 'this' use in initiator list
25#if defined(WIN32) && !defined(__GNUC__)
26#pragma warning( disable : 4355 ) // using this in base member initializer list
27#endif
28
29#define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
30
31using namespace resip;
32using namespace repro;
33using namespace std;
34
36 ProcessorChain& requestP,
37 ProcessorChain& responseP,
38 ProcessorChain& targetP) :
39 mHaveSentFinalResponse(false),
40 mOriginalRequest(0),
41 mCurrentEvent(0),
42 mAck200ToRetransmit(0),
43 mRequestProcessorChain(requestP),
44 mResponseProcessorChain(responseP),
45 mTargetProcessorChain(targetP),
46 mTransactionCount(1),
47 mProxy(proxy),
48 mTopRouteFlowTupleSet(false),
49 mResponseContext(new ResponseContext(*this)),
50 mSessionCreatedEventSent(false),
51 mSessionEstablishedEventSent(false),
52 mKeyValueStore(*Proxy::getRequestKeyValueStoreKeyAllocator())
53{
54}
55
57{
58 DebugLog (<< "RequestContext::~RequestContext() " << this);
60 {
61 delete mOriginalRequest;
63 }
64 delete mCurrentEvent;
65 mCurrentEvent = 0;
68}
69
70
71void
73{
74 InfoLog (<< "RequestContext::process(TransactionTerminated) "
75 << msg.getTransactionId() << " : " << *this);
76
77 if (msg.isClientTransaction())
78 {
79 mResponseContext->removeClientTransaction(msg.getTransactionId());
80 }
82 if (mTransactionCount == 0)
83 {
84 delete this;
85 }
86}
87
88void
89RequestContext::process(std::unique_ptr<resip::SipMessage> sipMessage)
90{
91 bool original = false;
92 InfoLog (<< "RequestContext::process(SipMessage) " << sipMessage->getTransactionId());
93
95 {
96 delete mCurrentEvent;
97 }
98 mCurrentEvent = sipMessage.release();
99
100 SipMessage* sip = dynamic_cast<SipMessage*>(mCurrentEvent);
101 if (!mOriginalRequest)
102 {
103 resip_assert(sip);
105 original = true;
109
110 // RFC 3261 Section 16.4
111 try
112 {
115 }
116 catch(resip::ParseException& e)
117 {
118 InfoLog(<<"Parse failure Exception caught: " << e);
119 if(mOriginalRequest->method()==ACK)
120 {
122 }
123 else
124 {
125 resip::SipMessage response;
126 Helper::makeResponse(response, *mOriginalRequest,400);
127 response.header(h_StatusLine).reason()="Malformed header-field-value: " + e.getMessage();
128 sendResponse(response);
129 }
130 return;
131 }
132 catch(resip::BaseException& e)
133 {
134 ErrLog(<<"Exception caught: " << e);
135 if(mOriginalRequest->method()==ACK)
136 {
138 }
139 else
140 {
141 resip::SipMessage response;
142 Helper::makeResponse(response, *mOriginalRequest,500);
143 response.header(h_StatusLine).reason()="Server error: " + e.getMessage();
144 sendResponse(response);
145 }
146 return;
147 }
148 }
149
150 if (sip->isRequest())
151 {
152 DebugLog(<<"Got a request.");
153 bool postProcess=false;
154
155 Uri& requestUri = sip->header(h_RequestLine).uri();
156 if(requestUri.exists(resip::p_wsSrcIp) &&
157 requestUri.exists(resip::p_wsSrcPort) &&
158 !isWebSocket(sip->getSource().getType()))
159 {
160 requestUri.host() = requestUri.param(resip::p_wsSrcIp);
161 requestUri.remove(resip::p_wsSrcIp);
162 requestUri.port() = requestUri.param(resip::p_wsSrcPort);
163 requestUri.remove(resip::p_wsSrcPort);
164 requestUri.param(resip::p_transport) = "WS";
165 DebugLog(<< "recognised request for WS peer, setting forceTarget to " << requestUri);
166 sip->setForceTarget(requestUri);
167 }
168
169 switch(mOriginalRequest->method())
170 {
171 case ACK:
172 processRequestAckTransaction(sip,original);
173 break;
174 case INVITE:
175 postProcess=processRequestInviteTransaction(sip,original);
176 if(postProcess) doPostRequestProcessing(sip,original);
177 break;
178 default:
179 postProcess=processRequestNonInviteTransaction(sip,original);
180 if(postProcess) doPostRequestProcessing(sip,original);
181 }
182 }
183 else if (sip->isResponse())
184 {
185 resip_assert(!original);
186 bool postProcess=false;
187 switch(mOriginalRequest->method())
188 {
189 case ACK:
190 // !bwc! Got a response to an ACK?
191 // Why did the stack let this through?
192 resip_assert(0);
193 break;
194 case INVITE:
195 postProcess=processResponseInviteTransaction(sip);
196 break;
197 default:
199 }
200
201 if(postProcess)
202 {
204 }
205 }
206}
207
208bool
210{
211 bool doPostProcess=false;
212 resip_assert(msg->isRequest());
213
214 if(original)
215 {
216 resip_assert(msg->method()==INVITE);
217
218 try
219 {
221 ret = mRequestProcessorChain.process(*this);
223 {
224 doPostProcess=true;
225 }
226 }
227 catch(resip::BaseException& e)
228 {
229 SipMessage response;
231 response.header(h_StatusLine).reason()="Server error: " + e.getMessage();
232 ErrLog(<<"Exception caught: " << e);
233 sendResponse(response);
234 }
235 }
236 else
237 {
238 if(msg->method()==CANCEL)
239 {
241 {
242 getProxy().doSessionAccounting(*msg, true /* received */, *this);
243 }
244 mResponseContext->processCancel(*msg);
245 doPostProcess=true;
246 }
247 else if(msg->method()==ACK)
248 {
249 // .bwc. The stack should not be forwarding ACK/failure to the TU,
250 // nor should we be getting a bad ACK/200. (There is code further
251 // up that makes bad ACK/200 look like a new transaction, like it
252 // is supposed to be.)
253 // TODO Remove this code block entirely.
254 resip_assert(0);
255
256 DebugLog(<<"This ACK has the same tid as the original INVITE.");
257 DebugLog(<<"The reponse we sent back was a "
258 << mResponseContext->mBestResponse.header(h_StatusLine).statusCode());
259 // .bwc. Since this is not an ACK transaction, the stack will let
260 // us know when we need to clean up.
262 {
263 // .bwc. Whoa, something went wrong here. We got an ACK, but we
264 // haven't sent back a final response. The stack shouldn't have
265 // allowed this through!
266 ErrLog(<<"Got an ACK, but haven't sent a final response. "
267 "What happened here?");
268 }
269 else if(mResponseContext->mBestResponse.header(h_StatusLine).statusCode() / 100 == 2)
270 {
271 InfoLog(<<"Got an ACK within an INVITE transaction, but our "
272 "response was a 2xx. Someone didn't change their tid "
273 "like they were supposed to...");
274 if((msg->exists(h_Routes) && !msg->header(h_Routes).empty()) || // If ACK/200 has a Route header OR
275 (!getProxy().isMyUri(msg->header(h_RequestLine).uri()) && // RequestUri is not us and From Uri is our domain
276 (msg->header(h_From).isWellFormed() && getProxy().isMyUri(msg->header(h_From).uri()))))
277 {
278 forwardAck200(*msg);
279 }
280 }
281 }
282 else
283 {
284 // .bwc. The stack should not have done this. This indicates either a
285 // bug in the stack, processInvite was called in a non-invite
286 // RequestContext, or this RequestContext was leaked and hit with a
287 // subsequent transaction
288 ErrLog(<<"We got an unexpected request from "
289 "the stack in an invite RequestContext. "
290 "Why?"
291 " Orig: " << mOriginalRequest->brief() <<
292 " This: " << msg->brief());
293 resip_assert(0);
294 }
295 }
296
297 return doPostProcess;
298
299}
300
301bool
303{
304 resip_assert(msg->isRequest());
305 bool doPostProcess=false;
306
307 if(original)
308 {
310 try
311 {
313 ret = mRequestProcessorChain.process(*this);
315 {
316 doPostProcess=true;
317 }
318 }
319 catch(resip::BaseException& e)
320 {
321 SipMessage response;
323 response.header(h_StatusLine).reason()="Server error: " + e.getMessage();
324 ErrLog(<<"Exception caught: " << e);
325 sendResponse(response);
326 }
327 }
328 else
329 {
330 if(msg->method()==CANCEL)
331 {
332 // .bwc. Got a CANCEL in a non-invite transaction. Just respond with
333 // 200 and ignore.
334 SipMessage response;
335 Helper::makeResponse(response,*msg,200);
336 send(response);
337 }
338 else
339 {
340 // ?bwc? We got a second request from the stack. Why?
341 ErrLog(<<"We got a second non-invite request from the"
342 " stack in an already-established non-"
343 "invite RequestContext. "
344 "Why?"
345 " Orig: " << mOriginalRequest->brief() <<
346 " This: " << msg->brief());
347 if(msg->method()!=ACK)
348 {
349 SipMessage response;
350 Helper::makeResponse(response,*msg,500);
351 response.header(h_StatusLine).reason()="Server error: got an "
352 "unexpected request in a non-invite RequestContext";
353 send(response);
354 }
355 resip_assert(0);
356 }
357 }
358
359 return doPostProcess;
360}
361
362void
364{
365 resip_assert(msg->isRequest());
366 if(msg->method() != ACK)
367 {
368 // !bwc! Somebody collided with an ACK/200. Send a failure response.
369 SipMessage response;
370 Helper::makeResponse(response,*msg,400);
371 response.header(h_StatusLine).reason() = "Transaction-id collision";
372 send(response);
373 return;
374 }
375
376 DebugLog(<<"This ACK has its own tid.");
377
378 try
379 {
380 // .slg. look at mOriginalRequest for Routes since removeTopRouteIfSelf() is only called on mOriginalRequest
381 if(!mTopRouteFlowTupleSet && // If we have a flow token in top route, then we don't need to route with RequestUri (so don't consider self aimed)
382 (!mOriginalRequest->exists(h_Routes) || mOriginalRequest->header(h_Routes).empty()) &&
383 getProxy().isMyUri(msg->header(h_RequestLine).uri()))
384 {
385 // .bwc. Someone sent an ACK with us in the Request-Uri, and no
386 // Route headers (after we have removed ourself). We will never perform
387 // location service or retargeting on an ACK, and we shouldn't send
388 // it to ourselves. So, just drop the thing.
390 }
391 // Note: mTopRoute is only populated if RemoveTopRouteIfSelf successfully removes the top route.
392 else if(msg->hasForceTarget() || !mTopRoute.uri().host().empty() || getProxy().isMyUri(msg->header(h_From).uri()))
393 {
394 // Top most route is us, or From header uri is ours. Note: The From check is
395 // required to interoperate with endpoints that configure outbound proxy
396 // settings, and do not place the outbound proxy in a Route header.
397 mResponseContext->cancelAllClientTransactions();
399 }
400 else
401 {
402 // .slg. Someone is using us to relay an ACK, but we are not the
403 // top-most route and the host in From isn't ours. Refusing to do so.
404 InfoLog(<<"Top most route or From header are not ours. We do not allow relaying ACKs. Dropping it...");
405 }
406 }
408 {
409 InfoLog(<<"Parse error processing ACK. Dropping it...");
410 }
411
412 if(original) // Only queue Ack200Done if this is the original request
413 {
415 }
416}
417
418void
420{
421 resip_assert(msg->isRequest());
422
423 // .bwc. This is called after an incoming request is done processing. This
424 // IS NOT called if the request-processor chain goes async, and IS NOT called
425 // when async work finishes. The intent of this function is to prompt either:
426 // 1) The initiation of new client transactions.
427 // 2) Failing 1, the sending of a failure response to the original request.
428
429
430 // if target list is empty return a 480
431 if (!mResponseContext->hasTargets())
432 {
433 // make 480, send, dispose of memory
434 resip::SipMessage response;
435 InfoLog (<< *this << ": no targets for "
437 << " send 480");
438 Helper::makeResponse(response, *mOriginalRequest, 480);
439 sendResponse(response);
440 }
441 else
442 {
444 InfoLog (<< *this << " there are "
445 << mResponseContext->mCandidateTransactionMap.size()
446 << " candidates -> continue");
447
448 try
449 {
450 ret = mTargetProcessorChain.process(*this);
451 }
452 catch(resip::BaseException& e)
453 {
454 if(mResponseContext->hasActiveTransactions())
455 {
456 // .bwc. Whoops. We may have just forwarded garbage upstream.
457 // TODO is it appropriate to try to CANCEL here?
458 ErrLog(<<"Server error caught after"
459 " request was forwarded. Exception was: "<<e);
460 }
461 else
462 {
463 mResponseContext->clearCandidateTransactions();
464 SipMessage response;
466 response.header(h_StatusLine).reason()="Server error: " + e.getMessage();
467 ErrLog(<<"Exception caught: " << e);
468 sendResponse(response);
469 }
470 }
471
472 if(ret != Processor::WaitingForEvent &&
474 !mResponseContext->hasActiveTransactions())
475 {
476 if(mResponseContext->hasCandidateTransactions())
477 {
478 // Someone forgot to start any of the targets they just added.
479 // Send a 500 response
480 resip::SipMessage response;
481 ErrLog( << "In RequestContext, target processor chain appears "
482 << "to have failed to process any targets. (Bad baboon?)"
483 << "Sending a 500 response for this request:"
485 Helper::makeResponse(response, *mOriginalRequest, 500);
486 sendResponse(response);
487 }
488 else
489 {
490 ErrLog(<< "In RequestContext, request processor chain "
491 << " appears to have added Targets, but all of these Targets"
492 << " are already Terminated. Further, there are no candidate"
493 << " Targets. (Bad monkey?)");
494 // Send best response
495 mResponseContext->forwardBestResponse();
496 }
497 }
498 }
499}
500
501bool
503{
504 resip_assert(msg->isResponse());
505
506 bool doPostProcessing=false;
507 resip::Data tid(msg->getTransactionId());
508 tid.lowercase();
509 if(msg->method()==INVITE)
510 {
511 try
512 {
514 ret = mResponseProcessorChain.process(*this);
516
517 if (ret == Processor::Continue)
518 {
519 doPostProcessing=true;
520 }
521 else
522 {
523 // This means the response has been eaten. Do not forward back.
524 mResponseContext->terminateClientTransaction(tid);
525 }
526 }
527 catch(resip::ParseException& e)
528 {
529 InfoLog(<<"Garbage in response; dropping message. " << e);
530 mResponseContext->terminateClientTransaction(tid);
531 }
532 catch(resip::BaseException& e)
533 {
534 ErrLog(<<"Exception thrown in response processor chain: " << e);
535 // ?bwc? TODO what do we do here? Continue processing? Give up?
536 mResponseContext->terminateClientTransaction(tid);
537 }
538 }
539 else if(msg->method()==CANCEL)
540 {
541 // .bwc. Do nothing.
542 }
543 else
544 {
545 // ?bwc? Is this possible?
546 resip_assert(0);
547 }
548
549 return doPostProcessing;
550}
551
552bool
554{
555 resip_assert(msg->isResponse());
556
557 resip::Data tid(msg->getTransactionId());
558 tid.lowercase();
559 bool doPostProcessing=false;
560 if(msg->method()==mOriginalRequest->method())
561 {
562 try
563 {
565 ret = mResponseProcessorChain.process(*this);
567
568 if (ret == Processor::Continue)
569 {
570 doPostProcessing=true;
571 }
572 else
573 {
574 // This means the response has been eaten. Do not forward back.
575 mResponseContext->terminateClientTransaction(tid);
576 }
577 }
578 catch(resip::ParseException& e)
579 {
580 InfoLog(<<"Garbage in response; dropping message. " << e);
581 mResponseContext->terminateClientTransaction(tid);
582 }
583 catch(resip::BaseException& e)
584 {
585 ErrLog(<<"Exception thrown in response processor chain: " << e);
586 // ?bwc? TODO what do we do here? Continue processing? Give up?
587 mResponseContext->terminateClientTransaction(tid);
588 }
589 }
590 else
591 {
592 // ?bwc? Is this possible?
593 resip_assert(0);
594 }
595
596 return doPostProcessing;
597
598}
599
600void
602{
603 bool nit408 = msg->method() != INVITE && msg->header(resip::h_StatusLine).statusCode() == 408;
604
605 mResponseContext->processResponse(*msg);
606
607 //If everything we have tried so far has gone quiescent, we
608 //need to fire up some more Targets (if there are any left)
610
612 !mResponseContext->hasActiveTransactions())
613 {
614 if(mResponseContext->hasCandidateTransactions())
615 {
616 resip::SipMessage response;
617 Helper::makeResponse(response, *mOriginalRequest, 500);
618 // The last active transaction has ended, and the response processors
619 // did not start any of the pending transactions.
620 // Send a 500 response.
621 ErrLog( << "In RequestContext, after processing a sip response:"
622 << " We have no active transactions, but there are candidates "
623 << " remaining. (Bad baboon?)"
624 << "Sending a 500 response for this request:"
626 sendResponse(response);
627 }
628 else if(nit408)
629 {
630 InfoLog(<<"In RequestContext, after processing a NIT/408, all"
631 << " transactions are terminated. In this case, we do not send a"
632 << " final response.");
633 }
634 else
635 {
636 ErrLog(<<"In RequestContext, after processing "
637 << "a sip response (_not_ a NIT/408): all transactions are terminated,"
638 << " but we have not sent a final response. (What happened here?) ");
639
640 // Send best response if there is one - otherwise send 500
641 if(mResponseContext->mBestResponse.isResponse())
642 {
643 mResponseContext->forwardBestResponse();
644 }
645 else
646 {
647 resip::SipMessage response;
648 Helper::makeResponse(response, *mOriginalRequest, 500);
649 sendResponse(response);
650 }
651 }
652 }
653}
654
655void
656RequestContext::process(std::unique_ptr<ApplicationMessage> app)
657{
658 InfoLog (<< "RequestContext::process(ApplicationMessage) " << *app);
659
661 {
662 delete mCurrentEvent;
663 }
664 mCurrentEvent = app.release();
665
666 Ack200DoneMessage* ackDone = dynamic_cast<Ack200DoneMessage*>(mCurrentEvent);
667 if (ackDone)
668 {
669 delete this;
670 return;
671 }
672
673 TimerCMessage* tc = dynamic_cast<TimerCMessage*>(mCurrentEvent);
674
675 if(tc)
676 {
677 mResponseContext->processTimerC(tc->getTransactionId(), tc->mSerial);
678 return;
679 }
680
681 ProcessorMessage* proc=dynamic_cast<ProcessorMessage*>(mCurrentEvent);
682
683 if(proc)
684 {
685 Processor::ChainType type = proc->chainType();
687
688 switch(type)
689 {
691 try
692 {
693 ret = mRequestProcessorChain.process(*this);
694 }
695 catch(resip::BaseException& e)
696 {
697 resip::SipMessage response;
699 response.header(h_StatusLine).reason()="Server error: " + e.getMessage();
700 ErrLog(<<"Exception caught: " << e);
701 sendResponse(response);
702 }
703
705 {
706 if (!mResponseContext->hasTargets())
707 {
708 // make 480, send, dispose of memory
709 resip::SipMessage response;
710 Helper::makeResponse(response, *mOriginalRequest, 480);
711 InfoLog (<< *this << ": no targets for "
713 << " send 480");
714 sendResponse(response);
715 }
716 else
717 {
718 InfoLog (<< *this << " there are "
719 << mResponseContext->mCandidateTransactionMap.size()
720 << " candidates -> continue");
721
722 try
723 {
724 ret = mTargetProcessorChain.process(*this);
725 }
726 catch(resip::BaseException& e)
727 {
728 if(mResponseContext->hasActiveTransactions())
729 {
730 // .bwc. Whoops. We may have just forwarded garbage upstream.
731 // ?bwc? TODO is it appropriate to try to CANCEL here?
732 ErrLog(<<"Server error caught after"
733 " request was forwarded. Exception was: "<<e);
734 }
735 else
736 {
737 mResponseContext->clearCandidateTransactions();
738 resip::SipMessage response;
740 response.header(h_StatusLine).reason()="Server error: " + e.getMessage();
741 ErrLog(<<"Exception caught: " << e);
742 sendResponse(response);
743 }
744 }
745
746 if(ret != Processor::WaitingForEvent &&
748 !mResponseContext->hasActiveTransactions())
749 {
750 if(mResponseContext->hasCandidateTransactions())
751 {
752 resip::SipMessage response;
753 Helper::makeResponse(response, *mOriginalRequest, 500);
754 // Someone forgot to start any of the targets they just added.
755 // Send a 500 response
756 ErrLog( << "In RequestContext, request and target processor"
757 << " chains have run, and we have some Candidate Targets,"
758 << " but no active Targets. (Bad baboon?)"
759 << "Sending a 500 response for this request:"
761 sendResponse(response);
762 }
763 else if(mResponseContext->mBestResponse.header(h_StatusLine).statusCode() != 408)
764 {
765 ErrLog(<< "In RequestContext, request and target processor "
766 << "chains have run, and all Targets are now Terminated."
767 << " However, we have not sent a final response, and our "
768 << "best final response is not a 408.(What happened here?)");
769
770 // Send best response
771 mResponseContext->forwardBestResponse();
772 }
773 }
774 }
775 }
776 break;
777
779 ret = mResponseProcessorChain.process(*this);
780
782 break;
783
785 ret = mTargetProcessorChain.process(*this);
786 break;
787
788 default:
789 ErrLog(<<"RequestContext " << getTransactionId() << " got a "
790 << "ProcessorMessage addressed to a non existent chain "
791 << type);
792 }
793 }
794}
795
796void
798{
799 InfoLog(<<"Stray ACK aimed at us that routes back to us. Dropping it...");
800}
801
802bool
804{
805 // Default behaviour is to not continue processing, this can be overridden
806 return false;
807}
808
809void
814
815void
817{
819 {
821 mAck200ToRetransmit->header(h_MaxForwards).value()--;
823
824 mAck200ToRetransmit->header(h_Vias).push_front(Via());
825
826 // .bwc. Check for flow-token use
828 {
830 }
831 }
832
834}
835
841
842const resip::SipMessage&
847
850{
852 {
853 static Data ack("ack");
855 }
856 else
857 {
859 }
860}
861
867
868const resip::Message*
870{
871 return mCurrentEvent;
872}
873
874void
879
880const resip::Data&
885
886void
887RequestContext::postTimedMessage(std::unique_ptr<resip::ApplicationMessage> msg,int seconds)
888{
889 mProxy.postMS(std::move(msg), seconds);
890}
891
892void
894{
896 DebugLog(<<"Posting Ack200DoneMessage");
897 // .bwc. This needs to have a timer attached to it. (We need to
898 // wait until all potential retransmissions of the ACK/200 have
899 // stopped. However, we must be mindful that we may receive a new,
900 // non-ACK transaction with the same tid during this time, and make
901 // sure we don't explode violently when this happens.)
903 std::unique_ptr<ApplicationMessage>(new Ack200DoneMessage(getTransactionId())),
905}
906
907void
909{
910 mProxy.send(msg);
911}
912
913void
915{
916 resip_assert (msg.isResponse());
917
918 // We can't respond to an ACK request - so just drop it and generate an Ack200DoneMessage so the request context
919 // gets cleaned up properly
920 if(mOriginalRequest->method() == ACK)
921 {
922 ErrLog(<<"Posting Ack200DoneMessage: due to sendResponse(). This is probably a bug.");
924 }
925 else
926 {
927 DebugLog(<< "tid of orig req: " << mOriginalRequest->getTransactionId());
928 resip::Data tid;
929 try
930 {
931 tid=msg.getTransactionId();
932 }
933 catch(BaseException&) // Could be SipMessage::Exception or ParseException
934 {
935 InfoLog(<< "Bad tid in response. Trying to replace with 2543 tid "
936 "from orig request.");
938 // .bwc. If the original request didn't have a proper transaction-
939 // id, the response will not either. We need to set the tid in the
940 // response in order to make sure that this response hits the
941 // correct transaction down in the stack.
943 }
944
946 {
947 InfoLog(<<"Someone messed with the Via stack in a response. This "
948 "is not only bad behavior, but potentially malicious. "
949 "Response came from: " << msg.getSource() <<
950 " Request came from: " <<
952 " Via after modification (in response): " <<
953 msg.header(h_Vias).front() <<
954 " Via before modification (in orig request): " <<
955 mOriginalRequest->header(h_Vias).front());
956 // .bwc. Compensate for malicous/broken UAS fiddling with Via stack.
957 msg.header(h_Vias).front() = mOriginalRequest->header(h_Vias).front();
958 }
959
960 DebugLog(<<"Ensuring orig tid matches tid of response: " <<
961 msg.getTransactionId() << " == " <<
964
965 // .bwc. Provisionals are not final responses, and CANCEL/200 is not a final
966 //response in this context.
967 if (msg.header(h_StatusLine).statusCode()>199 && msg.method()!=CANCEL)
968 {
969 DebugLog(<<"Sending final response.");
971 }
972 const resip::Data& serverText = mProxy.getServerText();
973 if (!serverText.empty() && !msg.exists(h_Server) )
974 {
975 msg.header(h_Server).value() = serverText;
976 }
978 {
979 getProxy().doSessionAccounting(msg, false /* received */, *this);
980 }
981 send(msg);
982 }
983}
984
985// This function assumes that if ;lr shows up in the RURI, that it's a URI
986// we put in a Record-Route header earlier. It will do the wrong thing if
987// some other malbehaving implementation lobs something at us with
988// ;lr in the RURI and it wasn't us. (from Section 16.4 of RFC 3261)
989void
991{
993 {
994 if (mOriginalRequest->exists(h_Routes)
995 && !mOriginalRequest->header(h_Routes).empty())
996 {
998 mOriginalRequest->header(h_Routes).pop_back();
999 }
1000 else
1001 {
1003 // place to log a warning
1004 }
1005 }
1006}
1007
1009void
1011{
1012 if(mOriginalRequest->exists(h_Routes)
1013 && !mOriginalRequest->header(h_Routes).empty()
1014 && mProxy.isMyUri(mOriginalRequest->header(h_Routes).front().uri()))
1015 {
1016 // save the top-most Route header field so monkeys can check it later
1017 mTopRoute = mOriginalRequest->header(h_Routes).front();
1018
1019 mOriginalRequest->header(h_Routes).pop_front();
1020
1021 static ExtensionParameter p_drr("drr");
1022 if(mTopRoute.uri().exists(p_drr))
1023 {
1024 if(!mOriginalRequest->header(h_Routes).empty()
1025 && mProxy.isMyUri(mOriginalRequest->header(h_Routes).front().uri()))
1026 {
1027 // .bwc. Do double-record routing logic
1028 mTopRoute = mOriginalRequest->header(h_Routes).front();
1029
1030 mOriginalRequest->header(h_Routes).pop_front();
1031 }
1032 else
1033 {
1034 // ?bwc? Somebody messed with our record-routes. Just ignore? Or
1035 // should we reject?
1036 }
1037 }
1038
1039 // Extract Flow Token from mTopRoute - if present
1040 if (!mTopRoute.uri().user().empty())
1041 {
1043 if (!(flowTuple == Tuple()))
1044 {
1045 mTopRouteFlowTuple = flowTuple;
1046 mTopRouteFlowTupleSet = true;
1047 }
1048 }
1049 }
1050}
1051
1052Proxy&
1054{
1055 return mProxy;
1056}
1057
1063
1064NameAddr&
1066{
1067 return mTopRoute;
1068}
1069
1070bool
1075
1076Tuple&
1081
1082const resip::Data&
1084{
1085 // (1) Check Preferred Identity
1087 {
1088 // !abr! Add this when we get a chance
1089 // find the fist sip or sips P-Preferred-Identity header
1090 // for (;;)
1091 // {
1092 // if ((i->uri().scheme() == Symbols::SIP) || (i->uri().scheme() == Symbols::SIPS))
1093 // {
1094 // return i->uri().host();
1095 // }
1096 // }
1097 }
1098
1099 // (2) Check From domain
1100 if (mProxy.isMyDomain(mOriginalRequest->header(h_From).uri().host()))
1101 {
1102 return mOriginalRequest->header(h_From).uri().host();
1103 }
1104
1105 // (3) Check Top Route Header
1106 if (mOriginalRequest->exists(h_Routes) &&
1107 mOriginalRequest->header(h_Routes).size()!=0 &&
1108 mOriginalRequest->header(h_Routes).front().isWellFormed())
1109 {
1110 // !abr! Add this when we get a chance
1111 }
1112
1113 // (4) Punt: Use Request URI
1115}
1116
1118repro::operator<<(EncodeStream& strm, const RequestContext& rc)
1119{
1120 strm << "numtrans=" << rc.mTransactionCount
1121 << " final=" << rc.mHaveSentFinalResponse;
1122 if(!rc.mDigestIdentity.empty()) strm << " identity=" << rc.mDigestIdentity;
1123 if (rc.mOriginalRequest) strm << " req=" << rc.mOriginalRequest->brief();
1124 //if (rc.mCurrentEvent) strm << " current=" << rc.mCurrentEvent->brief();
1125 return strm;
1126}
1127
1128
1129
1130/* ====================================================================
1131 * The Vovida Software License, Version 1.0
1132 *
1133 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1134 *
1135 * Redistribution and use in source and binary forms, with or without
1136 * modification, are permitted provided that the following conditions
1137 * are met:
1138 *
1139 * 1. Redistributions of source code must retain the above copyright
1140 * notice, this list of conditions and the following disclaimer.
1141 *
1142 * 2. Redistributions in binary form must reproduce the above copyright
1143 * notice, this list of conditions and the following disclaimer in
1144 * the documentation and/or other materials provided with the
1145 * distribution.
1146 *
1147 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1148 * and "Vovida Open Communication Application Library (VOCAL)" must
1149 * not be used to endorse or promote products derived from this
1150 * software without prior written permission. For written
1151 * permission, please contact vocal@vovida.org.
1152 *
1153 * 4. Products derived from this software may not be called "VOCAL", nor
1154 * may "VOCAL" appear in their name, without prior written
1155 * permission of Vovida Networks, Inc.
1156 *
1157 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1158 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1159 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1160 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1161 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1162 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1163 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1164 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1165 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1166 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1167 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1168 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1169 * DAMAGE.
1170 *
1171 * ====================================================================
1172 *
1173 * This software consists of voluntary contributions made by Vovida
1174 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1175 * Inc. For more information on Vovida Networks, Inc., please see
1176 * <http://www.vovida.org/>.
1177 *
1178 */
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
virtual processor_action_t process(RequestContext &)
Processor::ChainType chainType() const
virtual bool isMyUri(const resip::Uri &uri) const
Definition Proxy.cxx:600
void doSessionAccounting(const resip::SipMessage &sip, bool received, RequestContext &context)
Definition Proxy.cxx:703
static resip::Data FlowTokenSalt
Definition Proxy.hxx:61
resip::SipStack & getStack() noexcept
Definition Proxy.hxx:88
void postMS(std::unique_ptr< resip::ApplicationMessage > msg, int msec)
Definition Proxy.cxx:587
void send(const resip::SipMessage &msg)
Definition Proxy.cxx:557
const resip::Data & getServerText() const
Definition Proxy.hxx:103
virtual void handleSelfAimedStrayAck(resip::SipMessage *sip)
resip::Tuple mTopRouteFlowTuple
resip::SipMessage & getOriginalRequest()
Returns the SipMessage associated with the server transaction.
resip::SipMessage * mAck200ToRetransmit
void doPostResponseProcessing(resip::SipMessage *msg)
ProcessorChain & mRequestProcessorChain
bool processResponseNonInviteTransaction(resip::SipMessage *msg)
void postTimedMessage(std::unique_ptr< resip::ApplicationMessage > msg, int seconds)
virtual void removeTopRouteIfSelf()
Pops the topmost route if it's us.
virtual void process(resip::TransactionTerminated &msg)
virtual bool handleMissingResponseVias(resip::SipMessage *response)
void setDigestIdentity(const resip::Data &)
const resip::Data & getDigestRealm()
resip::Message * getCurrentEvent()
Returns the event that we are currently working on.
std::unique_ptr< ResponseContext > mResponseContext
void doPostRequestProcessing(resip::SipMessage *msg, bool original)
void processRequestAckTransaction(resip::SipMessage *msg, bool original)
resip::Message * mCurrentEvent
virtual void cancelClientTransaction(const resip::Data &tid, const resip::Tokens *reasons=0)
virtual void fixStrictRouterDamage()
resip::NameAddr mTopRoute
ResponseContext & getResponseContext()
ProcessorChain & mTargetProcessorChain
virtual void send(resip::SipMessage &msg)
resip::SipMessage * mOriginalRequest
virtual void forwardAck200(const resip::SipMessage &ack)
resip::Tuple & getTopRouteFlowTuple()
bool processResponseInviteTransaction(resip::SipMessage *msg)
bool processRequestNonInviteTransaction(resip::SipMessage *msg, bool original)
const resip::Data & getDigestIdentity() const
void sendResponse(resip::SipMessage &response)
resip::NameAddr & getTopRoute()
bool processRequestInviteTransaction(resip::SipMessage *msg, bool original)
ProcessorChain & mResponseProcessorChain
resip::Data getTransactionId() const
RequestContext(Proxy &proxy, ProcessorChain &requestP, ProcessorChain &responseP, ProcessorChain &targetP)
virtual const resip::Data & getTransactionId() const
The abstract base-class for all exceptions thrown by resip code.
const Data & getMessage() const noexcept
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Data base64decode() const
Performs RFC 3548 Base 64 decoding of the contents of this data.
Definition Data.cxx:2607
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
Data & lowercase()
Converts this Data to lowercase.
Definition Data.cxx:1635
static bool isClientBehindNAT(const SipMessage &request, bool privateToPublicOnly=true)
Looks at SIP headers and message source for a mismatch to make an assumption that the sender is behin...
Definition Helper.cxx:2357
static void processStrictRoute(SipMessage &request)
Definition Helper.cxx:1701
static void makeResponse(SipMessage &response, const SipMessage &request, int responseCode, const Data &reason=Data::Empty, const Data &hostname=Data::Empty, const Data &warning=Data::Empty)
Make a response to a provided request.
Definition Helper.cxx:412
static InteropHelper::ClientNATDetectionMode getClientNATDetectionMode()
bool isWellFormed() const
Returns true iff this element was parsed successfully, according to the implementation of parse().
The base-class used for message-passing.
Definition Message.hxx:21
virtual Brief brief() const
return a facet for brief encoding of message
Definition Message.cxx:16
Represents the "name-addr" and the "addr-spec" elements in the RFC 3261 grammar.
Definition NameAddr.hxx:19
BaseException used to indicate parse failures.
const Uri & uri() const
Represents a SIP message.
void setDestination(const Tuple &tuple)
Used by the stateless interface to specify where to send a request/response.
void setRFC2543TransactionId(const Data &tid)
bool isRequest() const
Returns true if message is a request, false otherwise.
const Data & getRFC2543TransactionId() const
Calculates an MD5 hash over the Request-URI, To tag (for non-INVITE transactions),...
bool hasForceTarget() const
void setForceTarget(const Uri &uri)
deal with a notion of an "out-of-band" forced target for SIP routing
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
virtual const Data & getTransactionId() const
Returns the transaction id from the branch or if 2543, the computed hash.
bool isResponse() const
Returns true if message is a response, false otherwise.
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
const Tuple & getSource() const
Returns the source tuple that the message was received from only makes sense for messages received fr...
resip::MethodTypes method() const
returns the method type of the message
void cancelClientInviteTransaction(const Data &tid, const Tokens *reasons)
Tells the stack that the TU wishes to CANCEL an INVITE request.
static unsigned long T1
Definition Timer.hxx:114
virtual const Data & getTransactionId() const
bool isMyDomain(const Data &domain) const
Returns true iff domain matches one of the domains that this TransactionUser is responsible for.
Represents a network address.
Definition Tuple.hxx:59
static Tuple makeTupleFromBinaryToken(const Data &binaryToken, const Data &salt=Data::Empty)
Definition Tuple.cxx:328
TransportType getType() const
Definition Tuple.hxx:122
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
Definition Uri.hxx:22
int & port()
Definition Uri.hxx:145
bool exists(const Param< Uri > &paramType) const
Definition Uri.cxx:1701
Data & user()
Definition Uri.hxx:42
void remove(const Param< Uri > &paramType)
Definition Uri.cxx:1709
Data & host()
Definition Uri.hxx:40
const Data & param(const ExtensionParameter &param) const
Const accessor for non-natively-supported parameter types.
Represents the "via-parm" element in the RFC 3261 grammar.
Definition Via.hxx:18
This Class is used to implement a primitive form of RPC using loose XML formatting.
EncodeStream & operator<<(EncodeStream &os, const repro::Processor &rp)
Definition Processor.cxx:69
dcm! – add UnusedChecking(_enum) below;
StatusLineType h_StatusLine
Definition Headers.cxx:348
bool isWebSocket(TransportType type)
Returns true if passed in transport type is a WebSocket transport protocol.
H_PPreferredIdentitys h_PPreferredIdentities
Definition Headers.cxx:211
RequestLineType h_RequestLine
Definition Headers.cxx:347
#define EncodeStream