1#if defined(HAVE_CONFIG_H)
24#define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
31 mRequestContext(context),
34 mIsClientBehindNAT(false)
41 TransactionMap::iterator i;
65 InfoLog (<<
"Adding candidate " << addr);
66 std::unique_ptr<Target> target(
new Target(addr));
67 Data tid=target->tid();
68 addTarget(std::move(target), beginImmediately);
103 Target* toAdd=target.release();
108 if(target->mShouldAutoProcess)
110 std::list<resip::Data> queue;
111 queue.push_back(target->tid());
115 Target* toAdd=target.release();
126 std::list<resip::Data> queue;
128 TargetPtrList::iterator it;
132 for(it=targets.begin();it!=targets.end();it++)
141 for(it=targets.begin();it!=targets.end();it++)
150 queue.push_back(target->
tid());
152 DebugLog(<<
"Adding Target to Candidates: " << target->
uri() <<
" tid=" << target->
tid());
197 InfoLog (<<
"Creating new client transaction " << i->second->tid() <<
" -> " << i->second->uri());
203 DebugLog(<<
"Found a repeated target.");
206 TransactionMap::iterator temp=i;
235 InfoLog(<<
"Creating new client transaction " << i->second->tid() <<
" -> " << i->second->uri());
306 TransactionMap::iterator temp = j;
458 WarningLog(<<
"Something removed an active transaction, " << transactionId
459 <<
". It is very likely that something is broken here. ");
468 resip::ContactList::const_iterator i;
478 if(*i==target->
rec())
487std::unique_ptr<resip::SipMessage>
491 std::unique_ptr<SipMessage> request(
new SipMessage(orig));
496 request->header(h_Routes).push_front(
NameAddr(target->
uri()));
504 request->header(h_MaxForwards).value()--;
506 bool inDialog =
false;
510 inDialog = request->header(h_To).
exists(p_tag);
523 bool transportSpecificRecordRoute;
528 (request->method() == INVITE ||
529 request->method() == SUBSCRIBE ||
530 request->method() == REFER))
534 receivedTransportRecordRoute,
535 transportSpecificRecordRoute,
538 else if (request->method() == REGISTER)
542 receivedTransportRecordRoute,
543 transportSpecificRecordRoute,
563 DebugLog(<<
"Set tuple dest: " << request->getDestination());
568 request->header(h_Routes).append(target->
rec().
mSipPath);
577 request->header(h_Vias).push_front(target->
via());
610 bool transportSpecificRecordRoute,
616 bool recordRouted=
false;
619 if( !inboundFlowToken.
empty()
620 || needsOutboundFlowToken
624 if(inboundFlowToken.
empty())
626 rt = receivedTransportRecordRoute;
634 rt = receivedTransportRecordRoute;
639 if(receivedTransportTuple.
isAnyInterface() || transportSpecificRecordRoute)
641 rt = receivedTransportRecordRoute;
652 rt.
uri().
user() = inboundFlowToken;
659 target->
uri().
param(p_comp)==
"sigcomp")
668 if(!inboundFlowToken.
empty())
677 outgoing.
header(h_Paths).push_front(rt);
678 if(!outgoing.
header(h_Supporteds).find(
Token(
"path")))
680 outgoing.
header(h_Supporteds).push_back(
Token(
"path"));
682 InfoLog (<<
"Added Path: " << rt);
686 outgoing.
header(h_RecordRoutes).push_front(rt);
687 InfoLog (<<
"Added Record-Route: " << rt);
695 if(!doPathInstead || recordRouted)
697 std::unique_ptr<resip::MessageDecorator> rrDecorator(
699 receivedTransportTuple,
700 receivedTransportRecordRoute,
702 !inboundFlowToken.
empty(),
725 if(orig.
header(h_Vias).size()==1)
735 else if(doPathInstead)
744 WarningLog(<<
"Client asked for outbound processing, but the edge "
745 "proxy did not support it. There's nothing we can do to "
746 "salvage this. The registrar might end up rejecting the "
747 "registration (if is supports outbound), or it might just "
748 "fail to add a Supported: outbound. In either case, the "
749 "client should know what's up, so we just let it all "
755 if(flowToken.
empty() && orig.
header(h_Vias).size() == 1)
772 if (flowToken.
empty() &&
835 if(type ==
TLS || type ==
TCP)
865 if (request.
method() != CANCEL &&
880 if(request.
exists(h_Routes) &&
914 std::vector<Data>::iterator itToken = it->value().begin();
915 for(; itToken != it->value().end() && !found; itToken++)
930 Auths &authHeaders = request.
header(h_ProxyAuthorizations);
935 i = authHeaders.
erase(i);
945 if (request.
method() == ACK)
947 DebugLog(<<
"Posting Ack200DoneMessage");
966 if (request.
exists(h_Reasons))
986 InfoLog(<<
"Updating timer C for client transaction " << tid);
991 timerCSerial = ++i->second;
1004 bool isLatestTimer =
false;
1008 isLatestTimer = (serial == i->second);
1013 InfoLog(<<
"Canceling client transaction " << tid <<
" due to timer C.");
1039 InfoLog (<<
"processResponse: " << endl << response);
1046 response.
header(h_Vias).pop_front();
1049 if (response.
header(h_Vias).empty())
1056 if(response.
method()==CANCEL)
1067 InfoLog(<<
"Received final response, but can't forward as there are "
1068 "no more Vias. Considering this branch failed. "
1069 << response.
brief());
1075 InfoLog(<<
"Received provisional response, but can't forward as there"
1076 " are no more Vias. Ignoring. " << response.
brief());
1091 const Via& via = response.
header(h_Vias).front();
1097 DebugLog(<<
"Some endpoint has corrupted one of our Vias"
1098 " in their response. (Via is malformed) This is not fixable.");
1115 DebugLog(<<
"Some endpoint has altered one of our Vias"
1116 " in their response. (branch is different) This is not fixable.");
1136 if ((code / 100) != 2)
1138 InfoLog( <<
"Discarding stray response" );
1182 Token reason(
"SIP");
1183 reason.
param(p_cause) = code;
1184 reason.
param(p_text) =
"Call completed elsewhere";
1202 if(response.
method() == REGISTER &&
1204 response.
empty(h_FlowTimer) &&
1227 if (code == 401 || code == 407)
1229 if (response.
exists(h_WWWAuthenticates))
1232 i != response.
header(h_WWWAuthenticates).end() ; ++i)
1238 if (response.
exists(h_ProxyAuthenticates))
1241 i != response.
header(h_ProxyAuthenticates).end() ; ++i)
1248 else if (code / 100 == 3)
1257 for (NameAddrs::iterator i=response.
header(h_Contacts).begin();
1258 i != response.
header(h_Contacts).end(); ++i)
1266 if(!i->isWellFormed() || i->isAllContacts())
1306 Token reason(
"SIP");
1307 reason.
param(p_cause) = code;
1334 InfoLog (<<
"Cancel client transaction: " << target);
1337 DebugLog(<<
"Canceling a transaction with uri: "
1381 resip_assert(responseCode >= 300 && responseCode <= 599);
1382 if (responseCode <= 399)
1386 if (responseCode >= 500)
1388 switch(responseCode)
1400 switch(responseCode)
1526 Token reason(
"SIP");
1563 strm <<
"ResponseContext: "
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
virtual bool isMyUri(const resip::Uri &uri) const
const resip::NameAddr & getRecordRoute(unsigned int transportKey, bool *transportSpecific=0) const
void doSessionAccounting(const resip::SipMessage &sip, bool received, RequestContext &context)
bool isPAssertedIdentityProcessingEnabled()
static resip::Data FlowTokenSalt
bool compressionEnabled() const
resip::SipStack & getStack() noexcept
void postTimerC(std::unique_ptr< TimerCMessage > tc)
bool isNeverStripProxyAuthorizationHeadersEnabled()
bool getRecordRouteForced() const
void addClientTransaction(const resip::Data &transactionId, RequestContext *rc)
resip::SipMessage & getOriginalRequest()
Returns the SipMessage associated with the server transaction.
virtual void process(resip::TransactionTerminated &msg)
virtual bool handleMissingResponseVias(resip::SipMessage *response)
virtual void cancelClientTransaction(const resip::Data &tid, const resip::Tokens *reasons=0)
bool mHaveSentFinalResponse
virtual void send(resip::SipMessage &msg)
const resip::Data & getDigestIdentity() const
void sendResponse(resip::SipMessage &response)
resip::Data getTransactionId() const
bool operator()(const resip::SipMessage &lhs, const resip::SipMessage &rhs) const
const TransactionMap & getCandidateTransactionMap() const
Self-explanatory.
virtual void forwardBestResponse()
bool isDuplicate(const repro::Target *target) const
void removeClientTransaction(const resip::Data &transactionId)
bool isTerminated(const resip::Data &tid) const
bool needsFlowTokenToWork(const resip::NameAddr &contact) const
std::unique_ptr< resip::SipMessage > buildTargetRequest(Target *target)
bool cancelAllClientTransactions(const resip::Tokens *reasons=0)
Cancels all active client transactions.
int getPriority(const resip::SipMessage &msg)
resip::Data mCurrentResponseTid
resip::Data addTarget(const resip::NameAddr &target, bool beginImmediately=false)
Adds this Target as a SimpleTarget to the collection of Targets.
RequestContext & mRequestContext
bwc! This should probably not be private, since these two classes are
resip::Data getInboundFlowToken(bool doPathInstead)
std::map< resip::Data, repro::Target * > TransactionMap
bool hasTerminatedTransactions() const
bool sendingToSelf(Target *target)
bool hasCandidateTransactions() const
TransactionMap mTerminatedTransactionMap
bool isActive(const resip::Data &tid) const
static const int TimerCSerialInit
void processTimerC(const resip::Data &tid, int serial)
resip::SipMessage mBestResponse
bool addTargetBatch(TargetPtrList &targets, bool highPriority=false)
Adds a batch of Targets.
void sendRequest(resip::SipMessage &request)
void terminateClientTransaction(const resip::Data &tid)
void updateTimerC(const resip::Data &tid)
bool outboundFlowTokenNeeded(Target *target)
ResponseContext(RequestContext &parent)
bool cancelClientTransaction(const resip::Data &serial, const resip::Tokens *reasons=0)
Cancels this client transaction if active, or Terminates it if Candidate.
void processCancel(const resip::SipMessage &request)
bool beginClientTransaction(const resip::Data &serial)
Begins a client transaction.
std::list< std::list< resip::Data > > mTransactionQueueCollection
Target * getTarget(const resip::Data &serial) const
Self-explanatory.
std::unordered_map< resip::Data, int > mTimerCSerial
void processResponse(resip::SipMessage &response)
bool hasActiveTransactions() const
bool clearCandidateTransactions(const resip::Tokens *reasons=0)
Removes all Candidate transactions.
void insertRecordRoute(resip::SipMessage &outgoing, const resip::Tuple &receivedTransportTuple, const resip::NameAddr &receivedTransportRecordRoute, bool transportSpecificRecordRoute, Target *target, bool doPathInstead=false)
TransactionMap mActiveTransactionMap
TransactionMap mCandidateTransactionMap
resip::ContactList mTargetList
bool beginClientTransactions()
Begins all Candidate client transactions.
bool isCandidate(const resip::Data &tid) const
bool cancelActiveClientTransactions(const resip::Tokens *reasons=0)
Cancels all active client transactions.
bool areAllTransactionsTerminated() const
virtual ~ResponseContext()
virtual const resip::Uri & uri() const
virtual Status & status()
virtual const resip::Data & tid() const
virtual const resip::Via & via() const
virtual const resip::ContactInstanceRecord & rec() const
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
static const Data Empty
Constant that represents a zero-length data.
Data base64encode(bool useUrlSafe=false) const
Performs RFC 3548 Base 64 encoding of the contents of this data.
bool empty() const noexcept
Checks whether the Data is empty.
static Data from(const T &x)
Converts from arbitrary other type to Data.
static bool isIpAddress(const Data &ipAddress)
static void processStrictRoute(SipMessage &request)
static void massageRoute(const SipMessage &request, NameAddr &route)
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 bool getAllowInboundFlowTokensForNonDirectClients()
static bool getRRTokenHackEnabled()
static unsigned int getFlowTimerSeconds()
static bool getOutboundSupported()
bool isWellFormed() const
Returns true iff this element was parsed successfully, according to the implementation of parse().
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.
bool exists(const Param< NameAddr > ¶mType) const
virtual void setQuoted(bool)
BaseException used to indicate parse failures.
Parameter * getParameterByEnum(ParameterTypes::Type type) const
bool empty() const
return true or false indicating whether the mParsers vector is empty or not
An iterator class (bidirectional)
iterator end()
Returns an iterator pointing to the last header field value.
iterator erase(iterator i)
Erases the header field value pointed to by i.
iterator begin()
Returns an iterator pointing to the first header field value.
void push_back(const T &t)
Inserts a header field value at the back of this container.
Represents a SIP message.
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),...
const Tuple & getReceivedTransportTuple() const
void addOutboundDecorator(std::unique_ptr< MessageDecorator > md)
Call a MessageDecorator to process the message before it is sent to the transport.
bool empty(const HeaderBase &headerType) const
Returns true if the header field is present and non-empty, false otherwise.
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.
const RequestLine & const_header(const RequestLineType &l) const
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...
void remove(const HeaderBase &headerType)
Prevents a header field from being present when the message is prepared for sending to a transport.
resip::MethodTypes method() const
returns the method type of the message
void abandonServerTransaction(const Data &tid)
Tells the stack that the TU has abandoned a server transaction.
void enableFlowTimer(const resip::Tuple &flow)
static const char * Outbound
Represents the "token" element in the RFC 3261 grammar.
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
bool isMyDomain(const Data &domain) const
Returns true iff domain matches one of the domains that this TransactionUser is responsible for.
void post(Message *msg)
Posts a Message to this TransactionUser's fifo.
Represents a network address.
bool isAnyInterface() const
TRUE if this address is equal to the "INADDR_ANY" value for this address family.
bool onlyUseExistingConnection
FlowKey mFlowKey
This is a (largely) opaque key that subclasses of Transport will use to help record/find flows.
static const Data & toDataLower(TransportType type)
static void writeBinaryToken(const Tuple &tuple, Data &container, const Data &salt=Data::Empty)
TransportType getType() const
static Data inet_ntop(const Tuple &tuple)
Converts the binary socket address to presentation format, via the DnsUtil::inet_ntop() method.
TransportKey mTransportKey
bool exists(const Param< Uri > ¶mType) const
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.
bool exists(const Param< Via > ¶mType) const
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
This Class is used to implement a primitive form of RPC using loose XML formatting.
EncodeStream & operator<<(EncodeStream &os, const repro::Processor &rp)
std::list< Target * > TargetPtrList
dcm! – add UnusedChecking(_enum) below;
StatusLineType h_StatusLine
bool isEqualNoCase(const Data &left, const Data &right)
TransportType toTransportType(const resip::Data &transportName)
bool isSecure(TransportType type)
Returns true if passed in transport type is a secure transport protocol.
H_PAssertedIdentitys h_PAssertedIdentities
InserterPClass< T > InserterP(const T &t)
Templatized function to construct an instance of InserterClass for a container to be inserted.
TransportType
An enumeration of transport protocols.
RequestLineType h_RequestLine