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

Reply via email to