Commit 27d3ec1c authored by Simon Morlat's avatar Simon Morlat

optimize memory usage, clean code

parent b440ceec
......@@ -641,7 +641,7 @@ inline void Agent::doSendEvent
void Agent::sendRequestEvent(shared_ptr<RequestSipEvent> ev) {
sip_t *sip=ev->getMsgSip()->mSip;
sip_t *sip=ev->getMsgSip()->getSip();
const sip_request_t *req=sip->sip_request;
const url_t *from= sip->sip_from->a_url;
SLOGD << "Receiving new Request SIP message "
......@@ -687,10 +687,10 @@ void Agent::sendRequestEvent(shared_ptr<RequestSipEvent> ev) {
void Agent::sendResponseEvent(shared_ptr<ResponseSipEvent> ev) {
SLOGD << "Receiving new Response SIP message: "
<< ev->getMsgSip()->mSip->sip_status->st_status << "\n"
<< ev->getMsgSip()->getSip()->sip_status->st_status << "\n"
<< *ev->getMsgSip();
sip_t *sip=ev->getMsgSip()->mSip;
sip_t *sip=ev->getMsgSip()->getSip();
switch (sip->sip_status->st_status) {
case 100:
++*mCountIncoming100;
......@@ -769,20 +769,18 @@ void Agent::injectResponseEvent(shared_ptr<ResponseSipEvent> ev) {
doSendEvent(ev, it, mModules.end());
}
/**
* This is a dangerous function when called at the wrong time.
* So we prefer an early abort with a stack trace.
* Indeed, incoming tport is global in sofia and will be overwritten
*/
static std::shared_ptr<tport_t> getIncomingTport(const msg_t *orig, Agent *ag) {
static tport_t* getIncomingTport(const msg_t *orig, Agent *ag) {
tport_t *primaries=nta_agent_tports(ag->getSofiaAgent());
tport_t *tport=tport_delivered_by(primaries,orig);
if (!tport) LOGA("tport not found");
return shared_ptr<tport_t>(tport_ref(tport), tport_unref);
return tport;
}
int Agent::onIncomingMessage(msg_t *msg, const sip_t *sip) {
if (mTerminating) {
// Avoid throwing a bad weak pointer on GatewayAdapter destruction
......@@ -790,10 +788,9 @@ int Agent::onIncomingMessage(msg_t *msg, const sip_t *sip) {
return -1;
}
// Assuming sip is derived from msg
shared_ptr<MsgSip> ms(new MsgSip(msg));
shared_ptr<MsgSip> ms=make_shared<MsgSip>(msg);
if (sip->sip_request) {
auto inTport=getIncomingTport(msg, this);
auto ev = make_shared<RequestSipEvent>(shared_from_this(), ms, inTport);
auto ev = make_shared<RequestSipEvent>(shared_from_this(), ms,getIncomingTport(msg,this));
sendRequestEvent(ev);
} else {
auto ev = make_shared<ResponseSipEvent>(shared_from_this(), ms);
......@@ -833,7 +830,7 @@ void Agent::stopTimer(su_timer_t *t) {
void Agent::send(const shared_ptr<MsgSip> &ms, url_string_t const *u, tag_type_t tag, tag_value_t value, ...) {
ta_list ta;
ta_start(ta, tag, value);
msg_t* msg = msg_dup(ms->getMsg());
msg_t* msg = msg_ref_create(ms->getMsg());
nta_msg_tsend(mAgent, msg, u, ta_tags(ta),TAG_END());
ta_end(ta);
}
......@@ -885,7 +882,7 @@ void Agent::reply(const shared_ptr<MsgSip> &ms, int status, char const *phrase,
incrReplyStat(status);
ta_list ta;
ta_start(ta, tag, value);
msg_t* msg = ms->createOrigMsgRef();
msg_t* msg = msg_ref_create(ms->getMsg());
nta_msg_treply(mAgent, msg, status, phrase, ta_tags(ta));
ta_end(ta);
}
......
......@@ -27,57 +27,66 @@
using namespace ::std;
void MsgSip::defineMsg(msg_t *msg) {
mMsg = msg_copy(msg);
msg_addr_copy(mMsg, msg);
mSip = sip_object(mMsg);
mHome = msg_home(mMsg);
mOriginal = false;
mSipAttr = make_shared<SipAttributes>(mSip);
void MsgSip::assignMsg(msg_t *msg) {
mMsg = msg_ref_create(msg);
mSipAttr = make_shared<SipAttributes>(getSip());
}
MsgSip::MsgSip(msg_t *msg) {
// LOGD("New MsgSip %p with reference to msg %p", this, msg);
mOriginalMsg = msg_ref_create(msg);
defineMsg(mOriginalMsg);
mOriginal = true;
assignMsg(msg);
}
/*Invoking the copy constructor of MsgSip implies the deep copy of the underlying msg_t */
MsgSip::MsgSip(const MsgSip &msgSip) {
// LOGD("New MsgSip %p with swallow copy %p of msg %p", this, mMsg, msgSip.mMsg);
msgSip.serialize();
defineMsg(msgSip.mMsg);
mOriginalMsg = msg_ref_create(msgSip.mOriginalMsg);
}
MsgSip::MsgSip(const MsgSip &msgSip, msg_t *msg) {
defineMsg(msg);
mOriginalMsg = msg_ref_create(msgSip.mOriginalMsg);
msg_t *freshCopy=msg_dup(msgSip.mMsg);
assignMsg(freshCopy);
msg_destroy(freshCopy);
}
const char * MsgSip::print() {
//make sure the message is serialized before showing it; it can be very confusing.
size_t msg_size;
msg_serialize(mMsg,(msg_pub_t*)mSip);
return msg_as_string(mHome, mMsg, NULL, 0, &msg_size);
msg_serialize(mMsg,(msg_pub_t*)getSip());
return msg_as_string(getHome(), mMsg, NULL, 0, &msg_size);
}
MsgSip::~MsgSip() {
//LOGD("Destroy MsgSip %p", this);
msg_destroy(mMsg);
msg_destroy(mOriginalMsg);
}
SipEvent::SipEvent(const shared_ptr<MsgSip> msgSip) :
SipEvent::SipEvent(const shared_ptr<IncomingAgent> &inAgent, const shared_ptr<MsgSip> msgSip) :
mCurrModule(NULL), mMsgSip(msgSip), mState(STARTED) {
LOGD("New SipEvent %p", this);
mIncomingAgent = inAgent;
mAgent=inAgent->getAgent();
shared_ptr<IncomingTransaction> it=dynamic_pointer_cast<IncomingTransaction>(inAgent);
if (it){
mOutgoingAgent = it->mOutgoing;
}else{
mOutgoingAgent = inAgent->getAgent()->shared_from_this();
}
}
SipEvent::SipEvent(const shared_ptr<OutgoingAgent> &outAgent, const shared_ptr<MsgSip> msgSip) :
mCurrModule(NULL), mMsgSip(msgSip), mState(STARTED) {
LOGD("New SipEvent %p", this);
mOutgoingAgent = outAgent;
mAgent=outAgent->getAgent();
shared_ptr<OutgoingTransaction> ot=dynamic_pointer_cast<OutgoingTransaction>(outAgent);
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;
}else mIncomingAgent=mAgent->shared_from_this();
}
SipEvent::SipEvent(const SipEvent &sipEvent) :
mCurrModule(sipEvent.mCurrModule), mMsgSip(sipEvent.mMsgSip), mIncomingAgent(sipEvent.mIncomingAgent), mOutgoingAgent(sipEvent.mOutgoingAgent), mState(sipEvent.mState) {
mCurrModule(sipEvent.mCurrModule), mMsgSip(sipEvent.mMsgSip), mIncomingAgent(sipEvent.mIncomingAgent), mOutgoingAgent(sipEvent.mOutgoingAgent), mAgent(sipEvent.mAgent), mState(sipEvent.mState) {
LOGD("New SipEvent %p with state %s", this, stateStr(mState).c_str());
}
......@@ -87,11 +96,7 @@ SipEvent::~SipEvent() {
void SipEvent::flushLog(){
if (mEventLog){
Agent *agent=NULL;
if (mIncomingAgent) agent=mIncomingAgent->getAgent();
else if (mOutgoingAgent) agent=mOutgoingAgent->getAgent();
else LOGA("Event has no incoming nor outgoing agent.");
agent->logEvent(shared_from_this());
mAgent->logEvent(shared_from_this());
mEventLog.reset();
}
}
......@@ -108,6 +113,8 @@ void SipEvent::terminateProcessing() {
if (mState == STARTED || mState == SUSPENDED) {
mState = TERMINATED;
flushLog();
mIncomingAgent.reset();
mOutgoingAgent.reset();
} else if (mState==TERMINATED){
LOGE("SipEvent::terminateProcessing(): event is already terminated. Please fix your code.");
}else{
......@@ -142,24 +149,17 @@ std::shared_ptr<OutgoingTransaction> SipEvent::getOutgoingTransaction(){
}
RequestSipEvent::RequestSipEvent(shared_ptr<IncomingAgent> incomingAgent,
const shared_ptr<MsgSip> &msgSip,
shared_ptr<tport_t> inTport
const shared_ptr<MsgSip> &msgSip, tport_t *tport
) :
SipEvent(msgSip), mRecordRouteAdded(false) {
mIncomingTport=inTport;
mIncomingAgent = incomingAgent;
SipEvent(incomingAgent,msgSip), mRecordRouteAdded(false) {
shared_ptr<IncomingTransaction> it=dynamic_pointer_cast<IncomingTransaction>(incomingAgent);
if (it){
mOutgoingAgent = it->mOutgoing;
}else{
mOutgoingAgent = incomingAgent->getAgent()->shared_from_this();
}
if (tport)
mIncomingTport=shared_ptr<tport_t>(tport_ref(tport), tport_unref);
}
RequestSipEvent::RequestSipEvent(const shared_ptr<RequestSipEvent> &sipEvent) :
SipEvent(*sipEvent), mIncomingTport(sipEvent->mIncomingTport),
mRecordRouteAdded(sipEvent->mRecordRouteAdded) {
SipEvent(*sipEvent), mRecordRouteAdded(sipEvent->mRecordRouteAdded), mIncomingTport(sipEvent->mIncomingTport)
{
}
void RequestSipEvent::send(const shared_ptr<MsgSip> &msg, url_string_t const *u, tag_type_t tag, tag_value_t value, ...) {
......@@ -200,7 +200,6 @@ void RequestSipEvent::setIncomingAgent(const shared_ptr<IncomingAgent> &agent) {
shared_ptr<IncomingTransaction> RequestSipEvent::createIncomingTransaction() {
shared_ptr<IncomingTransaction> transaction = dynamic_pointer_cast<IncomingTransaction>(mIncomingAgent);
if (transaction == NULL) {
if (!mMsgSip->mOriginal) LOGA("It is too late to create an incoming transaction");
transaction = IncomingTransaction::create(mIncomingAgent->getAgent());
mIncomingAgent = transaction;
......@@ -257,13 +256,13 @@ RequestSipEvent::~RequestSipEvent() {
bool RequestSipEvent::findIncomingSubject(const char *searched) {
auto strlst = tport_delivered_from_subjects(mIncomingTport.get(), mMsgSip->mOriginalMsg);
auto strlst = tport_delivered_from_subjects(mIncomingTport.get(), mMsgSip->getMsg());
return !!tport_subject_search(searched, strlst);
}
const char *RequestSipEvent::findIncomingSubject(const list<string> &in) {
if (in.empty()) return NULL;
auto strlst = tport_delivered_from_subjects(mIncomingTport.get(), mMsgSip->mOriginalMsg);
auto strlst = tport_delivered_from_subjects(mIncomingTport.get(), mMsgSip->getMsg());
for (auto it =in.cbegin(); it != in.cend(); ++it) {
if (tport_subject_search(it->c_str(), strlst)) return it->c_str();
}
......@@ -273,17 +272,8 @@ const char *RequestSipEvent::findIncomingSubject(const list<string> &in) {
bool findIncomingSubject(const list<string> &in);
ResponseSipEvent::ResponseSipEvent(shared_ptr<OutgoingAgent> outgoingAgent, const shared_ptr<MsgSip> &msgSip) :
SipEvent(msgSip), mPopVia(false) {
mOutgoingAgent = outgoingAgent;
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
SipEvent(outgoingAgent,msgSip), mPopVia(false) {
mPopVia=mAgent!=mOutgoingAgent.get(); //we pop the via if sending through transaction
}
ResponseSipEvent::ResponseSipEvent(const shared_ptr<ResponseSipEvent> &sipEvent) :
......
......@@ -48,7 +48,6 @@ class MsgSip {
public:
MsgSip(msg_t *msg);
MsgSip(const MsgSip &msgSip);
MsgSip(const MsgSip &msgSip, msg_t *msg);
~MsgSip();
inline msg_t* getMsg() const {
......@@ -56,28 +55,20 @@ public:
}
inline sip_t* getSip() const {
return mSip;
return (sip_t*)msg_object(mMsg);
}
inline su_home_t* getHome() const {
return mHome;
return msg_home(mMsg);
}
void serialize()const{
msg_serialize(mMsg,(msg_pub_t*)mSip);
msg_serialize(mMsg,(msg_pub_t*)getSip());
}
msg_t *createOrigMsgRef() { return msg_ref_create(mOriginalMsg); }
inline std::shared_ptr<SipAttributes> getSipAttr() { return mSipAttr; }
const char *print();
private:
static inline std::shared_ptr<MsgSip> createFromOriginalMsg(msg_t *msg) {
return std::make_shared<MsgSip>(msg);
}
void defineMsg(msg_t *msg);
mutable su_home_t *mHome;
msg_t *mOriginalMsg;
void assignMsg(msg_t *msg);
msg_t *mMsg;
sip_t *mSip;
bool mOriginal;
std::shared_ptr<SipAttributes> mSipAttr;
};
......@@ -86,7 +77,8 @@ class SipEvent : public std::enable_shared_from_this<SipEvent>{
friend class Agent;
public:
SipEvent(const std::shared_ptr<MsgSip> msgSip);
SipEvent(const std::shared_ptr<IncomingAgent> &inAgent, const std::shared_ptr<MsgSip> msgSip);
SipEvent(const std::shared_ptr<OutgoingAgent> &outAgent, const std::shared_ptr<MsgSip> msgSip);
SipEvent(const SipEvent &sipEvent);
inline const std::shared_ptr<MsgSip> &getMsgSip() const {
......@@ -102,7 +94,6 @@ public:
inline void setMsgSip(std::shared_ptr<MsgSip> msgSip) {
mMsgSip = msgSip;
mMsgSip->mOriginal = false;
}
virtual void terminateProcessing();
......@@ -155,6 +146,7 @@ protected:
std::shared_ptr<IncomingAgent> mIncomingAgent;
std::shared_ptr<OutgoingAgent> mOutgoingAgent;
std::shared_ptr<EventLog> mEventLog;
Agent *mAgent;
enum State {
STARTED, SUSPENDED, TERMINATED,
......@@ -173,12 +165,9 @@ protected:
};
class RequestSipEvent: public SipEvent {
std::shared_ptr<tport_t> mIncomingTport;
public:
RequestSipEvent(std::shared_ptr<IncomingAgent> incomingAgent,
const std::shared_ptr<MsgSip> &msgSip,
std::shared_ptr<tport_t> inTport
);
const std::shared_ptr<MsgSip> &msgSip, tport_t *tport=NULL);
RequestSipEvent(const std::shared_ptr<RequestSipEvent> &sipEvent);
virtual void suspendProcessing();
......@@ -190,19 +179,20 @@ public:
virtual void reply(int status, char const *phrase, tag_type_t tag, tag_value_t value, ...);
virtual void setIncomingAgent(const std::shared_ptr<IncomingAgent> &agent);
std::shared_ptr<tport_t> getIncomingTport() {
return mIncomingTport;
}
~RequestSipEvent();
/** Find if incoming tport TLS client certificate contains a given entry */
bool findIncomingSubject(const char *searched);
const char *findIncomingSubject(const std::list<std::string> &in);
bool mRecordRouteAdded;
void unlinkTransactions();
const std::shared_ptr<tport_t> &getIncomingTport()const{
return mIncomingTport;
}
bool mRecordRouteAdded;
private:
void linkTransactions();
std::shared_ptr<tport_t> mIncomingTport;
};
class ResponseSipEvent: public SipEvent {
......
......@@ -62,8 +62,7 @@ void ForkCallContext::cancelOthers(const shared_ptr<BranchInfo> & br) {
shared_ptr<OutgoingTransaction> tr = brit->mTransaction;
if (brit->getStatus()<200 && tr)
tr->cancel();
removeBranch(brit);
removeBranch(brit);
}
}
}
......
......@@ -140,6 +140,7 @@ bool ForkContext::allBranchesAnswered(bool ignore503)const{
}
void ForkContext::removeBranch(const shared_ptr<BranchInfo> &br){
LOGD("ForkContext [%p] branch [%p] removed.",this,br.get());
mBranches.remove(br);
br->clear();
}
......@@ -184,7 +185,7 @@ void ForkContext::addBranch(const shared_ptr<RequestSipEvent> &ev, const string
ot->setProperty("BranchInfo",br);
onNewBranch(br);
mBranches.push_back(br);
LOGD("ForkContext [%p] new fork branch [%p]",this,br.get());
}
std::shared_ptr<ForkContext> ForkContext::get(const std::shared_ptr<IncomingTransaction> &tr){
......@@ -261,6 +262,10 @@ void ForkContext::onFinished() {
}
void ForkContext::setFinished(){
if (mFinishTimer){
/*already finishing, ignore*/
return;
}
if (mLateTimer){
su_timer_destroy(mLateTimer);
mLateTimer=NULL;
......
......@@ -179,10 +179,9 @@ void ForwardModule::onRequest(shared_ptr<RequestSipEvent> &ev) {
}
// Check self-forwarding
if (ev->getOutgoingAgent()!=NULL && getAgent()->isUs(dest->url_host, dest->url_port, false)) {
SLOGD << "Skipping forwarding of request to us "
<< url_as_string(ms->getHome(), dest) << "\n" << ms;
ev->reply(SIP_501_NOT_IMPLEMENTED, SIPTAG_SERVER_STR(getAgent()->getServerString()), TAG_END());
if (ev->getOutgoingAgent()!=NULL && getAgent()->isUs(dest->url_host, dest->url_port, true)) {
SLOGD << "Stopping request to us";
ev->terminateProcessing();
return;
}
......
......@@ -313,7 +313,7 @@ void MediaRelay::onResponse(shared_ptr<ResponseSipEvent> &ev) {
shared_ptr<RelayedCall> c;
// Handle SipEvent associated with a Stateful transaction
shared_ptr<OutgoingTransaction> ot = dynamic_pointer_cast<OutgoingTransaction>(ev->getOutgoingAgent());
shared_ptr<OutgoingTransaction> ot=dynamic_pointer_cast<OutgoingTransaction>(ev->getOutgoingAgent());
shared_ptr<IncomingTransaction> it=dynamic_pointer_cast<IncomingTransaction>(ev->getIncomingAgent());
if (ot != NULL) {
......@@ -329,7 +329,7 @@ void MediaRelay::onResponse(shared_ptr<ResponseSipEvent> &ev) {
}
}
}
if (it && (c = it->getProperty<RelayedCall>(getModuleName()))!=NULL){
//This is a response sent to the incoming transaction. Check for failure code, in which case the call context can be destroyed
//immediately.
......
......@@ -345,14 +345,13 @@ public:
const shared_ptr<MsgSip> &ms = mEv->getMsgSip();
time_t now = getCurrentTime();
if (r){
addEventLogRecordFound(mEv, mContact);
mModule->reply(mEv, 200, "Registration successful", r->getContacts(ms->getHome(), now));
const sip_expires_t *expires=mEv->getMsgSip()->getSip()->sip_expires;
if (mContact && expires && expires->ex_delta > 0) {
LateForkApplier::onContactRegistered(mModule->getAgent(), mContact, mPath, r, mSipFrom->a_url);
}
addEventLogRecordFound(mEv, mContact);
}else{
LOGE("OnRequestBindListener::onRecordFound(): Record is null");
mModule->reply(mEv,SIP_480_TEMPORARILY_UNAVAILABLE);
......
......@@ -623,24 +623,6 @@ void ModuleRouter::onRequest(shared_ptr<RequestSipEvent> &ev) {
}
}
}
if (sip->sip_request->rq_method == sip_method_ack) {
//Seems very complex: maybe it could be simpler.
sip_route_t *route = sip->sip_route;
bool routeAck=false;
while (route) {
if (!mAgent->isUs(route->r_url, true)) {
routeAck=true;
break;
}
route=route->r_next;
}
const char *req_host = sip->sip_request->rq_url->url_host;
if (!routeAck && !ModuleToolbox::isNumeric(req_host)) {
LOGD("We are the destination of this ACK, stopped.");
ev->terminateProcessing();
return;
}
}
}
void ModuleRouter::onResponse(shared_ptr<ResponseSipEvent> &ev) {
......
......@@ -423,7 +423,6 @@ void Transcoder::processAck(TranscodedCall *ctx, shared_ptr<RequestSipEvent> &ev
void Transcoder::onRequest(shared_ptr<RequestSipEvent> &ev) {
const shared_ptr<MsgSip> &ms = ev->getMsgSip();
msg_t *msg = ms->getMsg();
sip_t *sip = ms->getSip();
if (sip->sip_request->rq_method == sip_method_invite) {
......@@ -462,8 +461,6 @@ void Transcoder::onRequest(shared_ptr<RequestSipEvent> &ev) {
} else {
//all other requests go through
}
ev->setMsgSip(make_shared<MsgSip>(*ms,msg));
}
int Transcoder::handleAnswer(TranscodedCall *ctx, shared_ptr<SipEvent> ev) {
......
......@@ -89,7 +89,7 @@ void OutgoingTransaction::send(const shared_ptr<MsgSip> &ms, url_string_t const
LOGD("Message is sent through an outgoing transaction.");
if (!mOutgoing){
msg_t* msg = msg_dup(ms->getMsg());
msg_t* msg = msg_ref_create(ms->getMsg());
ta_start(ta, tag, value);
mOutgoing = nta_outgoing_mcreate(mAgent->mAgent, OutgoingTransaction::_callback, (nta_outgoing_magic_t*) this, u, msg, ta_tags(ta),TAG_END());
ta_end(ta);
......@@ -150,8 +150,8 @@ shared_ptr<IncomingTransaction> IncomingTransaction::create(Agent *agent){
}
void IncomingTransaction::handle(const shared_ptr<MsgSip> &ms) {
msg_t* msg = ms->mOriginalMsg;
msg_ref_create(msg);
msg_t* msg = ms->getMsg();
msg=msg_ref_create(msg);
mIncoming = nta_incoming_create(mAgent->mAgent, NULL, msg, sip_object(msg), TAG_END());
if (mIncoming != NULL) {
nta_incoming_bind(mIncoming, IncomingTransaction::_callback, (nta_incoming_magic_t*) this);
......@@ -182,7 +182,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.
msg_t* msg = msg_ref_create(ms->getMsg()); //need to increment refcount of the message because mreply will decrement it.
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) {
......@@ -214,9 +214,7 @@ int IncomingTransaction::_callback(nta_incoming_magic_t *magic, nta_incoming_t *
if (sip != NULL) {
msg_t *msg = nta_incoming_getrequest_ackcancel(it->mIncoming);
auto ev = make_shared<RequestSipEvent>(it->shared_from_this(),
MsgSip::createFromOriginalMsg(msg),
shared_ptr<tport_t>() /* no access to nta_agent: may put tport in transaction if needed */
);
make_shared<MsgSip>(msg));
msg_destroy(msg);
it->mAgent->sendRequestEvent(ev);
if (sip->sip_request && sip->sip_request->rq_method == sip_method_cancel) {
......
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