diversion.c

Go to the documentation of this file.
00001 /* 
00002  * $Id: diversion.c 4657 2008-08-10 22:51:44Z henningw $
00003  *
00004  * Diversion Header Field Support
00005  *
00006  * Copyright (C) 2004 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  */
00025 
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include "../../sr_module.h"
00029 #include "../../error.h"
00030 #include "../../dprint.h"
00031 #include "../../mem/mem.h"
00032 #include "../../data_lump.h"
00033 #include "../../mod_fix.h"
00034 
00035 
00036 MODULE_VERSION
00037 
00038 #define DIVERSION_HF "Diversion"
00039 #define DIVERSION_HF_LEN (sizeof(DIVERSION_HF) - 1)
00040 
00041 #define DIVERSION_PREFIX     DIVERSION_HF ": <"
00042 #define DIVERSION_PREFIX_LEN (sizeof(DIVERSION_PREFIX) - 1)
00043 
00044 #define DIVERSION_SUFFIX     ">;reason="
00045 #define DIVERSION_SUFFIX_LEN (sizeof(DIVERSION_SUFFIX) - 1)
00046 
00047 
00048 
00049 str suffix = {"", 0};
00050 
00051 int add_diversion(struct sip_msg* msg, char* r, char* s);
00052 
00053 /*
00054  * Module initialization function prototype
00055  */
00056 static int mod_init(void);
00057 
00058 
00059 /*
00060  * Exported functions
00061  */
00062 static cmd_export_t cmds[] = {
00063    {"add_diversion",    (cmd_function)add_diversion,    1, fixup_str_null,
00064       0, REQUEST_ROUTE|FAILURE_ROUTE|LOCAL_ROUTE},
00065    {0, 0, 0, 0, 0, 0}
00066 };
00067 
00068 
00069 /*
00070  * Exported parameters
00071  */
00072 static param_export_t params[] = {
00073    {"suffix", STR_PARAM, &suffix.s},
00074    {0, 0, 0}
00075 };
00076 
00077 
00078 /*
00079  * Module interface
00080  */
00081 struct module_exports exports = {
00082    "diversion", 
00083    DEFAULT_DLFLAGS, /* dlopen flags */
00084    cmds,       /* Exported functions */
00085    params,     /* Exported parameters */
00086    0,          /* exported statistics */
00087    0,          /* exported MI functions */
00088    0,          /* exported pseudo-variables */
00089    0,          /* extra processes */
00090    mod_init,   /* module initialization function */
00091    0,          /* response function */
00092    0,          /* destroy function */
00093    0           /* child initialization function */
00094 };
00095 
00096 
00097 static int mod_init(void)
00098 {
00099    suffix.len = strlen(suffix.s);
00100    return 0;
00101 }
00102 
00103 
00104 static inline int add_diversion_helper(struct sip_msg* msg, str* s)
00105 {
00106    char *ptr;
00107 
00108    static struct lump* anchor = 0;
00109    static unsigned int msg_id = 0;
00110 
00111    if (msg_id != msg->id) {
00112       msg_id = msg->id;
00113       anchor = 0;
00114    }
00115    
00116    if (!msg->diversion && parse_headers(msg, HDR_DIVERSION_F, 0) == -1) {
00117       LM_ERR("header parsing failed\n");
00118       return -1;
00119    }
00120    
00121    if (msg->diversion) {
00122            /* Insert just before the topmost Diversion header */
00123       ptr = msg->diversion->name.s;
00124    } else {
00125            /* Insert at the end */
00126       ptr = msg->unparsed;
00127    }
00128 
00129    if (!anchor) {
00130       anchor = anchor_lump(msg, ptr - msg->buf, 0, 0);
00131       if (!anchor) {
00132          LM_ERR("can't get anchor\n");
00133          return -2;
00134       }
00135    }
00136    
00137    if (!insert_new_lump_before(anchor, s->s, s->len, 0)) {
00138       LM_ERR("can't insert lump\n");
00139       return -3;
00140    }
00141 
00142    return 0;
00143 }
00144 
00145 
00146 int add_diversion(struct sip_msg* msg, char* r, char* s)
00147 {
00148    str div_hf;
00149    char *at;
00150    str* uri;
00151    str* reason;
00152 
00153    reason = (str*)r;
00154 
00155    uri = &msg->first_line.u.request.uri;
00156 
00157    div_hf.len = DIVERSION_PREFIX_LEN + uri->len + DIVERSION_SUFFIX_LEN + reason->len + CRLF_LEN;
00158    div_hf.s = pkg_malloc(div_hf.len);
00159    if (!div_hf.s) {
00160       LM_ERR("no pkg memory left\n");
00161       return -1;
00162    }
00163 
00164    at = div_hf.s;
00165    memcpy(at, DIVERSION_PREFIX, DIVERSION_PREFIX_LEN);
00166    at += DIVERSION_PREFIX_LEN;
00167 
00168    memcpy(at, uri->s, uri->len);
00169    at += uri->len;
00170 
00171    memcpy(at, DIVERSION_SUFFIX, DIVERSION_SUFFIX_LEN);
00172    at += DIVERSION_SUFFIX_LEN;
00173 
00174    memcpy(at, reason->s, reason->len);
00175    at += reason->len;
00176 
00177    memcpy(at, CRLF, CRLF_LEN);
00178 
00179    if (add_diversion_helper(msg, &div_hf) < 0) {
00180       pkg_free(div_hf.s);
00181       return -1;
00182    }
00183 
00184    return 1;
00185 }

Generated on Tue May 22 16:00:26 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6