Author: rco
Date: 2010-04-30 17:17:01 +0200 (Fri, 30 Apr 2010)
New Revision: 1876
Modified:
trunk/core/AmEvent.h
trunk/core/AmMediaProcessor.cpp
trunk/core/AmSession.cpp
trunk/core/AmSessionContainer.cpp
trunk/core/AmSipDialog.cpp
trunk/core/AmSipDialog.h
trunk/core/AmSipEvent.h
trunk/core/SipCtrlInterface.cpp
trunk/core/SipCtrlInterface.h
trunk/core/sip/sip_trans.h
trunk/core/sip/sip_ua.h
trunk/core/sip/trans_layer.cpp
trunk/core/sip/trans_layer.h
Log:
- small enhancements and clean-ups for the SIP stack (work in progress...).
Modified: trunk/core/AmEvent.h
===================================================================
--- trunk/core/AmEvent.h 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/AmEvent.h 2010-04-30 15:17:01 UTC (rev 1876)
@@ -95,10 +95,4 @@
virtual ~AmEventHandler() { };
};
-/* class AmEventFactory */
-/* { */
-/* virtual AmEvent* generateEvent(const string& receiver_id) = 0; */
-/* virtual ~AmEventFactory() { } */
-/* }; */
-
#endif
Modified: trunk/core/AmMediaProcessor.cpp
===================================================================
--- trunk/core/AmMediaProcessor.cpp 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/AmMediaProcessor.cpp 2010-04-30 15:17:01 UTC (rev 1876)
@@ -178,7 +178,7 @@
}
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())) {
Modified: trunk/core/AmSession.cpp
===================================================================
--- trunk/core/AmSession.cpp 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/AmSession.cpp 2010-04-30 15:17:01 UTC (rev 1876)
@@ -671,19 +671,22 @@
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 @@
{
CALL_EVENT_H(onSipRequest,req);
- //dlg.updateStatus(req);
-
DBG("onSipRequest: method = %s\n",req.method.c_str());
if(req.method == "INVITE"){
Modified: trunk/core/AmSessionContainer.cpp
===================================================================
--- trunk/core/AmSessionContainer.cpp 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/AmSessionContainer.cpp 2010-04-30 15:17:01 UTC (rev 1876)
@@ -195,7 +195,7 @@
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);
Modified: trunk/core/AmSipDialog.cpp
===================================================================
--- trunk/core/AmSipDialog.cpp 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/AmSipDialog.cpp 2010-04-30 15:17:01 UTC (rev 1876)
@@ -97,16 +97,8 @@
r_cseq = req.cseq;
r_cseq_i = true;
+ uas_trans[req.cseq] = AmSipTransaction(req.method,req.cseq,req.tt);
- 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)
- // }
-
// target refresh requests
if (req.from_uri.length() &&
(req.method == "INVITE" ||
@@ -151,8 +143,6 @@
local_uri = req.from_uri;
remote_party = req.to;
local_party = req.from;
-
- //next_hop = req.next_hop;
}
}
@@ -304,6 +294,34 @@
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()) {
Modified: trunk/core/AmSipDialog.h
===================================================================
--- trunk/core/AmSipDialog.h 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/AmSipDialog.h 2010-04-30 15:17:01 UTC (rev 1876)
@@ -42,6 +42,8 @@
#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 @@
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 @@
void updateStatus(const AmSipRequest& req);
void updateStatus(const AmSipReply& reply);
+
+ void uasTimeout(AmSipTimeoutEvent* to_ev);
int reply(const AmSipRequest& req,
unsigned int code,
Modified: trunk/core/AmSipEvent.h
===================================================================
--- trunk/core/AmSipEvent.h 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/AmSipEvent.h 2010-04-30 15:17:01 UTC (rev 1876)
@@ -38,8 +38,33 @@
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 */
class AmSipRequestEvent: public AmSipEvent
{
Modified: trunk/core/SipCtrlInterface.cpp
===================================================================
--- trunk/core/SipCtrlInterface.cpp 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/SipCtrlInterface.cpp 2010-04-30 15:17:01 UTC (rev 1876)
@@ -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 @@
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 @@
#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 @@
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 @@
#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()){
Modified: trunk/core/SipCtrlInterface.h
===================================================================
--- trunk/core/SipCtrlInterface.h 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/SipCtrlInterface.h 2010-04-30 15:17:01 UTC (rev 1876)
@@ -59,7 +59,6 @@
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 @@
/**
* 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);
};
Modified: trunk/core/sip/sip_trans.h
===================================================================
--- trunk/core/sip/sip_trans.h 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/sip/sip_trans.h 2010-04-30 15:17:01 UTC (rev 1876)
@@ -132,8 +132,8 @@
/**
* Retransmission buffer
- * - UAS transaction: ACK
- * - UAC transaction: final reply
+ * - UAC transaction: ACK
+ * - UAS transaction: last reply
*/
char* retr_buf;
Modified: trunk/core/sip/sip_ua.h
===================================================================
--- trunk/core/sip/sip_ua.h 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/sip/sip_ua.h 2010-04-30 15:17:01 UTC (rev 1876)
@@ -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 @@
{
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
Modified: trunk/core/sip/trans_layer.cpp
===================================================================
--- trunk/core/sip/trans_layer.cpp 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/sip/trans_layer.cpp 2010-04-30 15:17:01 UTC (rev 1876)
@@ -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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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,11 +1553,16 @@
// 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
Modified: trunk/core/sip/trans_layer.h
===================================================================
--- trunk/core/sip/trans_layer.h 2010-04-30 15:12:00 UTC (rev 1875)
+++ trunk/core/sip/trans_layer.h 2010-04-30 15:17:01 UTC (rev 1876)
@@ -27,8 +27,6 @@
#ifndef _trans_layer_h_
#define _trans_layer_h_
-//#include "AmApi.h"
-
#include "cstring.h"
#include <list>
@@ -135,6 +133,13 @@
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.
*/
static trans_layer* instance();
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev