Commit 1b4c0aad authored by Simon Morlat's avatar Simon Morlat

Ensure that response received from an outgoing transaction created as a...

Ensure that response received from an outgoing transaction created as a consequence of an incoming transaction are really sent through the incoming transaction (and not statelessly)
parent 1285db6b
......@@ -196,6 +196,7 @@ shared_ptr<IncomingTransaction> RequestSipEvent::createIncomingTransaction() {
mIncomingAgent = transaction;
transaction->handle(mMsgSip);
linkTransactions();
}
return transaction;
}
......@@ -205,10 +206,22 @@ shared_ptr<OutgoingTransaction> RequestSipEvent::createOutgoingTransaction() {
if (transaction == NULL) {
transaction = shared_ptr<OutgoingTransaction>(new OutgoingTransaction(mOutgoingAgent->getAgent()));
mOutgoingAgent = transaction;
linkTransactions();
}
return transaction;
}
void RequestSipEvent::linkTransactions(){
shared_ptr<OutgoingTransaction> ot;
shared_ptr<IncomingTransaction> it;
if (mOutgoingAgent && mIncomingAgent &&
(ot=dynamic_pointer_cast<OutgoingTransaction>(mOutgoingAgent))!=NULL &&
(it=dynamic_pointer_cast<IncomingTransaction>(mIncomingAgent))!=NULL){
ot->mIncoming=it;
}
}
void RequestSipEvent::suspendProcessing() {
SipEvent::suspendProcessing();
......@@ -220,40 +233,55 @@ RequestSipEvent::~RequestSipEvent() {
}
ResponseSipEvent::ResponseSipEvent(shared_ptr<OutgoingAgent> outgoingAgent, const shared_ptr<MsgSip> &msgSip) :
SipEvent(msgSip) {
SipEvent(msgSip), mPopVia(false) {
mOutgoingAgent = outgoingAgent;
mIncomingAgent = outgoingAgent->getAgent()->shared_from_this();
shared_ptr<OutgoingTransaction> ot=dynamic_pointer_cast<OutgoingTransaction>(outgoingAgent);
if (ot){
//retrieve the incoming transaction associated with the outgoing one, if any.
//A response SipEvent is generated either from a stateless response or from a response from an outgoing transaction.
mIncomingAgent=ot->mIncoming;
mPopVia=true;
}
if (mIncomingAgent == NULL)
mIncomingAgent = outgoingAgent->getAgent()->shared_from_this();//the main (stateless) default agent
}
ResponseSipEvent::ResponseSipEvent(const shared_ptr<SipEvent> &sipEvent) :
SipEvent(*sipEvent) {
ResponseSipEvent::ResponseSipEvent(const shared_ptr<ResponseSipEvent> &sipEvent) :
SipEvent(*sipEvent), mPopVia(sipEvent->mPopVia) {
}
void ResponseSipEvent::send(const shared_ptr<MsgSip> &msg, url_string_t const *u, tag_type_t tag, tag_value_t value, ...) {
if (mIncomingAgent != NULL) {
SLOGD << "Sending Response SIP message to "
<< (u ? url_as_string(msg->getHome(), (url_t const *) u) : "NULL")
<< "\n" << *msg;
bool via_popped=false;
if (mPopVia && msg==mMsgSip) {
sip_via_remove(msg->getMsg(), msg->getSip());
via_popped=true;
}
SLOGD << "Sending response:" << (via_popped ? " (via popped) " : "")<<endl<< *msg;
ta_list ta;
ta_start(ta, tag, value);
mIncomingAgent->send(msg, u, ta_tags(ta));
ta_end(ta);
} else {
LOGD("The Response SIP message is not sent");
LOGD("The response is discarded.");
}
terminateProcessing();
}
void ResponseSipEvent::send(const shared_ptr<MsgSip> &msg) {
if (mIncomingAgent != NULL) {
SLOGD << "Sending Response SIP message:\n" << *msg;
/*if the message is still the one for which the ResponseSipEvent was created and mPopVia is set, then pop the via*/
if (mPopVia && msg==mMsgSip) sip_via_remove(msg->getMsg(), msg->getSip());
SLOGD << "Sending response:\n" << *msg;
mIncomingAgent->send(msg);
} else {
SLOGD << "The Response SIP message is not sent";
SLOGD << "The response is discarded.";
}
terminateProcessing();
}
void ResponseSipEvent::setOutgoingAgent(const shared_ptr<OutgoingAgent> &agent) {
LOGA("Can't change outgoing agent in response sip event");
}
......
......@@ -190,19 +190,23 @@ public:
~RequestSipEvent();
bool mRecordRouteAdded;
private:
void linkTransactions();
};
class ResponseSipEvent: public SipEvent {
public:
ResponseSipEvent(std::shared_ptr<OutgoingAgent> outgoingAgent, const std::shared_ptr<MsgSip> &msgSip);
ResponseSipEvent(const std::shared_ptr<SipEvent> &sipEvent);
ResponseSipEvent(const std::shared_ptr<ResponseSipEvent> &sipEvent);
virtual void send(const std::shared_ptr<MsgSip> &msg, url_string_t const *u, tag_type_t tag, tag_value_t value, ...);
virtual void send(const std::shared_ptr<MsgSip> &msg);
virtual void setOutgoingAgent(const std::shared_ptr<OutgoingAgent> &agent);
~ResponseSipEvent();
private:
bool mPopVia;//set to true if the response comes from an outgoing transaction.
};
inline std::ostream& operator<<(std::ostream& strm, MsgSip const& obj) {
......
......@@ -76,7 +76,7 @@ void ForkBasicContext::store(shared_ptr<ResponseSipEvent> &event) {
void ForkBasicContext::onResponse(const shared_ptr<OutgoingTransaction> &transaction, shared_ptr<ResponseSipEvent> &event) {
event->setIncomingAgent(mIncoming);
const shared_ptr<MsgSip> &ms = event->getMsgSip();
sip_via_remove(ms->getMsg(), ms->getSip()); // remove via
sip_t *sip = ms->getSip();
if (sip != NULL && sip->sip_status != NULL) {
LOGD("Fork: outgoingCallback %d", sip->sip_status->st_status);
......
......@@ -170,7 +170,6 @@ void ForkCallContext::store(shared_ptr<ResponseSipEvent> &event) {
void ForkCallContext::onResponse(const shared_ptr<OutgoingTransaction> &transaction, shared_ptr<ResponseSipEvent> &event) {
event->setIncomingAgent(mIncoming);
const shared_ptr<MsgSip> &ms = event->getMsgSip();
sip_via_remove(ms->getMsg(), ms->getSip()); // remove via
sip_t *sip = ms->getSip();
if (sip != NULL && sip->sip_status != NULL) {
......
......@@ -101,8 +101,8 @@ void ForkMessageContext::store(shared_ptr<ResponseSipEvent> &event) {
void ForkMessageContext::onResponse(const shared_ptr<OutgoingTransaction> &transaction, shared_ptr<ResponseSipEvent> &event) {
event->setIncomingAgent(mIncoming);
const shared_ptr<MsgSip> &ms = event->getMsgSip();
sip_via_remove(ms->getMsg(), ms->getSip()); // remove via
sip_t *sip = ms->getSip();
if (sip != NULL && sip->sip_status != NULL) {
LOGD("Fork: outgoingCallback %d", sip->sip_status->st_status);
......
......@@ -67,6 +67,7 @@ void OutgoingTransaction::send(const shared_ptr<MsgSip> &ms, url_string_t const
msg_t* msg = msg_dup(ms->getMsg());
ta_list ta;
ta_start(ta, tag, value);
LOGD("Message is sent through an outgoing transaction.");
mOutgoing = nta_outgoing_mcreate(mAgent->mAgent, OutgoingTransaction::_callback, (nta_outgoing_magic_t*) this, u, msg, ta_tags(ta));
ta_end(ta);
if (mOutgoing == NULL) {
......@@ -81,6 +82,7 @@ void OutgoingTransaction::send(const shared_ptr<MsgSip> &ms, url_string_t const
void OutgoingTransaction::send(const shared_ptr<MsgSip> &ms) {
msg_t* msg = msg_dup(ms->getMsg());
LOGD("Message is sent through an outgoing transaction.");
mOutgoing = nta_outgoing_mcreate(mAgent->mAgent, OutgoingTransaction::_callback, (nta_outgoing_magic_t*) this, NULL, msg, TAG_END());
if (mOutgoing == NULL) {
LOGE("Error during outgoing transaction creation");
......@@ -118,6 +120,7 @@ void OutgoingTransaction::destroy() {
mAgent->sendTransactionEvent(TransactionEvent::makeDestroy(shared_from_this()));
nta_outgoing_bind(mOutgoing, NULL, NULL); //avoid callbacks
nta_outgoing_destroy(mOutgoing);
mIncoming.reset();
looseProperties();
}
}
......@@ -155,6 +158,7 @@ shared_ptr<MsgSip> IncomingTransaction::createResponse(int status, char const *p
void IncomingTransaction::send(const shared_ptr<MsgSip> &ms, url_string_t const *u, tag_type_t tag, tag_value_t value, ...) {
if (mIncoming) {
msg_t* msg = msg_dup(ms->getMsg()); //need to duplicate the message because mreply will decrement its ref count.
LOGD("Response is sent through an incoming transaction.");
nta_incoming_mreply(mIncoming, msg);
if (ms->getSip()->sip_status != NULL && ms->getSip()->sip_status->st_status >= 200) {
destroy();
......@@ -167,6 +171,7 @@ void IncomingTransaction::send(const shared_ptr<MsgSip> &ms, url_string_t const
void IncomingTransaction::send(const shared_ptr<MsgSip> &ms) {
if (mIncoming) {
msg_t* msg = msg_dup(ms->getMsg());
LOGD("Response is sent through an incoming transaction.");
nta_incoming_mreply(mIncoming, msg);
if (ms->getSip()->sip_status != NULL && ms->getSip()->sip_status->st_status >= 200) {
destroy();
......
......@@ -145,17 +145,20 @@ public:
inline virtual Agent *getAgent() {
return Transaction::getAgent();
}
/// The incoming transaction from which the message comes from, if any.
std::shared_ptr<IncomingTransaction> mIncoming;
private:
friend class RequestSipEvent;
OutgoingTransaction(Agent *agent);
std::shared_ptr<OutgoingTransaction> mSofiaRef;
nta_outgoing_t *mOutgoing;
virtual void send(const std::shared_ptr<MsgSip> &msg, url_string_t const *u, tag_type_t tag, tag_value_t value, ...);
virtual void send(const std::shared_ptr<MsgSip> &msg);
void destroy();
private:
static int _callback(nta_outgoing_magic_t *magic, nta_outgoing_t *irq, const sip_t *sip);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment