reworked SST + B2BUA implementation

- B2BUA app with SIP Session Timer (SST) now can also use UPDATE
  (see session_refresh_method in sst_b2b.conf)

- if re-INVITE is used, normal SDP OA (INVITE+SDP/200+SDP) is done
  using last established SDP (instead of delayed SDP negotiation
  and SDP ping-pong)

- SDP is compared only after o= line (no SDP ping-pong with UAs which
  always increase SDP version)
sayer/1.4-spce2.6
Stefan Sayer 16 years ago
parent 903e909f8b
commit 90cccb3383

@ -181,7 +181,7 @@ void AnnounceTransferDialog::onSipRequest(const AmSipRequest& req)
}
void AnnounceTransferDialog::onSipReply(const AmSipReply& rep, int old_dlg_status) {
void AnnounceTransferDialog::onSipReply(const AmSipReply& rep, int old_dlg_status, const string& trans_method) {
if ((status==Transfering ||status==Hangup) &&
dlg.get_uac_trans_method(rep.cseq) == "REFER") {
if (rep.code >= 300) {
@ -191,7 +191,7 @@ void AnnounceTransferDialog::onSipReply(const AmSipReply& rep, int old_dlg_statu
}
}
AmSession::onSipReply(rep, old_dlg_status);
AmSession::onSipReply(rep, old_dlg_status, trans_method);
}
void AnnounceTransferDialog::onBye(const AmSipRequest& req)

@ -72,7 +72,7 @@ public:
void startSession();
void onBye(const AmSipRequest& req);
void onSipRequest(const AmSipRequest& req);
void onSipReply(const AmSipReply& rep, int old_dlg_status);
void onSipReply(const AmSipReply& rep, int old_dlg_status, const string& trans_method);
void onDtmf(int event, int duration_msec) {}
void process(AmEvent* event);

@ -314,15 +314,15 @@ inline UACAuthCred* AuthB2BCalleeSession::getCredentials() {
return &credentials;
}
void AuthB2BCalleeSession::onSipReply(const AmSipReply& reply, int old_dlg_status) {
void AuthB2BCalleeSession::onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method) {
if (NULL == auth) {
AmB2BCalleeSession::onSipReply(reply,old_dlg_status);
AmB2BCalleeSession::onSipReply(reply,old_dlg_status,trans_method);
return;
}
unsigned int cseq_before = dlg.cseq;
if (!auth->onSipReply(reply, old_dlg_status)) {
AmB2BCalleeSession::onSipReply(reply,old_dlg_status);
if (!auth->onSipReply(reply, old_dlg_status,trans_method)) {
AmB2BCalleeSession::onSipReply(reply,old_dlg_status,trans_method);
} else {
if (cseq_before != dlg.cseq) {
DBG("uac_auth consumed reply with cseq %d and resent with cseq %d; "

@ -95,7 +95,7 @@ class AuthB2BCalleeSession
AmSessionEventHandler* auth;
protected:
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method);
void onSendRequest(const string& method, const string& content_type,
const string& body, string& hdrs, int flags, unsigned int cseq);

@ -862,10 +862,10 @@ void ConferenceDialog::onSipRequest(const AmSipRequest& req)
return;
}
void ConferenceDialog::onSipReply(const AmSipReply& reply, int old_dlg_status)
void ConferenceDialog::onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method)
{
int status = dlg.getStatus();
AmSession::onSipReply(reply,old_dlg_status);
AmSession::onSipReply(reply, old_dlg_status, trans_method);
DBG("ConferenceDialog::onSipReply: code = %i, reason = %s\n, status = %i\n",
reply.code,reply.reason.c_str(),dlg.getStatus());

@ -153,7 +153,8 @@ public:
void onBye(const AmSipRequest& req);
void onSipRequest(const AmSipRequest& req);
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method);
#ifdef WITH_SAS_TTS
void onZRTPEvent(zrtp_event_t event, zrtp_stream_ctx_t *stream_ctx);

@ -287,7 +287,7 @@ void DSMCall::onSipRequest(const AmSipRequest& req) {
AmB2BCallerSession::onSipRequest(req);
}
void DSMCall::onSipReply(const AmSipReply& reply, int old_dlg_status) {
void DSMCall::onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method) {
if (checkVar(DSM_ENABLE_REPLY_EVENTS, DSM_TRUE)) {
map<string, string> params;
@ -318,7 +318,7 @@ void DSMCall::onSipReply(const AmSipReply& reply, int old_dlg_status) {
}
}
AmB2BCallerSession::onSipReply(reply,old_dlg_status);
AmB2BCallerSession::onSipReply(reply,old_dlg_status,trans_method);
if ((old_dlg_status < AmSipDialog::Connected) &&
(dlg.getStatus() == AmSipDialog::Disconnected)) {

@ -83,7 +83,7 @@ public:
void onDtmf(int event, int duration_msec);
void onSipRequest(const AmSipRequest& req);
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method);
void process(AmEvent* event);

@ -286,8 +286,10 @@ inline UACAuthCred* b2b_connectCalleeSession::getCredentials() {
return &credentials;
}
void b2b_connectCalleeSession::onSipReply(const AmSipReply& reply, int old_dlg_status) {
AmB2ABCalleeSession::onSipReply(reply, old_dlg_status);
void b2b_connectCalleeSession::onSipReply(const AmSipReply& reply,
int old_dlg_status,
const string& trans_method) {
AmB2ABCalleeSession::onSipReply(reply, old_dlg_status, trans_method);
if ((old_dlg_status == AmSipDialog::Pending)&&
(dlg.getStatus() == AmSipDialog::Disconnected)) {

@ -88,7 +88,8 @@ class b2b_connectCalleeSession
AmSipRequest invite_req;
protected:
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method);
public:
b2b_connectCalleeSession(const string& other_tag,

@ -90,7 +90,7 @@ void GWSession::onSipRequest(const AmSipRequest& req)
}
}
void GWSession::onSipReply(const AmSipReply& reply, int old_dlg_status) {
void GWSession::onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method) {
int status = dlg.getStatus();
DBG("GWSession::onSipReply: code = %i, reason = %s\n, status = %i\n",
reply.code,reply.reason.c_str(),dlg.getStatus());
@ -99,7 +99,7 @@ void GWSession::onSipReply(const AmSipReply& reply, int old_dlg_status) {
int ret=((mISDNChannel*)m_OtherLeg)->hangup();
}
DBG("GWSession::onSipReply calling parent\n");
AmSession::onSipReply(reply, old_dlg_status);
AmSession::onSipReply(reply, old_dlg_status, trans_method);
}
void GWSession::on_stop() {

@ -33,7 +33,7 @@ static GWSession* CallFromOutside(std::string &fromnumber, std::string &tonum
void onBye(const AmSipRequest& req);
//virtual void onSipEvent(AmSipEvent* sip_ev);
void onSipRequest(const AmSipRequest& req);
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method);
//virtual void onRtpTimeout();
//virtual void onSendRequest(const string& method, const string& content_type, const string& body, string& hdrs, int flags, unsigned int cseq);
//virtual void onSendReply(const AmSipRequest& req, unsigned int code,const string& reason,const string& content_type, const string& body,string& hdrs,int flags)

@ -749,11 +749,11 @@ void safe_Py_DECREF(PyObject* pyo) {
Py_DECREF(pyo);
}
void IvrDialog::onSipReply(const AmSipReply& r, int old_dlg_status) {
void IvrDialog::onSipReply(const AmSipReply& r, int old_dlg_status, const string& trans_method) {
PyObject* pyo = getPySipReply(r);
callPyEventHandler("onSipReply","(O)", pyo);
safe_Py_DECREF(pyo);
AmB2BSession::onSipReply(r,old_dlg_status);
AmB2BSession::onSipReply(r,old_dlg_status,trans_method);
}
void IvrDialog::onSipRequest(const AmSipRequest& r){

@ -149,7 +149,7 @@ class IvrDialog : public AmB2BCallerSession
void onOtherBye(const AmSipRequest& req);
bool onOtherReply(const AmSipReply& r);
void onSipReply(const AmSipReply& r,int old_dlg_status);
void onSipReply(const AmSipReply& r,int old_dlg_status, const string& trans_method);
void onSipRequest(const AmSipRequest& r);
void onRtpTimeout();

@ -369,9 +369,9 @@ bool SIPRegistration::registerExpired(time_t now_sec) {
return ((reg_begin+reg_expires) < (unsigned int)now_sec);
}
void SIPRegistration::onSipReply(const AmSipReply& reply, int old_dlg_status)
void SIPRegistration::onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method)
{
if ((seh!=NULL) && seh->onSipReply(reply, old_dlg_status))
if ((seh!=NULL) && seh->onSipReply(reply, old_dlg_status, trans_method))
return;
waiting_result = false;
@ -498,7 +498,7 @@ void SIPRegistrarClient::onRemoveRegistration(SIPRemoveRegistrationEvent* new_re
void SIPRegistrarClient::on_stop() { }
bool SIPRegistrarClient::onSipReply(const AmSipReply& rep) {
bool SIPRegistrarClient::onSipReply(const AmSipReply& rep, int old_dlg_status, const string& trans_method) {
DBG("got reply with tag '%s'\n", rep.local_tag.c_str());
if (instance()->hasRegistration(rep.local_tag)) {

@ -124,7 +124,7 @@ class SIPRegistration : public AmSipDialogEventHandler,
// CredentialHolder
UACAuthCred* getCredentials() { return &cred; }
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method);
void onSipRequest(const AmSipRequest& req) {}
void onInvite2xx(const AmSipReply&) {}
void onNoAck(unsigned int) {}
@ -192,7 +192,7 @@ class SIPRegistrarClient : public AmThread,
void invoke(const string& method,
const AmArg& args, AmArg& ret);
bool onSipReply(const AmSipReply& rep);
bool onSipReply(const AmSipReply& rep, int old_dlg_status, const string& trans_method);
int onLoad();
void run();

@ -132,25 +132,10 @@ void SSTB2BDialog::onInvite(const AmSipRequest& req)
recvd_req.insert(std::make_pair(req.cseq,req));
set_sip_relay_only(true);
DBG("##### connecting to <%s>",req.r_uri.c_str());
DBG("##### connecting to <%s> #####\n",req.r_uri.c_str());
connectCallee("<" + req.r_uri + ">", req.r_uri, true);
}
void SSTB2BDialog::sendReinvite(bool updateSDP, const string& headers) {
if (sip_relay_only) {
// we send empty reinvite
DBG("sending empty reinvite in callee session\n");
dlg.reinvite(headers, "", "");
} else {
AmB2BCallerSession::sendReinvite(updateSDP, headers);
}
// // we send empty reinvite
// dlg.reinvite(headers, "", "");
// we send reinvite with the last body we got from the other side
// last_otherleg_content_type, last_otherleg_body);
}
void SSTB2BDialog::process(AmEvent* ev)
{
AmB2BCallerSession::process(ev);
@ -171,7 +156,8 @@ void SSTB2BDialog::onSipRequest(const AmSipRequest& req) {
AmB2BCallerSession::onSipRequest(req);
}
void SSTB2BDialog::onSipReply(const AmSipReply& reply, int old_dlg_status)
void SSTB2BDialog::onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method)
{
TransMap::iterator t = relayed_req.find(reply.cseq);
bool fwd = t != relayed_req.end();
@ -179,10 +165,10 @@ void SSTB2BDialog::onSipReply(const AmSipReply& reply, int old_dlg_status)
DBG("onSipReply: %i %s (fwd=%i)\n",reply.code,reply.reason.c_str(),fwd);
DBG("onSipReply: content-type = %s\n",reply.content_type.c_str());
if (fwd) {
CALL_EVENT_H(onSipReply,reply, old_dlg_status);
CALL_EVENT_H(onSipReply,reply, old_dlg_status, trans_method);
}
AmB2BCallerSession::onSipReply(reply,old_dlg_status);
AmB2BCallerSession::onSipReply(reply,old_dlg_status, trans_method);
}
bool SSTB2BDialog::onOtherReply(const AmSipReply& reply)
@ -344,7 +330,8 @@ void SSTB2BCalleeSession::onSipRequest(const AmSipRequest& req) {
AmB2BCalleeSession::onSipRequest(req);
}
void SSTB2BCalleeSession::onSipReply(const AmSipReply& reply, int old_dlg_status)
void SSTB2BCalleeSession::onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method)
{
// call event handlers where it is not done
TransMap::iterator t = relayed_req.find(reply.cseq);
@ -352,17 +339,17 @@ void SSTB2BCalleeSession::onSipReply(const AmSipReply& reply, int old_dlg_status
DBG("onSipReply: %i %s (fwd=%i)\n",reply.code,reply.reason.c_str(),fwd);
DBG("onSipReply: content-type = %s\n",reply.content_type.c_str());
if(fwd) {
CALL_EVENT_H(onSipReply,reply, old_dlg_status);
CALL_EVENT_H(onSipReply,reply, old_dlg_status, trans_method);
}
if (NULL == auth) {
AmB2BCalleeSession::onSipReply(reply,old_dlg_status);
AmB2BCalleeSession::onSipReply(reply,old_dlg_status, trans_method);
return;
}
unsigned int cseq_before = dlg.cseq;
if (!auth->onSipReply(reply, old_dlg_status)) {
AmB2BCalleeSession::onSipReply(reply,old_dlg_status);
if (!auth->onSipReply(reply, old_dlg_status, trans_method)) {
AmB2BCalleeSession::onSipReply(reply, old_dlg_status, trans_method);
} else {
if (cseq_before != dlg.cseq) {
DBG("uac_auth consumed reply with cseq %d and resent with cseq %d; "
@ -390,13 +377,3 @@ void SSTB2BCalleeSession::onSendRequest(const string& method, const string& cont
body, hdrs, flags, cseq);
}
void SSTB2BCalleeSession::sendReinvite(bool updateSDP, const string& headers) {
if (sip_relay_only) {
// we send empty reinvite
DBG("sending empty reinvite in callee session\n");
dlg.reinvite(headers, "", "");
} else {
AmB2BCalleeSession::sendReinvite(updateSDP, headers);
}
}

@ -90,10 +90,9 @@ class SSTB2BDialog : public AmB2BCallerSession
void onInvite(const AmSipRequest& req);
void onCancel();
void sendReinvite(bool updateSDP, const string& headers);
protected:
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method);
void onSipRequest(const AmSipRequest& req);
protected:
@ -115,7 +114,8 @@ class SSTB2BCalleeSession
protected:
void onSipRequest(const AmSipRequest& req);
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method);
void onSendRequest(const string& method, const string& content_type,
const string& body, string& hdrs, int flags, unsigned int cseq);
@ -128,7 +128,5 @@ class SSTB2BCalleeSession
inline UACAuthCred* getCredentials();
void setAuthHandler(AmSessionEventHandler* h) { auth = h; }
void sendReinvite(bool updateSDP, const string& headers);
};
#endif

@ -173,11 +173,11 @@ void WebConferenceDialog::onSessionStart(const AmSipReply& rep) {
connectConference(dlg.user);
}
void WebConferenceDialog::onSipReply(const AmSipReply& reply, int old_dlg_status)
void WebConferenceDialog::onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method)
{
//int status = dlg.getStatus();
AmSession::onSipReply(reply,old_dlg_status);
AmSession::onSipReply(reply,old_dlg_status,trans_method);
DBG("reply: %u %s, old_dlg_status = %s, status = %s\n",
reply.code, reply.reason.c_str(),

@ -94,7 +94,7 @@ public:
~WebConferenceDialog();
void process(AmEvent* ev);
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method);
void onSessionStart(const AmSipRequest& req);
void onSessionStart(const AmSipReply& rep);
void onEarlySessionStart(const AmSipReply& rep);

@ -353,13 +353,13 @@ void AmB2ABCalleeSession::onSessionStart(const AmSipReply& rep) {
relayEvent(new B2ABConnectAudioEvent());
}
void AmB2ABCalleeSession::onSipReply(const AmSipReply& rep, int old_dlg_status) {
int status_before = old_dlg_status;//dlg.getStatus();
AmB2ABSession::onSipReply(rep, old_dlg_status);
void AmB2ABCalleeSession::onSipReply(const AmSipReply& rep,
int old_dlg_status,
const string& trans_method) {
AmB2ABSession::onSipReply(rep, old_dlg_status, trans_method);
int status = dlg.getStatus();
if ((status_before == AmSipDialog::Pending)&&
if ((old_dlg_status == AmSipDialog::Pending)&&
(status == AmSipDialog::Disconnected)) {
DBG("callee session creation failed. notifying caller session.\n");

@ -247,7 +247,8 @@ class AmB2ABCalleeSession: public AmB2ABSession
void onEarlySessionStart(const AmSipReply& rep);
void onSessionStart(const AmSipReply& rep);
void onSipReply(const AmSipReply& rep, int old_dlg_status);
void onSipReply(const AmSipReply& rep, int old_dlg_status,
const string& trans_method);
protected:
void onB2ABEvent(B2ABEvent* ev);

@ -90,6 +90,16 @@ void AmB2BSession::onB2BEvent(B2BEvent* ev)
assert(req_ev);
if(req_ev->forward){
if (req_ev->req.method == SIP_METH_INVITE &&
dlg.getUACInvTransPending()) {
// don't relay INVITE if INV trans pending
AmSipReply n_reply;
n_reply.code = 491;
n_reply.reason = "Request Pending";
n_reply.cseq = req_ev->req.cseq;
relayEvent(new B2BSipReplyEvent(n_reply, true, SIP_METH_INVITE));
return;
}
relaySip(req_ev->req);
}
@ -106,19 +116,21 @@ void AmB2BSession::onB2BEvent(B2BEvent* ev)
B2BSipReplyEvent* reply_ev = dynamic_cast<B2BSipReplyEvent*>(ev);
assert(reply_ev);
DBG("B2BSipReply: %i %s (fwd=%i)\n",reply_ev->reply.code,
reply_ev->reply.reason.c_str(),reply_ev->forward);
DBG("B2BSipReply: %i %s (fwd=%s)\n",reply_ev->reply.code,
reply_ev->reply.reason.c_str(),reply_ev->forward?"true":"false");
DBG("B2BSipReply: content-type = %s\n",reply_ev->reply.content_type.c_str());
if(reply_ev->forward){
std::map<int,AmSipRequest>::iterator t_req = recvd_req.find(reply_ev->reply.cseq);
std::map<int,AmSipRequest>::iterator t_req =
recvd_req.find(reply_ev->reply.cseq);
if (t_req != recvd_req.end()) {
relaySip(t_req->second,reply_ev->reply);
if(reply_ev->reply.code >= 200){
if( (t_req->second.method == "INVITE") &&
if( (t_req->second.method == SIP_METH_INVITE) &&
(reply_ev->reply.code == 487)){
terminateLeg();
@ -129,6 +141,24 @@ void AmB2BSession::onB2BEvent(B2BEvent* ev)
ERROR("Request with CSeq %u not found in recvd_req.\n",
reply_ev->reply.cseq);
}
} else {
// check whether not-forwarded (locally initiated)
// INV/UPD transaction changed session in other leg
if (SIP_IS_200_CLASS(reply_ev->reply.code) &&
(!reply_ev->reply.body.empty()) &&
(reply_ev->reply.method == SIP_METH_INVITE ||
reply_ev->reply.method == SIP_METH_UPDATE)) {
if (updateSessionDescription(reply_ev->reply.content_type,
reply_ev->reply.body)) {
if (dlg.getUACInvTransPending()) {
DBG("changed session, but UAC INVITE trans pending\n");
// todo(?): save until trans is finished?
return;
}
DBG("session description changed - refreshing\n");
sendEstablishedReInvite();
}
}
}
}
return;
@ -137,44 +167,6 @@ void AmB2BSession::onB2BEvent(B2BEvent* ev)
terminateLeg();
break;
case B2BMsgBody:
{
if (!sip_relay_only) {
ERROR("relayed message body received but not in sip_relay_only mode\n");
return;
}
B2BMsgBodyEvent* body_ev = dynamic_cast<B2BMsgBodyEvent*>(ev);
assert(body_ev);
DBG("received B2B Msg body event; is_offer=%s, r_cseq=%d\n",
body_ev->is_offer?"true":"false", body_ev->r_cseq);
if (body_ev->is_offer) {
// send INVITE with SDP
trans_ticket tt; // empty transaction ticket
relayed_body_req[dlg.cseq] = AmSipTransaction("INVITE", body_ev->r_cseq, tt);
if (dlg.reinvite("", body_ev->content_type, body_ev->body)) {
ERROR("sending reinvite with relayed body\n");
relayed_body_req.erase(dlg.cseq);
// TODO?: relay error back instead?
// tear down:
DBG("error sending reinvite - terminating this and the other leg\n");
terminateOtherLeg();
terminateLeg();
}
} else {
// is_answer - send 200 ACK
// todo: use that from uas_trans?
trans_ticket tt; // not used for ACK
AmSipTransaction trans("INVITE", body_ev->r_cseq, tt);
if (dlg.send_200_ack(trans, body_ev->content_type, body_ev->body,
"" /* hdrs - todo */, SIP_FLAGS_VERBATIM)) {
ERROR("sending ACK with SDP\n");
}
}
return;
}; break;
}
//ERROR("unknown event caught\n");
@ -189,7 +181,6 @@ void AmB2BSession::onSipRequest(const AmSipRequest& req)
if(!fwd)
AmSession::onSipRequest(req);
else {
//dlg.updateStatus(req);
updateRefreshMethod(req.hdrs);
recvd_req.insert(std::make_pair(req.cseq,req));
}
@ -197,73 +188,33 @@ void AmB2BSession::onSipRequest(const AmSipRequest& req)
relayEvent(new B2BSipRequestEvent(req,fwd));
}
void AmB2BSession::onSipReply(const AmSipReply& reply, int old_dlg_status)
void AmB2BSession::onSipReply(const AmSipReply& reply,
int old_dlg_status,
const string& trans_method)
{
updateRefreshMethod(reply.hdrs);
TransMap::iterator t = relayed_req.find(reply.cseq);
bool fwd = (t != relayed_req.end()) && (reply.code != 100);
DBG("onSipReply: %i %s (fwd=%i)\n",reply.code,reply.reason.c_str(),fwd);
DBG("onSipReply: %s -> %i %s (fwd=%s)\n",
trans_method.c_str(), reply.code,reply.reason.c_str(),fwd?"true":"false");
DBG("onSipReply: content-type = %s\n",reply.content_type.c_str());
if(fwd) {
updateRefreshMethod(reply.hdrs);
AmSipReply n_reply = reply;
n_reply.cseq = t->second.cseq;
//dlg.updateStatus(reply, false);
relayEvent(new B2BSipReplyEvent(n_reply,true));
relayEvent(new B2BSipReplyEvent(n_reply, true, t->second.method));
if(reply.code >= 200) {
if ((reply.code < 300) && (t->second.method == "INVITE")) {
if ((reply.code < 300) && (t->second.method == SIP_METH_INVITE)) {
DBG("not removing relayed INVITE transaction yet...\n");
} else
relayed_req.erase(t);
}
} else {
string trans_method = dlg.get_uac_trans_method(reply.cseq);
bool relay_body =
// is a reply to request we sent,
// even though we are in sip_relay_only mode
(sip_relay_only &&
// positive reply
(200 <= reply.code) && (reply.code < 300) &&
// with body
!reply.body.empty() &&
trans_method == SIP_METH_INVITE);
if (relay_body) {
// is it an answer to a relayed body, or an answer to empty re-INVITE?
TransMap::iterator rel_body_it = relayed_body_req.find(reply.cseq);
bool is_offer = (rel_body_it == relayed_body_req.end());
// answer to empty re-INVITE we have sent
relayEvent(new B2BMsgBodyEvent(reply.content_type, reply.body,
is_offer, is_offer ? reply.cseq : rel_body_it->second.cseq));
if (is_offer) {
// onSipReply from AmSession without do_200_ack in dlg.updateStatus(reply)
// todo (?): add do_200_ack flag to AmSession::onSipReply and call AmSession::onSipReply
CALL_EVENT_H(onSipReply,reply,old_dlg_status);
//int status = dlg.getStatus();
//dlg.updateStatus(reply, false);
if (old_dlg_status != dlg.getStatus())
DBG("Dialog status changed %s -> %s (stopped=%s) \n",
AmSipDialog::status2str[old_dlg_status],
AmSipDialog::status2str[dlg.getStatus()],
getStopped() ? "true" : "false");
else
DBG("Dialog status stays %s (stopped=%s)\n", AmSipDialog::status2str[old_dlg_status],
getStopped() ? "true" : "false");
} else {
relayed_body_req.erase(rel_body_it);
AmSession::onSipReply(reply, old_dlg_status);
}
} else {
AmSession::onSipReply(reply, old_dlg_status);
}
relayEvent(new B2BSipReplyEvent(reply,false));
AmSession::onSipReply(reply, old_dlg_status, trans_method);
relayEvent(new B2BSipReplyEvent(reply, false, trans_method));
}
}
@ -325,12 +276,97 @@ void AmB2BSession::onSessionTimeout() {
AmSession::onSessionTimeout();
}
void AmB2BSession::saveSessionDescription(const string& content_type,
const string& body) {
DBG("saving session description (%s, %.*s...)\n",
content_type.c_str(), 50, body.c_str());
established_content_type = content_type;
established_body = body;
const char* cmp_body_begin = body.c_str();
size_t cmp_body_length = body.length();
if (content_type == SIP_APPLICATION_SDP) {
// for SDP, skip v and o line
// (o might change even if SDP unchanged)
#define skip_line \
while (cmp_body_length-- && *cmp_body_begin != '\n') \
cmp_body_begin++; \
cmp_body_begin++; \
skip_line;
skip_line;
}
body_hash = hashlittle(cmp_body_begin, cmp_body_length, 0);
}
bool AmB2BSession::updateSessionDescription(const string& content_type,
const string& body) {
const char* cmp_body_begin = body.c_str();
size_t cmp_body_length = body.length();
if (content_type == SIP_APPLICATION_SDP) {
// for SDP, skip v and o line
// (o might change even if SDP unchanged)
skip_line;
skip_line;
}
#undef skip_line
uint32_t new_body_hash = hashlittle(cmp_body_begin, cmp_body_length, 0);
if (body_hash != new_body_hash) {
DBG("session description changed - saving (%s, %.*s...)\n",
content_type.c_str(), 50, body.c_str());
body_hash = new_body_hash;
established_content_type = content_type;
established_body = body;
return true;
}
return false;
}
int AmB2BSession::sendEstablishedReInvite() {
if (established_content_type.empty() || established_body.empty()) {
ERROR("trying to re-INVITE with saved description, but none saved\n");
return -1;
}
DBG("sending re-INVITE with saved session description\n");
return dlg.reinvite(get_100rel_hdr(reliable_1xx),
established_content_type, established_body);
}
bool AmB2BSession::refresh() {
// not in B2B mode
if (other_id.empty() ||
// UPDATE as refresh handled like normal session
refresh_method == REFRESH_UPDATE) {
return AmSession::refresh();
}
// refresh with re-INVITE
if (dlg.getUACInvTransPending()) {
DBG("INVITE transaction pending - not refreshing now\n");
return false;
}
return sendEstablishedReInvite() == 0;
}
void AmB2BSession::relaySip(const AmSipRequest& req)
{
if (req.method != "ACK") {
relayed_req[dlg.cseq] = AmSipTransaction(req.method,req.cseq,req.tt);
dlg.sendRequest(req.method,req.content_type, req.body, req.hdrs, SIP_FLAGS_VERBATIM);
// todo: relay error event back if sending fails
if ((req.method == SIP_METH_INVITE ||
req.method == SIP_METH_UPDATE) &&
!req.body.empty()) {
saveSessionDescription(req.content_type, req.body);
}
} else {
//its a (200) ACK
TransMap::iterator t = relayed_req.begin();
@ -344,9 +380,16 @@ void AmB2BSession::relaySip(const AmSipRequest& req)
ERROR("transaction for ACK not found in relayed requests\n");
return;
}
DBG("sending relayed ACK\n");
dlg.send_200_ack(AmSipTransaction(t->second.method, t->first,t->second.tt),
req.content_type, req.body, req.hdrs, SIP_FLAGS_VERBATIM);
if (!req.body.empty() && t->second.method == SIP_METH_INVITE) {
// delayed SDP negotiation - save SDP
saveSessionDescription(req.content_type, req.body);
}
relayed_req.erase(t);
}
}
@ -356,6 +399,13 @@ void AmB2BSession::relaySip(const AmSipRequest& orig, const AmSipReply& reply)
dlg.reply(orig,reply.code,reply.reason,
reply.content_type,
reply.body,reply.hdrs,SIP_FLAGS_VERBATIM);
if ((orig.method == SIP_METH_INVITE ||
orig.method == SIP_METH_UPDATE) &&
!reply.body.empty()) {
saveSessionDescription(reply.content_type, reply.body);
}
}
//
@ -411,7 +461,8 @@ void AmB2BCallerSession::onB2BEvent(B2BEvent* ev)
if ((!sip_relay_only) && sip_relay_early_media_sdp &&
reply.code>=180 && reply.code<=183 && (!reply.body.empty())) {
if (reinviteCaller(reply)) {
ERROR("re-INVITEing caller for early session - stopping this and other leg\n");
ERROR("re-INVITEing caller for early session - "
"stopping this and other leg\n");
terminateOtherLeg();
terminateLeg();
}
@ -500,7 +551,9 @@ void AmB2BCallerSession::connectCallee(const string& remote_party,
int AmB2BCallerSession::reinviteCaller(const AmSipReply& callee_reply)
{
return dlg.sendRequest("INVITE",callee_reply.content_type,callee_reply.body, "", SIP_FLAGS_VERBATIM);
return dlg.sendRequest(SIP_METH_INVITE,
callee_reply.content_type, callee_reply.body,
"" /* hdrs */, SIP_FLAGS_VERBATIM);
}
void AmB2BCallerSession::createCalleeSession() {
@ -572,12 +625,17 @@ void AmB2BCalleeSession::onB2BEvent(B2BEvent* ev)
dlg.remote_uri = co_ev->remote_uri;
if (co_ev->relayed_invite) {
relayed_req[dlg.cseq] = AmSipTransaction("INVITE", co_ev->r_cseq, trans_ticket());
relayed_req[dlg.cseq] =
AmSipTransaction(SIP_METH_INVITE, co_ev->r_cseq, trans_ticket());
}
dlg.sendRequest("INVITE",co_ev->content_type,co_ev->body,co_ev->hdrs,SIP_FLAGS_VERBATIM);
dlg.sendRequest(SIP_METH_INVITE,
co_ev->content_type, co_ev->body,
co_ev->hdrs, SIP_FLAGS_VERBATIM);
// todo: relay error event back if sending fails
saveSessionDescription(co_ev->content_type, co_ev->body);
return;
}

@ -30,6 +30,7 @@
#include "AmSession.h"
#include "AmSipDialog.h"
#include "sip/hash.h"
enum { B2BTerminateLeg,
B2BConnectLeg,
@ -65,18 +66,20 @@ struct B2BSipRequestEvent: public B2BSipEvent
B2BSipRequestEvent(const AmSipRequest& req, bool forward)
: B2BSipEvent(B2BSipRequest,forward),
req(req)
{}
{ }
};
/** \brief SIP reply in B2B session */
struct B2BSipReplyEvent: public B2BSipEvent
{
AmSipReply reply;
string trans_method;
B2BSipReplyEvent(const AmSipReply& reply, bool forward)
: B2BSipEvent(B2BSipReply,forward),
reply(reply)
{}
B2BSipReplyEvent(const AmSipReply& reply, bool forward,
string trans_method)
: B2BSipEvent(B2BSipReply,forward),
reply(reply), trans_method(trans_method)
{ }
};
/** \brief relay a message body to other leg in B2B session */
@ -84,17 +87,10 @@ struct B2BMsgBodyEvent : public B2BEvent {
string content_type;
string body;
bool is_offer;
unsigned int r_cseq;
B2BMsgBodyEvent(const string& content_type,
const string& body,
bool is_offer,
unsigned int r_cseq)
B2BMsgBodyEvent(const string& content_type,
const string& body)
: B2BEvent(B2BMsgBody),
content_type(content_type), body(body),
is_offer(is_offer), r_cseq(r_cseq) {
}
content_type(content_type), body(body) { }
~B2BMsgBodyEvent() { }
};
@ -124,7 +120,8 @@ struct B2BConnectEvent: public B2BEvent
/**
* \brief Base class for Sessions in B2BUA mode.
*
* It has two legs: Callee- and caller-leg.
* It has two legs as independent sessions:
* Callee- and caller-leg.
*/
class AmB2BSession: public AmSession
{
@ -134,32 +131,40 @@ class AmB2BSession: public AmSession
/** Tell if the session should
* process SIP request itself
* or only relay them.
* or only relay them (B2B mode).
*/
bool sip_relay_only;
/**
* Requests which
* have been relayed (sent)
* Requests which have been relayed
* from the other leg and sent as SIP
*/
TransMap relayed_req;
/**
* Requests which have been originated
* from local dialog but with
* relayed body
*/
TransMap relayed_body_req;
/** Requests received for relaying */
std::map<int,AmSipRequest> recvd_req;
/** content-type of established session */
string established_content_type;
/** body of established session */
string established_body;
/** hash of body (from o-line) */
uint32_t body_hash;
/** save current session description (SDP) */
void saveSessionDescription(const string& content_type, const string& body);
/** @return whether session has changed */
bool updateSessionDescription(const string& content_type, const string& body);
/** reset relation with other leg */
void clear_other();
/** Relay one event to the other side. */
virtual void relayEvent(AmEvent* ev);
/** send a relayed SIP Request */
void relaySip(const AmSipRequest& req);
/** send a relayed SIP Reply */
void relaySip(const AmSipRequest& orig, const AmSipReply& reply);
/** Terminate our leg and forget the other. */
@ -170,18 +175,27 @@ class AmB2BSession: public AmSession
/** @see AmSession */
void onSipRequest(const AmSipRequest& req);
void onSipReply(const AmSipReply& reply, int old_dlg_status);
void onSipReply(const AmSipReply& reply,
int old_dlg_status, const string& trans_method);
void onInvite2xx(const AmSipReply& reply);
void onSessionTimeout();
/** send re-INVITE with established session description
* @return 0 on success
*/
int sendEstablishedReInvite();
/** do session refresh */
bool refresh();
/** @see AmEventQueue */
void process(AmEvent* event);
/** B2BEvent handler */
virtual void onB2BEvent(B2BEvent* ev);
// Other leg received a BYE
/** handle BYE on other leg */
virtual void onOtherBye(const AmSipRequest& req);
/**

@ -36,7 +36,6 @@
#include "AmMediaProcessor.h"
#include "AmDtmfDetector.h"
#include "AmPlayoutBuffer.h"
#include "AmSipHeaders.h"
#ifdef WITH_ZRTP
#include "AmZRTP.h"
@ -774,9 +773,10 @@ void AmSession::onSipRequest(const AmSipRequest& req)
}
}
void AmSession::onSipReply(const AmSipReply& reply, int old_dlg_status)
void AmSession::onSipReply(const AmSipReply& reply,
int old_dlg_status, const string& trans_method)
{
CALL_EVENT_H(onSipReply,reply,old_dlg_status);
CALL_EVENT_H(onSipReply, reply, old_dlg_status, trans_method);
updateRefreshMethod(reply.hdrs);
@ -786,7 +786,8 @@ void AmSession::onSipReply(const AmSipReply& reply, int old_dlg_status)
AmSipDialog::status2str[dlg.getStatus()],
sess_stopped.get() ? "true" : "false");
else
DBG("Dialog status stays %s (stopped=%s)\n", AmSipDialog::status2str[old_dlg_status],
DBG("Dialog status stays %s (stopped=%s)\n",
AmSipDialog::status2str[old_dlg_status],
sess_stopped.get() ? "true" : "false");
@ -953,7 +954,7 @@ void AmSession::onInvite(const AmSipRequest& req)
acceptAudio(req.body,req.hdrs,&sdp_reply);
if(dlg.reply(req,200,"OK",
"application/sdp",sdp_reply) != 0)
SIP_APPLICATION_SDP, sdp_reply) != 0)
throw AmSession::Exception(500,"could not send response");
}catch(const AmSession::Exception& e){
@ -1103,20 +1104,26 @@ void AmSession::updateRefreshMethod(const string& headers) {
}
}
void AmSession::refresh() {
bool AmSession::refresh() {
if (refresh_method == REFRESH_UPDATE) {
DBG("Refreshing session with UPDATE\n");
sendUpdate("", "", "");
return sendUpdate("", "", "") == 0;
} else {
if (dlg.getUACInvTransPending()) {
DBG("INVITE transaction pending - not refreshing now\n");
return false;
}
DBG("Refreshing session with re-INVITE\n");
sendReinvite(true);
return sendReinvite(true) == 0;
}
}
void AmSession::sendUpdate(const string &cont_type, const string &body,
int AmSession::sendUpdate(const string &cont_type, const string &body,
const string &hdrs)
{
dlg.update(cont_type, body, hdrs);
return dlg.update(cont_type, body, hdrs);
}
void AmSession::sendPrack(const string &sdp_offer,
@ -1141,32 +1148,16 @@ string AmSession::sid4dbg()
return dbg;
}
static inline string get_100rel_hdr(unsigned char reliable_1xx)
{
switch(reliable_1xx) {
case REL100_SUPPORTED:
return SIP_HDR_COLSP(SIP_HDR_SUPPORTED) SIP_EXT_100REL CRLF;
case REL100_REQUIRE:
return SIP_HDR_COLSP(SIP_HDR_REQUIRE) SIP_EXT_100REL CRLF;
default:
ERROR("BUG: unexpected reliability switch value of '%d'.\n",
reliable_1xx);
case 0:
break;
}
return "";
}
void AmSession::sendReinvite(bool updateSDP, const string& headers)
int AmSession::sendReinvite(bool updateSDP, const string& headers)
{
if (updateSDP) {
RTPStream()->setLocalIP(AmConfig::LocalIP);
string sdp_body;
sdp.genResponse(advertisedIP(), RTPStream()->getLocalPort(), sdp_body);
dlg.reinvite(headers + get_100rel_hdr(reliable_1xx), "application/sdp",
return dlg.reinvite(headers + get_100rel_hdr(reliable_1xx), SIP_APPLICATION_SDP,
sdp_body);
} else {
dlg.reinvite(headers + get_100rel_hdr(reliable_1xx), "", "");
return dlg.reinvite(headers + get_100rel_hdr(reliable_1xx), "", "");
}
}
@ -1181,7 +1172,7 @@ int AmSession::sendInvite(const string& headers)
// Generate SDP.
string sdp_body;
sdp.genRequest(advertisedIP(), RTPStream()->getLocalPort(), sdp_body);
return dlg.invite(headers + get_100rel_hdr(reliable_1xx), "application/sdp",
return dlg.invite(headers + get_100rel_hdr(reliable_1xx), SIP_APPLICATION_SDP,
sdp_body);
}

@ -34,6 +34,7 @@
#include "AmRtpAudio.h"
#include "AmDtmfDetector.h"
#include "AmSipMsg.h"
#include "AmSipHeaders.h"
#include "AmSipDialog.h"
#include "AmSipEvent.h"
#include "AmApi.h"
@ -360,13 +361,13 @@ public:
string* sdp_reply);
/** refresh the session - re-INVITE or UPDATE*/
virtual void refresh();
virtual bool refresh();
/** send an UPDATE in the session */
virtual void sendUpdate(const string &cont_type, const string &body, const string &hdrs);
virtual int sendUpdate(const string &cont_type, const string &body, const string &hdrs);
/** send a Re-INVITE (if connected) */
virtual void sendReinvite(bool updateSDP = true, const string& headers = "");
virtual int sendReinvite(bool updateSDP = true, const string& headers = "");
/** send an INVITE */
virtual int sendInvite(const string& headers = "");
@ -521,7 +522,8 @@ public:
virtual void onSipRequest(const AmSipRequest& req);
/** Entry point for SIP Replies */
virtual void onSipReply(const AmSipReply& reply, int old_dlg_status);
virtual void onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method);
/** 2xx reply has been received for an INVITE transaction */
virtual void onInvite2xx(const AmSipReply& reply);
@ -586,6 +588,7 @@ public:
// The IP address to put as c= in SDP bodies and to use for Contact:.
string advertisedIP();
/** format session id for debugging */
string sid4dbg();
};
@ -598,6 +601,22 @@ inline AmRtpAudio* AmSession::RTPStream() {
return _rtp_str.get();
}
static inline string get_100rel_hdr(unsigned char reliable_1xx)
{
switch(reliable_1xx) {
case REL100_SUPPORTED:
return SIP_HDR_COLSP(SIP_HDR_SUPPORTED) SIP_EXT_100REL CRLF;
case REL100_REQUIRE:
return SIP_HDR_COLSP(SIP_HDR_REQUIRE) SIP_EXT_100REL CRLF;
default:
ERROR("BUG: unexpected reliability switch value of '%d'.\n",
reliable_1xx);
case 0:
break;
}
return "";
}
#endif
/** EMACS **

@ -43,7 +43,8 @@ bool AmSessionEventHandler::onSipRequest(const AmSipRequest&)
return false;
}
bool AmSessionEventHandler::onSipReply(const AmSipReply& reply, int old_dlg_status)
bool AmSessionEventHandler::onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method)
{
return false;
}

@ -66,7 +66,8 @@ public:
virtual bool process(AmEvent*);
virtual bool onSipRequest(const AmSipRequest&);
virtual bool onSipReply(const AmSipReply&, int old_dlg_status);
virtual bool onSipReply(const AmSipReply&, int old_dlg_status,
const string& trans_method);
virtual bool onSipReqTimeout(const AmSipRequest &);
virtual bool onSipRplTimeout(const AmSipRequest &, const AmSipReply &);

@ -226,6 +226,7 @@ void AmSipDialog::updateStatus(const AmSipReply& reply)
AmSipTransaction& t = t_it->second;
int old_dlg_status = status;
string trans_method = t.method;
// rfc3261 12.1
// Dialog established only by 101-199 or 2xx
@ -240,7 +241,7 @@ void AmSipDialog::updateStatus(const AmSipReply& reply)
remote_tag = reply.remote_tag;
}
// allow route overwritting
// allow route overwriting
if ((status < Connected) && !reply.route.empty()) {
route = reply.route;
}
@ -250,7 +251,7 @@ void AmSipDialog::updateStatus(const AmSipReply& reply)
switch(status){
case Disconnecting:
if( t.method == "INVITE" ){
if (trans_method == SIP_METH_INVITE) {
if(reply.code == 487){
// CANCEL accepted
@ -270,7 +271,7 @@ void AmSipDialog::updateStatus(const AmSipReply& reply)
case Disconnected:
// only change status of dialog if reply
// to INVITE received
if(t.method == "INVITE"){
if (trans_method == SIP_METH_INVITE) {
if(reply.code < 200)
status = Pending;
else if(reply.code >= 300)
@ -289,7 +290,7 @@ void AmSipDialog::updateStatus(const AmSipReply& reply)
// TODO:
// - place this somewhere else.
// (probably in AmSession...)
if((reply.code < 300) && (t.method == "INVITE")) {
if((reply.code < 300) && (trans_method == SIP_METH_INVITE)) {
if(hdl) {
hdl->onInvite2xx(reply);
@ -304,7 +305,7 @@ void AmSipDialog::updateStatus(const AmSipReply& reply)
}
if(hdl)
hdl->onSipReply(reply, old_dlg_status);
hdl->onSipReply(reply, old_dlg_status, trans_method);
}
void AmSipDialog::uasTimeout(AmSipTimeoutEvent* to_ev)
@ -330,6 +331,19 @@ void AmSipDialog::uasTimeout(AmSipTimeoutEvent* to_ev)
to_ev->processed = true;
}
bool AmSipDialog::getUACTransPending() {
return !uac_trans.empty();
}
bool AmSipDialog::getUACInvTransPending() {
for (TransMap::iterator it=uac_trans.begin();
it != uac_trans.end(); it++) {
if (it->second.method == "INVITE")
return true;
}
return false;
}
string AmSipDialog::getContactHdr()
{
if(contact_uri.empty()) {

@ -74,7 +74,8 @@ class AmSipDialogEventHandler
virtual void onSipRequest(const AmSipRequest& req)=0;
/** Hook called when a reply has been received */
virtual void onSipReply(const AmSipReply& reply, int old_dlg_status)=0;
virtual void onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method)=0;
/** Hook called before a request is sent */
virtual void onSendRequest(const string& method,
@ -160,7 +161,11 @@ class AmSipDialog
AmSipDialog(AmSipDialogEventHandler* h=0);
~AmSipDialog();
bool getUACTransPending() { return !uac_trans.empty(); }
/** @return whether UAC transaction is pending */
bool getUACTransPending();
/** @return whether INVITE transaction is pending */
bool getUACInvTransPending();
int getStatus() { return status; }
void setStatus(int new_status);
@ -174,6 +179,7 @@ class AmSipDialog
void uasTimeout(AmSipTimeoutEvent* to_ev);
/** @return 0 on success */
int reply(const AmSipRequest& req,
unsigned int code,
const string& reason,
@ -182,34 +188,51 @@ class AmSipDialog
const string& hdrs = "",
int flags = 0);
/** @return 0 on success */
int sendRequest(const string& method,
const string& content_type = "",
const string& body = "",
const string& hdrs = "",
int flags = 0);
/** @return 0 on success */
int send_200_ack(const AmSipTransaction& t,
const string& content_type = "",
const string& body = "",
const string& hdrs = "",
int flags = 0);
/** @return 0 on success */
int bye(const string& hdrs = "");
/** @return 0 on success */
int cancel();
/** @return 0 on success */
int prack(const string &cont_type,
const string &body,
const string &hdrs);
/** @return 0 on success */
int update(const string &cont_type,
const string &body,
const string &hdrs);
/** @return 0 on success */
int reinvite(const string& hdrs,
const string& content_type,
const string& body);
/** @return 0 on success */
int invite(const string& hdrs,
const string& content_type,
const string& body);
/** @return 0 on success */
int refer(const string& refer_to,
int expires = -1);
/** @return 0 on success */
int transfer(const string& target);
int drop();

@ -41,4 +41,8 @@
#define SIP_EXT_100REL "100rel"
#define SIP_HDR_SESSION_EXPIRES_COMPACT "x"
#define SIP_IS_200_CLASS(code) ((code >= 200) && (code < 300))
#define SIP_APPLICATION_SDP "application/sdp"
#endif /* __AMSIPHEADERS_H__ */

@ -77,7 +77,8 @@ bool SessionTimer::onSipRequest(const AmSipRequest& req)
return false;
}
bool SessionTimer::onSipReply(const AmSipReply& reply, int old_dlg_status)
bool SessionTimer::onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method)
{
updateTimer(s,reply);
return false;
@ -327,6 +328,15 @@ void SessionTimer::setTimers(AmSession* s)
}
}
void SessionTimer::retryRefreshTimer(AmSession* s) {
DBG("Retrying session refresh timer: T-2s, tag '%s' \n",
s->getLocalTag().c_str());
UserTimer::instance()->
setTimer(ID_SESSION_REFRESH_TIMER, 2, s->getLocalTag());
}
void SessionTimer::removeTimers(AmSession* s)
{
UserTimer::instance()->
@ -342,7 +352,9 @@ void SessionTimer::onTimeoutEvent(AmTimeoutEvent* timeout_ev)
if (timer_id == ID_SESSION_REFRESH_TIMER) {
if (session_refresher == refresh_local) {
DBG("Session Timer: initiating session refresh\n");
s->refresh();
if (!s->refresh()) {
retryRefreshTimer(s);
}
} else {
DBG("need session refresh but remote session is refresher\n");
}

@ -120,6 +120,7 @@ class SessionTimer: public AmSessionEventHandler
void updateTimer(AmSession* s,const AmSipReply& reply);
void setTimers(AmSession* s);
void retryRefreshTimer(AmSession* s);
void removeTimers(AmSession* s);
string getReplyHeaders(const AmSipRequest& req);
@ -140,7 +141,8 @@ class SessionTimer: public AmSessionEventHandler
virtual bool process(AmEvent*);
virtual bool onSipRequest(const AmSipRequest&);
virtual bool onSipReply(const AmSipReply&, int old_dlg_status);
virtual bool onSipReply(const AmSipReply&, int old_dlg_status,
const string& trans_method);
virtual bool onSendRequest(const string& method,
const string& content_type,

@ -124,7 +124,7 @@ bool UACAuth::onSipRequest(const AmSipRequest& req)
return false;
}
bool UACAuth::onSipReply(const AmSipReply& reply, int old_dlg_status)
bool UACAuth::onSipReply(const AmSipReply& reply, int old_dlg_status, const string& trans_method)
{
bool processed = false;
if (reply.code==407 || reply.code==401) {

@ -138,7 +138,7 @@ class UACAuth : public AmSessionEventHandler
virtual bool process(AmEvent*);
virtual bool onSipEvent(AmSipEvent*);
virtual bool onSipRequest(const AmSipRequest&);
virtual bool onSipReply(const AmSipReply&, int old_dlg_status);
virtual bool onSipReply(const AmSipReply&, int old_dlg_status, const string& trans_method);
virtual bool onSendRequest(const string& method,
const string& content_type,

Loading…
Cancel
Save