Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

dset.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dset.c,v 1.19 2006/12/15 09:09:11 andrei Exp $
00003  *
00004  * destination set
00005  *
00006  * Copyright (C) 2001-2004 FhG FOKUS
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser 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  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License 
00026  * along with this program; if not, write to the Free Software 
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  */
00029 
00030 #include <string.h>
00031 #include "dprint.h"
00032 #include "config.h"
00033 #include "parser/parser_f.h"
00034 #include "parser/msg_parser.h"
00035 #include "ut.h"
00036 #include "hash_func.h"
00037 #include "error.h"
00038 #include "dset.h"
00039 #include "mem/mem.h"
00040 #include "ip_addr.h"
00041 
00042 #define CONTACT "Contact: "
00043 #define CONTACT_LEN (sizeof(CONTACT) - 1)
00044 
00045 #define CONTACT_DELIM ", "
00046 #define CONTACT_DELIM_LEN (sizeof(CONTACT_DELIM) - 1)
00047 
00048 #define Q_PARAM ">;q="
00049 #define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
00050 
00051 struct branch
00052 {
00053         char uri[MAX_URI_SIZE];
00054         unsigned int len;
00055 
00056              /* Real destination of the request */
00057         char dst_uri[MAX_URI_SIZE];
00058         unsigned int dst_uri_len;
00059 
00060         int q; /* Preference of the contact among
00061                 * contact within the array */
00062         struct socket_info* force_send_socket;
00063 };
00064 
00065 
00066 /* 
00067  * Where we store URIs of additional transaction branches
00068  * (-1 because of the default branch, #0)
00069  */
00070 static struct branch branches[MAX_BRANCHES - 1];
00071 
00072 /* how many of them we have */
00073 unsigned int nr_branches = 0;
00074 
00075 /* branch iterator */
00076 static int branch_iterator = 0;
00077 
00078 /* The q parameter of the Request-URI */
00079 static qvalue_t ruri_q = Q_UNSPECIFIED; 
00080 
00081 
00082 /*
00083  * Initialize the branch iterator, the next
00084  * call to next_branch will return the first
00085  * contact from the dset array
00086  */
00087 void init_branch_iterator(void)
00088 {
00089         branch_iterator = 0;
00090 }
00091 
00092 
00093 /*
00094  * Return the next branch from the dset
00095  * array, 0 is returned if there are no
00096  * more branches
00097  */
00098 char* next_branch(int* len, qvalue_t* q, char** dst_uri, int* dst_len, struct socket_info** force_socket)
00099 {
00100         unsigned int i;
00101 
00102         i = branch_iterator;
00103         if (i < nr_branches) {
00104                 branch_iterator++;
00105                 *len = branches[i].len;
00106                 *q = branches[i].q;
00107                 if (dst_uri && dst_len) {
00108                         *dst_uri = branches[i].dst_uri;
00109                         *dst_len = branches[i].dst_uri_len;
00110                 }
00111                 if (force_socket) {
00112                         *force_socket = branches[i].force_send_socket;
00113                 }
00114                 return branches[i].uri;
00115         } else {
00116                 *len = 0;
00117                 *q = Q_UNSPECIFIED;
00118                 if (dst_uri && dst_len) {
00119                         *dst_uri = 0;
00120                         *dst_len = 0;
00121                 }
00122                 if (force_socket) {
00123                         *force_socket = 0;
00124                 }
00125                 return 0;
00126         }
00127 }
00128 
00129 
00130 /*
00131  * Empty the dset array
00132  */
00133 void clear_branches(void)
00134 {
00135         nr_branches = 0;
00136         ruri_q = Q_UNSPECIFIED;
00137 }
00138 
00139 
00140 /* 
00141  * Add a new branch to current transaction 
00142  */
00143 int append_branch(struct sip_msg* msg, char* uri, int uri_len, char* dst_uri, int dst_uri_len, 
00144                   qvalue_t q, struct socket_info* force_socket)
00145 {
00146              /* if we have already set up the maximum number
00147               * of branches, don't try new ones 
00148               */
00149         if (nr_branches == MAX_BRANCHES - 1) {
00150                 LOG(L_ERR, "ERROR: append_branch: max nr of branches exceeded\n");
00151                 ser_error = E_TOO_MANY_BRANCHES;
00152                 return -1;
00153         }
00154 
00155         if (uri_len > MAX_URI_SIZE - 1) {
00156                 LOG(L_ERR, "ERROR: append_branch: too long uri: %.*s\n",
00157                     uri_len, uri);
00158                 return -1;
00159         }
00160         
00161         if (dst_uri_len > MAX_URI_SIZE - 1) {
00162                 LOG(L_ERR, "ERROR: append_branch: too long dst_uri: %.*s\n",
00163                     dst_uri_len, ZSW(dst_uri));
00164                 return -1;
00165         }
00166 
00167              /* if not parameterized, take current uri */
00168         if (uri == 0) {
00169                 if (msg->new_uri.s) { 
00170                         uri = msg->new_uri.s;
00171                         uri_len = msg->new_uri.len;
00172                 } else {
00173                         uri = msg->first_line.u.request.uri.s;
00174                         uri_len = msg->first_line.u.request.uri.len;
00175                 }
00176         }
00177         
00178         memcpy(branches[nr_branches].uri, uri, uri_len);
00179              /* be safe -- add zero termination */
00180         branches[nr_branches].uri[uri_len] = 0;
00181         branches[nr_branches].len = uri_len;
00182         branches[nr_branches].q = q;
00183         
00184         if (dst_uri && dst_uri_len) {
00185                 memcpy(branches[nr_branches].dst_uri, dst_uri, dst_uri_len);
00186                 branches[nr_branches].dst_uri[dst_uri_len] = 0;
00187                 branches[nr_branches].dst_uri_len = dst_uri_len;
00188         } else {
00189                 branches[nr_branches].dst_uri[0] = '\0';
00190                 branches[nr_branches].dst_uri_len = 0;
00191         }
00192 
00193         branches[nr_branches].force_send_socket = force_socket;
00194         
00195         nr_branches++;
00196         return 1;
00197 }
00198 
00199 
00200 /*
00201  * Create a Contact header field from the dset
00202  * array
00203  */
00204 char* print_dset(struct sip_msg* msg, int* len) 
00205 {
00206         int cnt, i;
00207         unsigned int qlen;
00208         qvalue_t q;
00209         str uri;
00210         char* p, *qbuf;
00211         static char dset[MAX_REDIRECTION_LEN];
00212 
00213         if (msg->new_uri.s) {
00214                 cnt = 1;
00215                 *len = msg->new_uri.len;
00216                 if (ruri_q != Q_UNSPECIFIED) {
00217                         *len += 1 + Q_PARAM_LEN + len_q(ruri_q);
00218                 }
00219         } else {
00220                 cnt = 0;
00221                 *len = 0;
00222         }
00223 
00224         init_branch_iterator();
00225         while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0))) {
00226                 cnt++;
00227                 *len += uri.len;
00228                 if (q != Q_UNSPECIFIED) {
00229                         *len += 1 + Q_PARAM_LEN + len_q(q);
00230                 }
00231         }
00232 
00233         if (cnt == 0) return 0; 
00234 
00235         *len += CONTACT_LEN + CRLF_LEN + (cnt - 1) * CONTACT_DELIM_LEN;
00236 
00237         if (*len + 1 > MAX_REDIRECTION_LEN) {
00238                 LOG(L_ERR, "ERROR: redirection buffer length exceed\n");
00239                 return 0;
00240         }
00241 
00242         memcpy(dset, CONTACT, CONTACT_LEN);
00243         p = dset + CONTACT_LEN;
00244         if (msg->new_uri.s) {
00245                 if (ruri_q != Q_UNSPECIFIED) {
00246                         *p++ = '<';
00247                 }
00248 
00249                 memcpy(p, msg->new_uri.s, msg->new_uri.len);
00250                 p += msg->new_uri.len;
00251 
00252                 if (ruri_q != Q_UNSPECIFIED) {
00253                         memcpy(p, Q_PARAM, Q_PARAM_LEN);
00254                         p += Q_PARAM_LEN;
00255 
00256                         qbuf = q2str(ruri_q, &qlen);
00257                         memcpy(p, qbuf, qlen);
00258                         p += qlen;
00259                 }
00260                 i = 1;
00261         } else {
00262                 i = 0;
00263         }
00264 
00265         init_branch_iterator();
00266         while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0))) {
00267                 if (i) {
00268                         memcpy(p, CONTACT_DELIM, CONTACT_DELIM_LEN);
00269                         p += CONTACT_DELIM_LEN;
00270                 }
00271 
00272                 if (q != Q_UNSPECIFIED) {
00273                         *p++ = '<';
00274                 }
00275 
00276                 memcpy(p, uri.s, uri.len);
00277                 p += uri.len;
00278                 if (q != Q_UNSPECIFIED) {
00279                         memcpy(p, Q_PARAM, Q_PARAM_LEN);
00280                         p += Q_PARAM_LEN;
00281 
00282                         qbuf = q2str(q, &qlen);
00283                         memcpy(p, qbuf, qlen);
00284                         p += qlen;
00285                 }
00286                 i++;
00287         }
00288 
00289         memcpy(p, CRLF " ", CRLF_LEN + 1);
00290         return dset;
00291 }
00292 
00293 
00294 /*
00295  * Sets the q parameter of the Request-URI
00296  */
00297 void set_ruri_q(qvalue_t q)
00298 {
00299         ruri_q = q;
00300 }
00301 
00302 
00303 /*
00304  * Return the q value of the Request-URI
00305  */
00306 qvalue_t get_ruri_q(void)
00307 {
00308         return ruri_q;
00309 }
00310 
00311 
00312 
00313 /*
00314  * Get actual Request-URI
00315  */
00316 int get_request_uri(struct sip_msg* _m, str* _u)
00317 {
00318              /* Use new_uri if present */
00319         if (_m->new_uri.s) {
00320                 _u->s = _m->new_uri.s;
00321                 _u->len = _m->new_uri.len;
00322         } else {
00323                 _u->s = _m->first_line.u.request.uri.s;
00324                 _u->len = _m->first_line.u.request.uri.len;
00325         }
00326 
00327         return 0;
00328 }
00329 
00330 
00331 /*
00332  * Rewrite Request-URI
00333  */
00334 int rewrite_uri(struct sip_msg* _m, str* _s)
00335 {
00336         char* buf;
00337 
00338         buf = (char*)pkg_malloc(_s->len + 1);
00339         if (!buf) {
00340                 LOG(L_ERR, "ERROR: rewrite_uri: No memory left\n");
00341                 return -1;
00342         }
00343 
00344         memcpy(buf, _s->s, _s->len);
00345         buf[_s->len] = '\0';
00346 
00347         _m->parsed_uri_ok = 0;
00348         if (_m->new_uri.s) {
00349                 pkg_free(_m->new_uri.s);
00350         }
00351 
00352         _m->new_uri.s = buf;
00353         _m->new_uri.len = _s->len;
00354 
00355         DBG("rewrite_uri: Rewriting Request-URI with '%.*s'\n", _s->len, 
00356                                                                                                                                                    buf);
00357         return 1;
00358 }
00359 

Generated on Tue Sep 7 04:15:51 2010 for SIPExpressRouter by  doxygen 1.3.9.1