Mercurial > hg > freeDiameter
diff extensions/rt_un_number/rtun.c @ 514:179ef7de53de
New extension: load-balancing based on numerical user-name AVP values
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Wed, 25 Aug 2010 19:00:25 +0900 |
parents | |
children | b9167b4de7dc |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/rt_un_number/rtun.c Wed Aug 25 19:00:25 2010 +0900 @@ -0,0 +1,165 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis <sdecugis@nict.go.jp> * +* * +* Copyright (c) 2010, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* + * Load-balancing routing extension for numeric-based User-Name values + * + * This extension relies on a User-Name AVP in the format: "<number> text". + * It will load-balance the messages between the servers defined in the configuration, + * based on the number. + * For example, if the configuratino contains 3 servers A, B, C, then: + * "1 first user" -> A + * "2 second user" -> B + * "3 third" -> C + * "4 fourth" -> A + * "99 and so on" -> C + * + * The message is sent to the server selected only if it is in OPEN state, of course. + * Otherwise, this extension has no effect, and the default routing behavior will be used. + * + * Note that the score added is FD_SCORE_LOAD_BALANCE, which mean any other routing + * indication will take precedence (for example Destination-Host AVP). + */ + +#include "rtun.h" + +/* The configuration structure */ +struct rtun_conf rtun_conf; + +/* The callback called on new messages */ +static int rtun_out(void * cbdata, struct msg * msg, struct fd_list * candidates) +{ + struct avp * avp = NULL; + + TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); + + CHECK_PARAMS(msg && candidates); + + /* Check if it is worth processing the message */ + if (FD_IS_LIST_EMPTY(candidates)) { + return 0; + } + + /* Now search the user-name AVP */ + CHECK_FCT( fd_msg_search_avp ( msg, rtun_conf.username, &avp ) ); + if (avp != NULL) { + struct avp_hdr * ahdr = NULL; + CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); + if (ahdr->avp_value != NULL) { + int conv = 0; + int idx; + + /* We cannot use strtol or sscanf functions without copying the AVP value and \0-terminate it... */ + for (idx = 0; idx < ahdr->avp_value->os.len; idx++) { + char c = (char) ahdr->avp_value->os.data[idx]; + if (c == ' ') + continue; + if ((c >= '0') && (c <= '9')) { + conv *= 10; + conv += c - '0'; + continue; + } + /* we found a non-numeric character, stop */ + break; + } + + if (conv) { + /* We succeeded in reading a numerical value */ + struct fd_list * c; + char *s; + + idx = conv % rtun_conf.serv_nb; + s = rtun_conf.servs[idx]; + + /* We should send the message to 's', search in the candidates list */ + for (c = candidates->next; c != candidates; c = c->next) { + struct rtd_candidate * cand = (struct rtd_candidate *)c; + + if (strcmp(s, cand->diamid) == 0) { + cand->score += FD_SCORE_LOAD_BALANCE; + break; + } + } + } + } + } + + return 0; +} + +/* handler */ +static struct fd_rt_out_hdl * rtun_hdl = NULL; + +/* entry point */ +static int rtun_entry(char * conffile) +{ + TRACE_ENTRY("%p", conffile); + + /* Initialize the configuration */ + memset(&rtun_conf, 0, sizeof(rtun_conf)); + + /* Search the User-Name AVP in the dictionary */ + CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &rtun_conf.username, ENOENT )); + + /* Parse the configuration file */ + CHECK_FCT( rtun_conf_handle(conffile) ); + + /* Register the callback */ + CHECK_FCT( fd_rt_out_register( rtun_out, NULL, 1, &rtun_hdl ) ); + + /* We're done */ + return 0; +} + +/* Unload */ +void fd_ext_fini(void) +{ + int i; + TRACE_ENTRY(); + + /* Unregister the cb */ + CHECK_FCT_DO( fd_rt_out_unregister ( rtun_hdl, NULL ), /* continue */ ); + + /* Destroy the data */ + if (rtun_conf.servs) + for (i = 0; i < rtun_conf.serv_nb; i++) + free(rtun_conf.servs[i]); + free(rtun_conf.servs); + + /* Done */ + return ; +} + +EXTENSION_ENTRY("rt_un_number", rtun_entry);