t_serial.c

Go to the documentation of this file.
00001 /*
00002  * serial.c Serial forking functions
00003  *
00004  * Copyright (C) 2008 Juha Heinanen
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * -------
00024  *  2008-10-22: Moved functions from lcr module to tm module (jh)
00025  */
00026 
00027 #include "../../qvalue.h"
00028 #include "../../mem/mem.h"
00029 #include "../../socket_info.h"
00030 #include "../../usr_avp.h"
00031 #include "../../dset.h"
00032 #include "../../parser/msg_parser.h"
00033 #include "../../ut.h"
00034 #include "config.h"
00035 #include "t_funcs.h"
00036 #include "t_lookup.h"
00037 
00038 /* usr_avp flag for sequential forking */
00039 #define Q_FLAG      (1<<2)
00040 
00041 /* module parameter variable */
00042 int fr_inv_timer_next = INV_FR_TIME_OUT_NEXT;
00043 
00044 /* Struture where information regarding contacts is stored */
00045 struct contact {
00046     str uri;
00047     qvalue_t q;
00048     str dst_uri;
00049     str path;
00050     unsigned int flags;
00051     struct socket_info* sock;
00052     unsigned short q_flag;
00053     struct contact *next;
00054 };
00055 
00056 /* 
00057  * Frees contact list used by load_contacts function
00058  */
00059 static inline void free_contact_list(struct contact *curr) {
00060     struct contact *prev;
00061     while (curr) {
00062    prev = curr;
00063    curr = curr->next;
00064    pkg_free(prev);
00065     }
00066 }
00067 
00068 /* Encode branch info from contact struct to str */
00069 static inline int encode_branch_info(str *info, struct contact *con)
00070 {
00071     char *at, *s;
00072     int len;
00073 
00074     info->len = con->uri.len + con->dst_uri.len +
00075    con->path.len + MAX_SOCKET_STR + INT2STR_MAX_LEN + 5;
00076     info->s = pkg_malloc(info->len);
00077     if (!info->s) {
00078    LM_ERR("no memory left for branch info\n");
00079    return 0;
00080     }
00081     at = info->s;
00082     append_str(at, con->uri.s, con->uri.len);
00083     append_chr(at, '\n');
00084     append_str(at, con->dst_uri.s, con->dst_uri.len);
00085     append_chr(at, '\n');
00086     append_str(at, con->path.s, con->path.len);
00087     append_chr(at, '\n');
00088     if (con->sock) {
00089    len = MAX_SOCKET_STR;
00090    if (!socket2str(con->sock, at, &len)) {
00091        LM_ERR("failed to convert socket to str\n");
00092        return 0;
00093    }
00094     } else {
00095    len = 0;
00096     }
00097     at = at + len;
00098     append_chr(at, '\n');
00099     s = int2str(con->flags, &len);
00100     append_str(at, s, len);
00101     append_chr(at, '\n');
00102     info->len = at - info->s + 1;
00103 
00104     return 1;
00105 }
00106 
00107 
00108 /* Encode branch info from str */
00109 static inline int decode_branch_info(char *info, str *uri, str *dst, str *path,
00110                  struct socket_info **sock,
00111                  unsigned int *flags)
00112 {
00113     str s, host;
00114     int port, proto;
00115     char *pos, *at;
00116 
00117     pos = strchr(info, '\n');
00118     uri->len = pos - info;
00119     if (uri->len) {
00120    uri->s = info;
00121     } else {
00122    uri->s = 0;
00123     }
00124     at = pos + 1;
00125 
00126     pos = strchr(at, '\n');
00127     dst->len = pos - at;
00128     if (dst->len) {
00129    dst->s = at;
00130     } else {
00131    dst->s = 0;
00132     }
00133     at = pos + 1;
00134 
00135     pos = strchr(at, '\n');
00136     path->len = pos - at;
00137     if (path->len) {
00138    path->s = at;
00139     } else {
00140    path->s = 0;
00141     }
00142     at = pos + 1;
00143 
00144     pos = strchr(at, '\n');
00145     s.len = pos - at;
00146     if (s.len) {
00147    s.s = at;
00148    if (parse_phostport(s.s, s.len, &host.s, &host.len,
00149              &port, &proto) != 0) {
00150        LM_ERR("parsing of socket info <%.*s> failed\n",  s.len, s.s);
00151        return 0;
00152    }
00153    *sock = grep_sock_info(&host, (unsigned short)port,
00154                 (unsigned short)proto);
00155    if (*sock == 0) {
00156        LM_ERR("invalid socket <%.*s>\n", s.len, s.s);
00157        return 0;
00158    }
00159     } else {
00160    *sock = 0;
00161     }
00162     at = pos + 1;
00163 
00164     pos = strchr(at, '\n');
00165     s.len = pos - at;
00166     if (s.len) {
00167    s.s = at;
00168    if (str2int(&s, flags) != 0) {
00169        LM_ERR("failed to decode flags <%.*s>\n", s.len, s.s);
00170        return 0;
00171    }
00172     } else {
00173    *flags = 0;
00174     }
00175 
00176     return 1;
00177 }
00178 
00179 
00180 /* 
00181  * Loads contacts in destination set into contacts_avp in reverse
00182  * priority order and associated each contact with Q_FLAG telling if
00183  * contact is the last one in its priority class.  Finally, removes
00184  * all branches from destination set.
00185  */
00186 int t_load_contacts(struct sip_msg* msg, char* key, char* value)
00187 {
00188     str uri, tmp, dst_uri, path, branch_info, *ruri;
00189     qvalue_t first_q, q;
00190     struct contact *contacts, *next, *prev, *curr;
00191     int_str val;
00192     int first_idx, idx;
00193     struct socket_info* sock;
00194     unsigned int flags;
00195     struct cell *t;
00196 
00197     /* Check if contacts_avp has been defined */
00198     if (contacts_avp.n == 0) {
00199    LM_ERR("feature has been disabled - "
00200           "to enable define contacts_avp module parameter");
00201    return -1;
00202     }
00203 
00204     /* Check if anything needs to be done */
00205     if (nr_branches == 0) {
00206    LM_DBG("nothing to do - no branches!\n");
00207    return 1;
00208     }
00209 
00210     t = get_t();
00211     ruri = (str *)0;
00212 
00213     if (!t || (t == T_UNDEFINED)) {
00214 
00215    /* No transaction yet - take first q from Request-URI */
00216    ruri = GET_RURI(msg);
00217    if (!ruri) {
00218        LM_ERR("no Request-URI found\n");
00219        return -1;
00220    }
00221    first_q = get_ruri_q();
00222    first_idx = 0;
00223 
00224     } else {
00225 
00226    /* Transaction exists - take first q from first branch */
00227    
00228    uri.s = get_branch(0, &uri.len, &first_q, &dst_uri, &path, &flags,
00229             &sock);
00230    first_idx = 1;
00231 
00232     }
00233 
00234     /* Check if all q values are equal */
00235     for(idx = first_idx; (tmp.s = get_branch(idx, &tmp.len, &q, 0, 0, 0, 0))
00236        != 0; idx++) {
00237    if (q != first_q) {
00238        goto rest;
00239    }
00240     }
00241 
00242     LM_DBG("nothing to do - all contacts have same q!\n");
00243     return 1;
00244 
00245 rest:
00246 
00247     /* Allocate memory for first contact */
00248     contacts = (struct contact *)pkg_malloc(sizeof(struct contact));
00249     if (!contacts) {
00250    LM_ERR("no memory for contact info\n");
00251    return -1;
00252     }
00253 
00254     if (!t || (t == T_UNDEFINED)) {
00255 
00256    /* Insert Request-URI branch to first contact */
00257    contacts->uri.s = ruri->s;
00258    contacts->uri.len = ruri->len;
00259    contacts->dst_uri = msg->dst_uri;
00260    contacts->sock = msg->force_send_socket;
00261    contacts->flags = getb0flags();
00262    contacts->path = msg->path_vec;
00263 
00264     } else {
00265    
00266    /* Insert first branch to first contact */
00267    contacts->uri = uri;
00268    contacts->q = first_q;
00269    contacts->dst_uri = dst_uri;
00270    contacts->sock = sock;
00271    contacts->flags = flags;
00272    contacts->path = path;
00273     }
00274 
00275     contacts->q = first_q;
00276     contacts->next = (struct contact *)0;
00277 
00278     /* Insert (remaining) branches to contact list in increasing q order */
00279 
00280     for(idx = first_idx;
00281    (uri.s = get_branch(idx,&uri.len,&q,&dst_uri,&path,&flags,&sock))
00282        != 0;
00283    idx++ ) {
00284    next = (struct contact *)pkg_malloc(sizeof(struct contact));
00285    if (!next) {
00286        LM_ERR("no memory for contact info\n");
00287        free_contact_list(contacts);
00288        return -1;
00289    }
00290    next->uri = uri;
00291    next->q = q;
00292    next->dst_uri = dst_uri;
00293    next->path = path;
00294    next->flags = flags;
00295    next->sock = sock;
00296    next->next = (struct contact *)0;
00297    prev = (struct contact *)0;
00298    curr = contacts;
00299    while (curr && (curr->q < q)) {
00300        prev = curr;
00301        curr = curr->next;
00302    }
00303    if (!curr) {
00304        next->next = (struct contact *)0;
00305        prev->next = next;
00306    } else {
00307        next->next = curr;
00308        if (prev) {
00309       prev->next = next;
00310        } else {
00311       contacts = next;
00312        }
00313    }    
00314     }
00315 
00316     /* Assign values for q_flags */
00317     curr = contacts;
00318     curr->q_flag = 0;
00319     while (curr->next) {
00320    if (curr->q < curr->next->q) {
00321        curr->next->q_flag = Q_FLAG;
00322    } else {
00323        curr->next->q_flag = 0;
00324    }
00325    curr = curr->next;
00326     }
00327 
00328     /* Add contacts to contacts_avp */
00329     curr = contacts;
00330     while (curr) {
00331    if (encode_branch_info(&branch_info, curr) == 0) {
00332        LM_ERR("encoding of branch info failed\n");
00333        free_contact_list(contacts);
00334        if (branch_info.s) pkg_free(branch_info.s);
00335        return -1;
00336    }
00337    val.s = branch_info;
00338    add_avp(contacts_avp_type|AVP_VAL_STR|(curr->q_flag),
00339       contacts_avp, val);
00340    pkg_free(branch_info.s);
00341    LM_DBG("loaded contact <%.*s> with q_flag <%d>\n",
00342           val.s.len, val.s.s, curr->q_flag);
00343    curr = curr->next;
00344     }
00345 
00346     /* Clear all branches */
00347     clear_branches();
00348 
00349     /* Free contact list */
00350     free_contact_list(contacts);
00351 
00352     return 1;
00353 }
00354 
00355 
00356 /*
00357  * Adds to request a destination set that includes all highest priority
00358  * class contacts in contacts_avp.   If called from a route block,
00359  * rewrites the request uri with first contact and adds the remaining
00360  * contacts as branches.  If called from failure route block, adds all
00361  * contacts as branches.  Removes added contacts from contacts_avp.
00362  */
00363 int t_next_contacts(struct sip_msg* msg, char* key, char* value)
00364 {
00365     struct usr_avp *avp, *prev;
00366     int_str val;
00367     str uri, dst, path;
00368     struct socket_info *sock;
00369     unsigned int flags;
00370     struct cell *t;
00371 
00372     /* Check if contacts_avp has been defined */
00373     if (contacts_avp.n == 0) {
00374    LM_ERR("feature has been disabled - "
00375           "to enable define contacts_avp module parameter");
00376    return -1;
00377     }
00378 
00379     t = get_t();
00380 
00381     if (!t || (t == T_UNDEFINED)) {
00382 
00383    /* no transaction yet => load Request-URI and branches */
00384 
00385    if (route_type == FAILURE_ROUTE) {
00386        LM_CRIT("BUG - undefined transaction in failure route\n");
00387        return -1;
00388    }
00389 
00390    /* Find first contacts_avp value */
00391    avp = search_first_avp(contacts_avp_type, contacts_avp, &val, 0);
00392    if (!avp) {
00393        LM_DBG("no AVPs - we are done!\n");
00394        return 1;
00395    }
00396 
00397    LM_DBG("next contact is <%s>\n", val.s.s);
00398 
00399    if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)
00400        == 0) {
00401        LM_ERR("decoding of branch info <%.*s> failed\n",
00402          val.s.len, val.s.s);
00403        destroy_avp(avp);
00404        return -1;
00405    }
00406 
00407    /* Rewrite Request-URI */
00408    rewrite_uri(msg, &uri);
00409    set_dst_uri(msg, &dst);
00410    set_path_vector(msg, &path);
00411    msg->force_send_socket = sock;
00412    setb0flags(flags);
00413 
00414    if (avp->flags & Q_FLAG) {
00415        destroy_avp(avp);
00416        /* Set fr_inv_timer */
00417        val.n = fr_inv_timer_next;
00418        if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val) != 0) {
00419       LM_ERR("setting of fr_inv_timer_avp failed\n");
00420       return -1;
00421        }
00422        return 1;
00423    }
00424 
00425    /* Append branches until out of branches or Q_FLAG is set */
00426    prev = avp;
00427    while ((avp = search_next_avp(avp, &val))) {
00428        destroy_avp(prev);
00429 
00430        LM_DBG("next contact is <%s>\n", val.s.s);
00431 
00432        if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)
00433       == 0) {
00434       LM_ERR("decoding of branch info <%.*s> failed\n",
00435              val.s.len, val.s.s);
00436       destroy_avp(avp);
00437       return -1;
00438        }
00439 
00440        if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) {
00441       LM_ERR("appending branch failed\n");
00442       destroy_avp(avp);
00443       return -1;
00444        }
00445 
00446        if (avp->flags & Q_FLAG) {
00447       destroy_avp(avp);
00448       val.n = fr_inv_timer_next;
00449       if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val)
00450           != 0) {
00451           LM_ERR("setting of fr_inv_timer_avp failed\n");
00452           return -1;
00453       }
00454       return 1;
00455        }
00456        prev = avp;
00457    }
00458    
00459     } else {
00460    
00461    /* Transaction exists => only load branches */
00462 
00463    /* Find first contacts_avp value */
00464    avp = search_first_avp(contacts_avp_type, contacts_avp, &val, 0);
00465    if (!avp) return -1;
00466 
00467    /* Append branches until out of branches or Q_FLAG is set */
00468    prev = avp;
00469    do {
00470 
00471        LM_DBG("next contact is <%s>\n", val.s.s);
00472 
00473        if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)
00474       == 0) {
00475       LM_ERR("decoding of branch info <%.*s> failed\n",
00476              val.s.len, val.s.s);
00477       destroy_avp(avp);
00478       return -1;
00479        }
00480        
00481        if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) {
00482       LM_ERR("appending branch failed\n");
00483       destroy_avp(avp);
00484       return -1;
00485        }
00486 
00487        if (avp->flags & Q_FLAG) {
00488       destroy_avp(avp);
00489       return 1;
00490        }
00491 
00492        prev = avp;
00493        avp = search_next_avp(avp, &val);
00494        destroy_avp(prev);
00495 
00496    } while (avp);
00497 
00498    /* Restore fr_inv_timer */
00499    val.n = timer_id2timeout[FR_INV_TIMER_LIST];
00500    if (add_avp(fr_inv_timer_avp_type, fr_inv_timer_avp, val) != 0) {
00501        LM_ERR("setting of fr_inv_timer_avp failed\n");
00502        return -1;
00503    }
00504    
00505     }
00506 
00507     return 1;
00508 }

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