- small enhancements and clean-ups for the SIP stack (work in progress...).

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1876 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Raphael Coeffic 16 years ago
parent 4a332caf8a
commit 7cae214d9c

@ -95,10 +95,4 @@ class AmEventHandler
virtual ~AmEventHandler() { };
};
/* class AmEventFactory */
/* { */
/* virtual AmEvent* generateEvent(const string& receiver_id) = 0; */
/* virtual ~AmEventFactory() { } */
/* }; */
#endif

@ -178,7 +178,7 @@ void AmMediaProcessor::stop() {
}
bool threads_stopped = true;
do {
usleep(10000);
usleep(10000); // 10ms
threads_stopped = true;
for (unsigned int i=0;i<num_threads;i++) {
if((threads[i] != NULL) &&(!threads[i]->is_stopped())) {

@ -671,19 +671,22 @@ void AmSession::onSipEvent(AmSipEvent* sip_ev)
AmSipRequestEvent* req_ev = dynamic_cast<AmSipRequestEvent*>(sip_ev);
if(req_ev) {
//onSipRequest(req_ev->req);
dlg.updateStatus(req_ev->req);
return;
}
AmSipReplyEvent* reply_ev = dynamic_cast<AmSipReplyEvent*>(sip_ev);
if(reply_ev) {
//onSipReply(reply_ev->reply);
dlg.updateStatus(reply_ev->reply);
return;
}
AmSipTimeoutEvent* to_ev = dynamic_cast<AmSipTimeoutEvent*>(sip_ev);
if(to_ev) {
dlg.uasTimeout(to_ev);
return;
}
ERROR("Unknown SIP Event");
}
@ -691,8 +694,6 @@ void AmSession::onSipRequest(const AmSipRequest& req)
{
CALL_EVENT_H(onSipRequest,req);
//dlg.updateStatus(req);
DBG("onSipRequest: method = %s\n",req.method.c_str());
if(req.method == "INVITE"){

@ -195,7 +195,7 @@ AmSession* AmSessionContainer::startSessionUAC(AmSipRequest& req, AmArg* session
AmSession* session = NULL;
try {
if((session = createSession(req, session_params)) != 0) {
session->dlg.updateStatusFromLocalRequest(req); // sets local tag as well
session->dlg.updateStatusFromLocalRequest(req);
session->setCallgroup(req.from_tag);
session->setNegotiateOnReply(true);

@ -97,15 +97,7 @@ void AmSipDialog::updateStatus(const AmSipRequest& req)
r_cseq = req.cseq;
r_cseq_i = true;
if(uas_trans.find(req.cseq) == uas_trans.end()){
DBG("req.tt = {%p,%p}\n",req.tt._bucket, req.tt._t);
uas_trans[req.cseq] = AmSipTransaction(req.method,req.cseq,req.tt);
}
// else {
// // shouldn't we drop those requests?
// // (CANCEL requests should have been handled before)
// }
uas_trans[req.cseq] = AmSipTransaction(req.method,req.cseq,req.tt);
// target refresh requests
if (req.from_uri.length() &&
@ -151,8 +143,6 @@ void AmSipDialog::updateStatusFromLocalRequest(const AmSipRequest& req)
local_uri = req.from_uri;
remote_party = req.to;
local_party = req.from;
//next_hop = req.next_hop;
}
}
@ -304,6 +294,34 @@ void AmSipDialog::updateStatus(const AmSipReply& reply)
hdl->onSipReply(reply, old_dlg_status);
}
void AmSipDialog::uasTimeout(AmSipTimeoutEvent* to_ev)
{
assert(to_ev);
switch(to_ev->type){
case AmSipTimeoutEvent::no2xxACK:
//TODO
DBG("Timeout: missing 2xx-ACK received\n");
break;
case AmSipTimeoutEvent::noErrorACK:
//TODO
DBG("Timeout: missing non-2xx-ACK\n");
break;
case AmSipTimeoutEvent::noPRACK:
//TODO
DBG("Timeout: missing PRACK\n");
break;
case AmSipTimeoutEvent::_noEv:
default:
break;
};
to_ev->processed = true;
}
string AmSipDialog::getContactHdr()
{
if(contact_uri.empty()) {

@ -42,6 +42,8 @@ using std::string;
#define SIP_FLAGS_VERBATIM 1 // send request verbatim,
// i.e. modify as little as possible
class AmSipTimeoutEvent;
/** \brief SIP transaction representation */
struct AmSipTransaction
{
@ -49,12 +51,8 @@ struct AmSipTransaction
unsigned int cseq;
trans_ticket tt;
// last reply code
// (sent or received)
//int reply_code;
AmSipTransaction(const string& method, unsigned int cseq, const trans_ticket& tt)
: method(method),
AmSipTransaction(const string& method, unsigned int cseq, const trans_ticket& tt)
: method(method),
cseq(cseq),
tt(tt)
{}
@ -164,6 +162,8 @@ class AmSipDialog
void updateStatus(const AmSipRequest& req);
void updateStatus(const AmSipReply& reply);
void uasTimeout(AmSipTimeoutEvent* to_ev);
int reply(const AmSipRequest& req,
unsigned int code,

@ -38,6 +38,31 @@ class AmSipEvent: public AmEvent
AmSipEvent(int id = -1)
: AmEvent(id)
{}
AmSipEvent(const AmSipEvent& ev)
: AmEvent(ev)
{}
};
class AmSipTimeoutEvent: public AmSipEvent
{
public:
enum EvType {
_noEv=0,
no2xxACK,
noErrorACK,
noPRACK
};
EvType type;
unsigned int cseq_num;
string cseq_method;
AmSipTimeoutEvent(EvType t, unsigned int cseq_num, const string& cseq_method)
: AmSipEvent(-1), type(t)
{}
};
/** \brief SIP request event */

@ -47,8 +47,9 @@
#include "AmApi.h"
#include "AmConfigReader.h"
#include "AmSipDispatcher.h"
#include "AmEventDispatcher.h"
#include "AmSipEvent.h"
bool SipCtrlInterface::accept_fr_without_totag = false;
int SipCtrlInterface::log_raw_messages = 3;
bool SipCtrlInterface::log_parsed_messages = true;
int SipCtrlInterface::udp_rcvbuf = -1;
@ -71,11 +72,11 @@ int SipCtrlInterface::load()
string cfgfile = AmConfig::ConfigurationFile.c_str();
if (file_exists(cfgfile) && !cfg.loadFile(cfgfile)) {
if (cfg.hasParameter("accept_fr_without_totag")) {
accept_fr_without_totag =
trans_layer::accept_fr_without_totag =
cfg.getParameter("accept_fr_without_totag") == "yes";
}
DBG("accept_fr_without_totag = %s\n",
accept_fr_without_totag?"yes":"no");
trans_layer::accept_fr_without_totag?"yes":"no");
if (cfg.hasParameter("log_raw_messages")) {
string msglog = cfg.getParameter("log_raw_messages");
@ -324,12 +325,11 @@ int SipCtrlInterface::send(const AmSipReply &rep)
#define DBG_PARAM(p)\
DBG("%s = <%s>\n",#p,p.c_str());
void SipCtrlInterface::handle_sip_request(trans_ticket* tt, sip_msg* msg)
void SipCtrlInterface::handle_sip_request(const trans_ticket& tt, sip_msg* msg)
{
assert(msg);
assert(msg->from && msg->from->p);
assert(msg->to && msg->to->p);
assert(tt);
AmSipRequest req;
@ -384,7 +384,7 @@ void SipCtrlInterface::handle_sip_request(trans_ticket* tt, sip_msg* msg)
req.cseq = get_cseq(msg)->num;
req.body = c2stlstr(msg->body);
req.tt = *tt;
req.tt = tt;
if (msg->content_type)
req.content_type = c2stlstr(msg->content_type->value);
@ -486,6 +486,50 @@ void SipCtrlInterface::handle_sip_reply(sip_msg* msg)
#undef DBG_PARAM
void SipCtrlInterface::timer_expired(sip_trans* trans, sip_timer_type tt)
{
assert(trans);
assert(trans->type == TT_UAS);
AmSipTimeoutEvent::EvType ev = AmSipTimeoutEvent::_noEv;
//TODO: send an event to the SIP Dialog
switch(tt){
case STIMER_H:
switch(trans->state){
case TS_TERMINATED_200: // missing 200-ACK
ev = AmSipTimeoutEvent::no2xxACK;
break;
case TS_COMPLETED: // missing error-ACK
ev = AmSipTimeoutEvent::noErrorACK;
break;
// TODO: missing PRACK
//case TS_???:
default:
ERROR("timer H expired / transaction in undefined state\n");
return;
}
default:
return;
}
assert(trans->msg);
assert(trans->to_tag.len);
assert(trans->msg->cseq && trans->msg->cseq->p);
sip_cseq* cseq = dynamic_cast<sip_cseq*>(trans->msg->cseq->p);
if(!cseq){
ERROR("missing CSeq\n");
return;
}
AmEventDispatcher::instance()->post(c2stlstr(trans->to_tag),
new AmSipTimeoutEvent(ev, cseq->num, c2stlstr(cseq->method_str)));
}
void SipCtrlInterface::prepare_routes_uac(const list<sip_header*>& routes, string& route_field)
{
if(!routes.empty()){

@ -59,7 +59,6 @@ public:
static unsigned int outbound_port;
static bool log_parsed_messages;
static int log_raw_messages;
static bool accept_fr_without_totag;
static int udp_rcvbuf;
SipCtrlInterface();
@ -96,8 +95,9 @@ public:
/**
* From sip_ua
*/
void handle_sip_request(trans_ticket* tt, sip_msg* msg);
void handle_sip_request(const trans_ticket& tt, sip_msg* msg);
void handle_sip_reply(sip_msg* msg);
void timer_expired(sip_trans* trans, sip_timer_type tt);
};

@ -132,8 +132,8 @@ class sip_trans
/**
* Retransmission buffer
* - UAS transaction: ACK
* - UAC transaction: final reply
* - UAC transaction: ACK
* - UAS transaction: last reply
*/
char* retr_buf;

@ -27,6 +27,8 @@
#ifndef _sip_ua_h_
#define _sip_ua_h_
#include "sip_trans.h"
class trans_ticket;
struct sip_msg;
@ -34,8 +36,12 @@ class sip_ua
{
public:
virtual ~sip_ua() {}
virtual void handle_sip_request(trans_ticket* tt, sip_msg* msg)=0;
virtual void handle_sip_request(const trans_ticket& tt, sip_msg* msg)=0;
virtual void handle_sip_reply(sip_msg* msg)=0;
// UAS timer expired (UAC timers generate a local 408)
virtual void timer_expired(sip_trans* trans, sip_timer_type tt)=0;
};
#endif

@ -59,6 +59,7 @@
*/
trans_layer* trans_layer::_instance = NULL;
bool trans_layer::accept_fr_without_totag = false;
trans_layer* trans_layer::instance()
{
@ -879,6 +880,10 @@ int trans_layer::cancel(trans_ticket* tt)
case TS_COMPLETED:
// final reply has been sent, but still no ACK:
// do nothing!!!
// TODO: switch to TS_CANCELLING??
// this would allow for sending the BYE as soon
// we get an ACK or a timeout (STIMER_H)...
bucket->unlock();
return 0;
@ -1043,8 +1048,7 @@ void trans_layer::received_msg(sip_msg* msg)
// the UA.
assert(ua);
DBG("Passing ACK to the UA.\n");
trans_ticket tt(t,bucket);
ua->handle_sip_request(&tt,msg);
ua->handle_sip_request(trans_ticket(t,bucket),msg);
DROP_MSG;
}
@ -1072,8 +1076,7 @@ void trans_layer::received_msg(sip_msg* msg)
// the UA.
assert(ua);
trans_ticket tt(t,bucket);
ua->handle_sip_request(&tt,msg);
ua->handle_sip_request(trans_ticket(t,bucket),msg);
// forget the msg: it will be
// owned by the new transaction
@ -1159,7 +1162,7 @@ int trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg* m
to_tag = ((sip_from_to*)msg->to->p)->tag;
if((t->msg->u.request->method != sip_request::CANCEL) && !to_tag.len){
DBG("To-tag missing in final reply (see sipctrl.conf?)\n");
if (!SipCtrlInterface::accept_fr_without_totag)
if (!trans_layer::accept_fr_without_totag)
return -1;
}
@ -1220,7 +1223,7 @@ int trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg* m
t->to_tag.s = new char[to_tag.len];
t->to_tag.len = to_tag.len;
memcpy((void*)t->to_tag.s,to_tag.s,to_tag.len);
}
}
goto pass_reply;
@ -1542,7 +1545,6 @@ void trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
case STIMER_D: // Completed: -> Terminated
case STIMER_K: // Completed: terminate transaction
case STIMER_J: // Completed: -> Terminated
case STIMER_H: // Completed: -> Terminated
case STIMER_I: // Confirmed: -> Terminated
case STIMER_L: // Terminated_200 -> Terminated
@ -1551,10 +1553,15 @@ void trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
// else, send ACK & BYE.
tr->clear_timer(type);
tr->state = TS_TERMINATED;
bucket->remove_trans(tr);
break;
case STIMER_H: // Completed: -> Terminated
tr->clear_timer(type);
ua->timer_expired(tr,STIMER_H);
bucket->remove_trans(tr);
break;
case STIMER_E: // Trying/Proceeding: (re-)send request
case STIMER_G: // Completed: (re-)send response

@ -27,8 +27,6 @@
#ifndef _trans_layer_h_
#define _trans_layer_h_
//#include "AmApi.h"
#include "cstring.h"
#include <list>
@ -134,6 +132,13 @@ class trans_layer
public:
/**
* Config option: if true, final replies without
* a to-tag will be accepted for requests which do not
* create a dialog.
*/
static bool accept_fr_without_totag;
/**
* Retrieve the singleton instance.
*/

Loading…
Cancel
Save