1#if defined(HAVE_CONFIG_H)
25#if defined(WIN32) && !defined(__GNUC__)
26#pragma warning( disable : 4355 )
29#define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
39 mHaveSentFinalResponse(false),
42 mAck200ToRetransmit(0),
43 mRequestProcessorChain(requestP),
44 mResponseProcessorChain(responseP),
45 mTargetProcessorChain(targetP),
48 mTopRouteFlowTupleSet(false),
50 mSessionCreatedEventSent(false),
51 mSessionEstablishedEventSent(false),
52 mKeyValueStore(*
Proxy::getRequestKeyValueStoreKeyAllocator())
58 DebugLog (<<
"RequestContext::~RequestContext() " <<
this);
74 InfoLog (<<
"RequestContext::process(TransactionTerminated) "
91 bool original =
false;
92 InfoLog (<<
"RequestContext::process(SipMessage) " << sipMessage->getTransactionId());
118 InfoLog(<<
"Parse failure Exception caught: " << e);
134 ErrLog(<<
"Exception caught: " << e);
153 bool postProcess=
false;
156 if(requestUri.
exists(resip::p_wsSrcIp) &&
157 requestUri.
exists(resip::p_wsSrcPort) &&
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);
186 bool postProcess=
false;
211 bool doPostProcess=
false;
232 ErrLog(<<
"Exception caught: " << e);
247 else if(msg->
method()==ACK)
256 DebugLog(<<
"This ACK has the same tid as the original INVITE.");
257 DebugLog(<<
"The reponse we sent back was a "
266 ErrLog(<<
"Got an ACK, but haven't sent a final response. "
267 "What happened here?");
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()) ||
288 ErrLog(<<
"We got an unexpected request from "
289 "the stack in an invite RequestContext. "
292 " This: " << msg->
brief());
297 return doPostProcess;
305 bool doPostProcess=
false;
324 ErrLog(<<
"Exception caught: " << e);
341 ErrLog(<<
"We got a second non-invite request from the"
342 " stack in an already-established non-"
343 "invite RequestContext. "
346 " This: " << msg->
brief());
352 "unexpected request in a non-invite RequestContext";
359 return doPostProcess;
376 DebugLog(<<
"This ACK has its own tid.");
404 InfoLog(<<
"Top most route or From header are not ours. We do not allow relaying ACKs. Dropping it...");
409 InfoLog(<<
"Parse error processing ACK. Dropping it...");
435 InfoLog (<< *
this <<
": no targets for "
444 InfoLog (<< *
this <<
" there are "
446 <<
" candidates -> continue");
458 ErrLog(<<
"Server error caught after"
459 " request was forwarded. Exception was: "<<e);
467 ErrLog(<<
"Exception caught: " << e);
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:"
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?)");
506 bool doPostProcessing=
false;
519 doPostProcessing=
true;
529 InfoLog(<<
"Garbage in response; dropping message. " << e);
534 ErrLog(<<
"Exception thrown in response processor chain: " << e);
539 else if(msg->
method()==CANCEL)
549 return doPostProcessing;
559 bool doPostProcessing=
false;
570 doPostProcessing=
true;
580 InfoLog(<<
"Garbage in response; dropping message. " << e);
585 ErrLog(<<
"Exception thrown in response processor chain: " << e);
596 return doPostProcessing;
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:"
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.");
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?) ");
658 InfoLog (<<
"RequestContext::process(ApplicationMessage) " << *app);
700 ErrLog(<<
"Exception caught: " << e);
711 InfoLog (<< *
this <<
": no targets for "
718 InfoLog (<< *
this <<
" there are "
720 <<
" candidates -> continue");
732 ErrLog(<<
"Server error caught after"
733 " request was forwarded. Exception was: "<<e);
741 ErrLog(<<
"Exception caught: " << e);
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:"
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?)");
790 <<
"ProcessorMessage addressed to a non existent chain "
799 InfoLog(<<
"Stray ACK aimed at us that routes back to us. Dropping it...");
853 static Data ack(
"ack");
896 DebugLog(<<
"Posting Ack200DoneMessage");
922 ErrLog(<<
"Posting Ack200DoneMessage: due to sendResponse(). This is probably a bug.");
935 InfoLog(<<
"Bad tid in response. Trying to replace with 2543 tid "
936 "from orig request.");
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): " <<
960 DebugLog(<<
"Ensuring orig tid matches tid of response: " <<
969 DebugLog(<<
"Sending final response.");
975 msg.
header(h_Server).value() = serverText;
1043 if (!(flowTuple ==
Tuple()))
#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
void doSessionAccounting(const resip::SipMessage &sip, bool received, RequestContext &context)
static resip::Data FlowTokenSalt
resip::SipStack & getStack() noexcept
void postMS(std::unique_ptr< resip::ApplicationMessage > msg, int msec)
void send(const resip::SipMessage &msg)
const resip::Data & getServerText() const
virtual void handleSelfAimedStrayAck(resip::SipMessage *sip)
resip::Data mDigestIdentity
resip::Tuple mTopRouteFlowTuple
resip::SipMessage & getOriginalRequest()
Returns the SipMessage associated with the server transaction.
resip::SipMessage * mAck200ToRetransmit
void doPostResponseProcessing(resip::SipMessage *msg)
bool mTopRouteFlowTupleSet
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()
virtual ~RequestContext()
resip::NameAddr mTopRoute
ResponseContext & getResponseContext()
ProcessorChain & mTargetProcessorChain
bool mHaveSentFinalResponse
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)
bool mSessionCreatedEventSent
const resip::Data & getDigestIdentity() const
void sendResponse(resip::SipMessage &response)
bool isTopRouteFlowTupleSet()
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)
bool mSessionEstablishedEventSent
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.
Data base64decode() const
Performs RFC 3548 Base 64 decoding of the contents of this data.
bool empty() const noexcept
Checks whether the Data is empty.
Data & lowercase()
Converts this Data to lowercase.
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...
static void processStrictRoute(SipMessage &request)
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.
static InteropHelper::ClientNATDetectionMode getClientNATDetectionMode()
@ ClientNATDetectionDisabled
@ ClientNATDetectionPrivateToPublicOnly
bool isWellFormed() const
Returns true iff this element was parsed successfully, according to the implementation of parse().
The base-class used for message-passing.
virtual Brief brief() const
return a facet for brief encoding of message
Represents the "name-addr" and the "addr-spec" elements in the RFC 3261 grammar.
BaseException used to indicate parse failures.
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.
virtual bool isClientTransaction() const
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.
static Tuple makeTupleFromBinaryToken(const Data &binaryToken, const Data &salt=Data::Empty)
TransportType getType() const
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
bool exists(const Param< Uri > ¶mType) const
void remove(const Param< Uri > ¶mType)
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
Represents the "via-parm" element in the RFC 3261 grammar.
This Class is used to implement a primitive form of RPC using loose XML formatting.
EncodeStream & operator<<(EncodeStream &os, const repro::Processor &rp)
dcm! – add UnusedChecking(_enum) below;
StatusLineType h_StatusLine
bool isWebSocket(TransportType type)
Returns true if passed in transport type is a WebSocket transport protocol.
H_PPreferredIdentitys h_PPreferredIdentities
RequestLineType h_RequestLine