- script callbacks splitted into REQUEST and REPLY callbacks for flexibility
authorBogdan-Andrei Iancu <bogdan@voice-system.ro>
Sun, 13 Feb 2005 18:25:11 +0000 (18:25 +0000)
committerBogdan-Andrei Iancu <bogdan@voice-system.ro>
Sun, 13 Feb 2005 18:25:11 +0000 (18:25 +0000)
  and efficiency reasons

receive.c
script_cb.c
script_cb.h

index d3ed170..c325038 100644 (file)
--- a/receive.c
+++ b/receive.c
@@ -81,7 +81,6 @@ str default_via_port={0,0};
 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
 {
        struct sip_msg* msg;
-       int ret;
 #ifdef STATS
        int skipped = 1;
        struct timeval tvb, tve;        
@@ -125,7 +124,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
                if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
                        /* no via, send back error ? */
                        LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
-                       goto error;
+                       goto error02;
                }
                /* check if necessary to add receive?->moved to forward_req */
                /* check for the alias stuff */
@@ -156,16 +155,14 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
                   (like presence of at least one via), so you can count
                   on via1 being parsed in a pre-script callback --andrei
                */
-               ret=exec_pre_cb(msg);
-               if (ret<=0){
-                       if (ret<0) goto error;
-                       else goto end; /* drop the message -- no error -- andrei */
-               }
+               if (exec_pre_req_cb(msg)==0 )
+                       goto end; /* drop the request */
+
                /* exec the routing script */
                if (run_actions(rlist[0], msg)<0) {
                        LOG(L_WARN, "WARNING: receive_msg: "
                                        "error while trying script\n");
-                       goto error;
+                       goto error_req;
                }
 
 #ifdef STATS
@@ -176,21 +173,16 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
                DBG("successfully ran routing scripts...(%d usec)\n", diff);
                STATS_RX_REQUEST( msg->first_line.u.request.method_value );
 #endif
+
+               /* execute post request-script callbacks */
+               exec_post_req_cb(msg);
        }else if (msg->first_line.type==SIP_REPLY){
                /* sanity checks */
                if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
                        /* no via, send back error ? */
                        LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
-                       goto error;
-               }
-#if 0
-               if ((msg->via2==0) || (msg->via2->error!=PARSE_OK)){
-                       /* no second via => error? */
-                       LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
-                       goto error;
+                       goto error02;
                }
-               /* check if via1 == us */
-#endif
 
 #ifdef STATS
                gettimeofday( & tvb, &tz );
@@ -204,11 +196,8 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
                   (like presence of at least one via), so you can count
                   on via1 being parsed in a pre-script callback --andrei
                */
-               ret=exec_pre_cb(msg);
-               if (ret<=0){
-                       if (ret<0) goto error;
-                       else goto end; /* drop the message -- no error -- andrei */
-               }
+               if (exec_pre_rpl_cb(msg)==0 )
+                       goto end; /* drop the request */
 
                /* send the msg */
                forward_reply(msg);
@@ -220,13 +209,15 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
                stats->acc_res_time+=diff;
                DBG("successfully ran reply processing...(%d usec)\n", diff);
 #endif
+
+               /* execute post reply-script callbacks */
+               exec_post_rpl_cb(msg);
        }
+
 end:
 #ifdef STATS
        skipped = 0;
 #endif
-       /* execute post-script callbacks, if any; -jiri */
-       exec_post_cb(msg);
        /* free possible loaded avps -bogdan */
        reset_avps();
        DBG("receive_msg: cleaning up\n");
@@ -236,10 +227,10 @@ end:
        if (skipped) STATS_RX_DROPS;
 #endif
        return 0;
-error:
-       DBG("error:...\n");
-       /* execute post-script callbacks, if any; -jiri */
-       exec_post_cb(msg);
+error_req:
+       DBG("receive_msg: error:...\n");
+       /* execute post request-script callbacks */
+       exec_post_req_cb(msg);
        /* free possible loaded avps -bogdan */
        reset_avps();
 error02:
index 3e2fc1e..c68d972 100644 (file)
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/* History:
+ *
+ * History:
  * --------
  *  2003-03-29  cleaning pkg allocation introduced (jiri)
  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
+ *  2005-02-13  script callbacks devided into request and reply types (bogdan)
  */
 
 
 #include "error.h"
 #include "mem/mem.h"
 
-static struct script_cb *pre_cb=0;
-static struct script_cb *post_cb=0;
+static struct script_cb *pre_req_cb=0;
+static struct script_cb *post_req_cb=0;
+
+static struct script_cb *pre_rpl_cb=0;
+static struct script_cb *post_rpl_cb=0;
+
 static unsigned int cb_id=0;
 
-int register_script_cb( cb_function f, callback_t t, void *param )
+
+static inline int add_callback( struct script_cb **list,
+       cb_function f, void *param)
 {
        struct script_cb *new_cb;
 
        new_cb=pkg_malloc(sizeof(struct script_cb));
        if (new_cb==0) {
-               LOG(L_ERR, "ERROR: register_script_cb: out of memory\n");
-               return E_OUT_OF_MEM;
+               LOG(L_ERR, "ERROR:add_script_callback: out of memory\n");
+               return -1;
        }
-       new_cb->cbf=f;
-       new_cb->id=cb_id++;
-       new_cb->param=param;
-       /* insert into appropriate list */
-       if (t==PRE_SCRIPT_CB) {
-               new_cb->next=pre_cb;
-               pre_cb=new_cb;
-       } else if (t==POST_SCRIPT_CB) {
-               new_cb->next=post_cb;
-               post_cb=new_cb;
-       } else {
-               LOG(L_CRIT, "ERROR: register_script_cb: unknown CB type\n");
-               return E_BUG;
+       new_cb->cbf = f;
+       new_cb->id = cb_id++;
+       new_cb->param = param;
+       /* link at the beginning of the list */
+       new_cb->next = *list;
+       *list = new_cb;
+       return 0;
+}
+
+
+int register_script_cb( cb_function f, int type, void *param )
+{
+       /* type checkings */
+       if ( (type&(REQ_TYPE_CB|RPL_TYPE_CB))==0 ) {
+               LOG(L_CRIT,"BUG:register_script_cb: REQUEST or REPLY "
+                       "type not specified\n");
+               goto error;
        }
-       /* ok, callback installed */
-       return 1;
+       if ( (type&(PRE_SCRIPT_CB|POST_SCRIPT_CB))==0 ||
+       (type&PRE_SCRIPT_CB && type&POST_SCRIPT_CB) ) {
+               LOG(L_CRIT,"BUG:register_script_cb: callback POST or PRE type must "
+                       "be exactly one\n");
+               goto error;
+       }
+
+       if (type&REQ_TYPE_CB) {
+               /* callback for request script */
+               if (type&PRE_SCRIPT_CB) {
+                       if (add_callback( &pre_req_cb, f, param)<0)
+                               goto add_error;
+               } else if (type&POST_SCRIPT_CB) {
+                       if (add_callback( &post_req_cb, f, param)<0)
+                               goto add_error;
+               }
+       }
+       if (type&REQ_TYPE_CB) {
+               /* callback (also) for reply script */
+               if (type&PRE_SCRIPT_CB) {
+                       if (add_callback( &pre_rpl_cb, f, param)<0)
+                               goto add_error;
+               } else if (type&POST_SCRIPT_CB) {
+                       if (add_callback( &post_rpl_cb, f, param)<0)
+                               goto add_error;
+               }
+       }
+
+       return 0;
+add_error:
+       LOG(L_ERR,"ERROR:register_script_cb: failed to add callback\n");
+error:
+       return -1;
 }
 
-void destroy_script_cb()
+
+static inline void destroy_cb_list(struct script_cb **list)
 {
-       struct script_cb *cb, *foo;
+       struct script_cb *foo;
+
+       while( *list ) {
+               foo = *list;
+               *list = (*list)->next;
+               pkg_free( foo );
+       }
+}
 
-       cb=pre_cb;
-       while(cb) { foo=cb->next;pkg_free(cb);cb=foo; }
-       cb=post_cb;
-       while(cb) { foo=cb->next;pkg_free(cb);cb=foo; }
+
+void destroy_script_cb()
+{
+       destroy_cb_list( &pre_req_cb  );
+       destroy_cb_list( &post_req_cb );
+       destroy_cb_list( &pre_rpl_cb  );
+       destroy_cb_list( &post_req_cb );
 }
 
-int exec_pre_cb( struct sip_msg *msg)
+
+static inline int exec_pre_cb( struct sip_msg *msg, struct script_cb *cb)
 {
-       struct script_cb *i;
-       for (i=pre_cb; i; i=i->next) {
+       for ( ; cb ; cb=cb->next ) {
                /* stop on error */
-               if (i->cbf(msg, i->param)==0)
+               if (cb->cbf(msg, cb->param)==0)
                        return 0;
        }
        return 1;
 }
 
-void exec_post_cb( struct sip_msg *msg)
+
+static inline int exec_post_cb( struct sip_msg *msg, struct script_cb *cb)
+{
+       for ( ; cb ; cb=cb->next){
+               cb->cbf( msg, cb->param);
+       }
+       return 1;
+}
+
+
+int exec_pre_req_cb( struct sip_msg *msg)
+{
+       return exec_pre_cb( msg, pre_req_cb);
+}
+
+int exec_pre_rpl_cb( struct sip_msg *msg)
+{
+       return exec_pre_cb( msg, pre_rpl_cb);
+}
+
+int exec_post_req_cb( struct sip_msg *msg)
+{
+       return exec_post_cb( msg, post_req_cb);
+}
+
+int exec_post_rpl_cb( struct sip_msg *msg)
 {
-       struct script_cb *i;
-       for (i=post_cb; i; i=i->next) i->cbf(msg, i->param);
+       return exec_post_cb( msg, post_rpl_cb);
 }
 
index 4e8a779..0c81028 100644 (file)
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ *  2005-02-13  script callbacks devided into request and reply types (bogdan)
  */
 
 #ifndef _SCRIPT_CB_H_
 
 typedef int (cb_function)( struct sip_msg *msg, void *param );
 
-typedef enum {
-    PRE_SCRIPT_CB,
-       POST_SCRIPT_CB
-} callback_t;       /* Allowed types of callbacks */
+
+#define PRE_SCRIPT_CB    (1<<0)
+#define POST_SCRIPT_CB   (1<<1)
+#define REQ_TYPE_CB      (1<<2)
+#define RPL_TYPE_CB      (1<<3)
 
 
 struct script_cb{
@@ -45,10 +50,14 @@ struct script_cb{
        void *param;
 };
 
-int register_script_cb( cb_function f, callback_t t, void *param );
-int exec_pre_cb( struct sip_msg *msg);
-void exec_post_cb( struct sip_msg *msg);
+int register_script_cb( cb_function f, int type, void *param );
 void destroy_script_cb();
 
+int exec_pre_req_cb( struct sip_msg *msg);
+int exec_post_req_cb( struct sip_msg *msg);
+
+int exec_pre_rpl_cb( struct sip_msg *msg);
+int exec_post_rpl_cb( struct sip_msg *msg);
+
 #endif