qos_handlers.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2007 SOMA Networks, Inc.
00005  * Written by Ovidiu Sas (osas)
00006  *
00007  * This file is part of Kamailio, a free SIP server.
00008  *
00009  * Kamailio is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * Kamailio is distributed in the hope that it will be useful, but
00015  * WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00022  * USA
00023  *
00024  * History:
00025  * --------
00026  * 2007-07-16 initial version (osas)
00027  */
00028 
00029 
00030 #include <stdio.h>  /* for snprintf() */
00031 #include <string.h> /* for memset() */
00032 #include <stdlib.h> /* For atoi() */
00033 
00034 #include "../../parser/parser_f.h"
00035 #include "../../parser/sdp/sdp.h"
00036 #include "../../ut.h"
00037 #include "../../dprint.h"
00038 #include "../dialog/dlg_hash.h"
00039 
00040 #include "qos_mi.h"
00041 #include "qos_handlers.h"
00042 #include "qos_ctx_helpers.h"
00043 
00044 /**
00045  * The binding to the dialog module functions. Most importantly the
00046  * register_dlgcb function.
00047  */
00048 extern struct dlg_binds *dlg_binds;
00049 
00050 
00051 /**
00052  * Local function prototypes. See function definition for
00053  * documentation.
00054  */
00055 static void setup_dialog_callbacks(struct dlg_cell *did, qos_ctx_t *ctx);
00056 
00057 static void qos_dialog_destroy_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params);
00058 static void qos_dialog_request_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params);
00059 static void qos_dialog_response_CB(struct dlg_cell* did, int type,struct dlg_cb_params * params);
00060 
00061 
00062 /**
00063  * The value of the message flag to flag an INVITE we want to process
00064  * through the QoS module.
00065  */
00066 //static int qos_flag = 0;
00067 
00068 
00069 
00070 /**
00071  * A helper function to setup all the callbacks from the dialog module
00072  * after we find intrest in the dialog.
00073  *
00074  * @param did The Dialog ID.
00075  * @param info The qos information.
00076  *
00077  */
00078 
00079 static void setup_dialog_callbacks(struct dlg_cell *did, qos_ctx_t *ctx)
00080 {
00081    dlg_binds->register_dlgcb(did, DLGCB_REQ_WITHIN,
00082          qos_dialog_request_CB, (void *)ctx, NULL);
00083 
00084    dlg_binds->register_dlgcb(did, DLGCB_RESPONSE_FWDED|DLGCB_RESPONSE_WITHIN,
00085          qos_dialog_response_CB, (void *)ctx, NULL);
00086 
00087    dlg_binds->register_dlgcb(did, DLGCB_DESTROY,
00088          qos_dialog_destroy_CB, (void *)ctx, NULL);
00089 
00090    dlg_binds->register_dlgcb(did, DLGCB_MI_CONTEXT,
00091          qos_dialog_mi_context_CB, (void *)ctx, NULL);
00092 
00093    return;
00094 }
00095 
00096 /**
00097  * Every time a new dialog is created (from a new INVITE) the dialog
00098  * module will call this callback function. We need to track the
00099  * dialogs lifespan from this point forward until it is terminated
00100  * with a BYE, CANCEL, etc. In the process, we will see if either or
00101  * both ends of the conversation are trying to re-negotiate the media.
00102  *
00103  * This function will setup the other types of dialog callbacks
00104  * required to track the lifespan of the dialog.
00105  *
00106  *
00107  * @param did   - The dialog ID
00108  * @param type  - The trigger event type (CREATED)
00109  * @param msg   - The SIP message that triggered the callback (INVITE)
00110  * @param param - The pointer to nothing. As we did not attach
00111  *                anything to this callback in the dialog module.
00112  */
00113 void qos_dialog_created_CB(struct dlg_cell *did, int type, struct dlg_cb_params * params)
00114 {
00115    qos_ctx_t *qos_ctx = NULL;
00116    struct sip_msg* msg = params->msg;
00117    unsigned int dir = params->direction, role, other_role;
00118 
00119    if (dir == DLG_DIR_UPSTREAM) {
00120       role = QOS_CALLEE;
00121       other_role = QOS_CALLER;
00122    } else if (dir == DLG_DIR_DOWNSTREAM) {
00123       role = QOS_CALLER;
00124       other_role = QOS_CALLEE;
00125    } else {
00126       LM_ERR("Unknown dir %d\n", dir);
00127       return;
00128    }
00129 
00130    if (msg == NULL || msg == FAKED_REPLY) {
00131       LM_ERR("Improper msg\n");
00132       return;
00133    }
00134 
00135    /* look only at INVITE */
00136    if (msg->first_line.type != SIP_REQUEST ||
00137       msg->first_line.u.request.method_value != METHOD_INVITE) {
00138       LM_WARN("Dialog create callback called with a non-INVITE req.\n");
00139       return;
00140    }
00141 
00142    qos_ctx = build_new_qos_ctx();
00143    if (qos_ctx==NULL) {
00144       /* Error message printed in build_new_qos_ctx() */
00145       return;
00146    }
00147 
00148    LM_DBG("setup_dialog_callbacks( %p , %p )\n", did, qos_ctx);
00149    setup_dialog_callbacks(did, qos_ctx);
00150 
00151    run_create_cbs(qos_ctx, msg);
00152 
00153    if (0 == parse_sdp(msg)) {
00154       lock_get(&qos_ctx->lock);
00155       add_sdp(qos_ctx, dir, msg, role, other_role);
00156       lock_release(&qos_ctx->lock);
00157    }
00158 
00159 
00160    return;
00161 }
00162 
00163 
00164 /**
00165  * This callback is called when ever a dialog isdestroyed.
00166  *
00167  * @param did - The Dialog ID / structure pointer. Used as an ID only.
00168  * @param type - The termination cause/reason.
00169  * @param params - pointer to the dlg_cb params
00170  */
00171 static void qos_dialog_destroy_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params)
00172 {
00173    struct sip_msg* msg = params->msg;
00174    qos_ctx_t* qos_ctx = (qos_ctx_t*)*(params->param);
00175 
00176    /* run the QOSCB_TERMINATED callback */
00177    run_qos_callbacks(QOSCB_TERMINATED, qos_ctx, NULL, 0, msg);
00178 
00179    /* Free the param qos_info_t memory */
00180    if (qos_ctx) {
00181       destroy_qos_ctx(qos_ctx);
00182       params->param = NULL;
00183    }
00184    return;
00185 }
00186 
00187 /**
00188  *
00189  * @param did - The dialog structure. The pointer is used as an ID.
00190  * @param type - The reason for the callback. DLGCB_REQ_WITHIN
00191  * @param msg - The SIP message that causes the callback.
00192  * @param param - The qos information
00193  */
00194 static void qos_dialog_request_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params)
00195 {
00196    struct sip_msg* msg = params->msg;
00197    unsigned int dir = params->direction, role, other_role;
00198    qos_ctx_t* qos_ctx = (qos_ctx_t*)*(params->param);
00199 
00200    if (dir == DLG_DIR_UPSTREAM) {
00201       role = QOS_CALLEE;
00202       other_role = QOS_CALLER;
00203    } else if (dir == DLG_DIR_DOWNSTREAM) {
00204       role = QOS_CALLER;
00205       other_role = QOS_CALLEE;
00206    } else {
00207       LM_ERR("Unknown dir %d\n", dir);
00208       return;
00209    }
00210 
00211    if (msg->first_line.type == SIP_REQUEST) {
00212       if (    (msg->first_line.u.request.method_value == METHOD_INVITE) ||
00213          (msg->first_line.u.request.method_value == METHOD_UPDATE) ||
00214          (msg->first_line.u.request.method_value == METHOD_ACK) ||
00215          (msg->first_line.u.request.method_value == METHOD_PRACK)) {
00216          if (0 == parse_sdp(msg)) {
00217             lock_get(&qos_ctx->lock);
00218             add_sdp(qos_ctx, dir, msg, role, other_role);
00219             lock_release(&qos_ctx->lock);
00220          }
00221       } else {
00222          LM_DBG("Ignoring non-carrying SDP req\n");
00223          return;
00224       }
00225    } else {
00226       LM_ERR("not a SIP_REQUEST\n");
00227       return;
00228    }
00229 
00230    return;
00231 }
00232 
00233 /**
00234  * This callback is called on any response message in the lifespan of
00235  * the dialog. The callback is called just before the message is
00236  * copied to pkg memory so it is still mutable.
00237  *
00238  * @param did - The dialog structure. The pointer is used as an ID.
00239  * @param type - The reason for the callback. DLGCB_CONFIRMED
00240  * @param msg - The SIP message that causes the callback.
00241  * @param param - The qos information
00242  */
00243 static void qos_dialog_response_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params)
00244 {
00245    struct sip_msg* msg = params->msg;
00246    unsigned int dir = params->direction, role, other_role;
00247    qos_ctx_t* qos_ctx = (qos_ctx_t*)*(params->param);
00248 
00249    if (dir == DLG_DIR_UPSTREAM) {
00250       role = QOS_CALLEE;
00251       other_role = QOS_CALLER;
00252    } else if (dir == DLG_DIR_DOWNSTREAM) {
00253       role = QOS_CALLER;
00254       other_role = QOS_CALLEE;
00255    } else {
00256       LM_ERR("Unknown dir %d\n", dir);
00257       return;
00258    }
00259 
00260    if (msg->first_line.type == SIP_REPLY) {
00261       if (msg->first_line.u.reply.statuscode > 100 &&
00262          msg->first_line.u.reply.statuscode < 300) {
00263          if (0 == parse_sdp(msg)) {
00264             lock_get(&qos_ctx->lock);
00265             add_sdp(qos_ctx, dir, msg, role, other_role);
00266             lock_release(&qos_ctx->lock);
00267          }
00268       } else if (msg->first_line.u.reply.statuscode > 399 &&
00269          msg->first_line.u.reply.statuscode < 700) {
00270          lock_get(&qos_ctx->lock);
00271          remove_sdp(qos_ctx, dir, msg, role, other_role);
00272          lock_release(&qos_ctx->lock);
00273       }
00274    } else {
00275       LM_ERR("not a SIP_REPLY\n");
00276       return;
00277    }
00278 
00279    return;
00280 }
00281 

Generated on Thu May 24 08:00:53 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6