Documentation |
Documentation -> Development Manual 3.6 -> Extending the Configuration FileThis page has been visited 159 times. Pages for other versions: Older versions:
Table of Content (hide) OpenSIPS uses flex and bison in order to parse the configuration file and then build the entire action tree that a SIP message will go through once it is read from network level. 1. Adding a core parameterIn the following step by step tutorial, we will follow the implementation of the udp_workers core parameter, which is an integer controlling the number of OpenSIPS processes per UDP interface. extern int udp_workers_no;
/* Default value in case the parameter is not set from the script */ int udp_workers_no = 8;
/* Default value in case the parameter is not set from the script */ UDP_WORKERS udp_workers
%token UDP_WORKERS
| UDP_WORKERS EQUAL NUMBER { udp_workers_no=$3; } | UDP_WORKERS EQUAL error { yyerror("number expected"); }
2. Adding a core functionIn the following step by step tutorial, we will follow the implementation of the xlog core function, which is used to print information to the logging facility. Note that xlog can receive either a single parameter (the string to be printed), or two parameters (the log level and then the string to be printed). First, we extend the lexer file with the new word. Under cfg.lex, we have: XLOG "xlog"
%token XLOG ... ... | XLOG LPAREN STRING RPAREN { mk_action1($$, XLOG_T, STR_ST, $3); } | XLOG LPAREN folded_string RPAREN { mk_action1($$, XLOG_T, STR_ST, $3); } | XLOG LPAREN STRING COMMA STRING RPAREN { mk_action2($$, XLOG_T, STR_ST, STR_ST, $3, $5); } | XLOG LPAREN STRING COMMA folded_string RPAREN { mk_action2($$, XLOG_T, STR_ST, STR_ST, $3, $5); }
case XLOG_T: s.s = (char*)t->elem[1].u.data; if (s.s == NULL) { /* commands have only one parameter */ s.s = (char *)t->elem[0].u.data; s.len = strlen(s.s); if(s.len==0) { LM_ERR("param is empty string!\n"); return E_CFG; } if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n", s.s); ret=E_BUG; goto error; } t->elem[0].u.data = (void*)model; t->elem[0].type = SCRIPTVAR_ELEM_ST; } else { /* there are two parameters */
case XLOG_T: script_trace("core", "xlog", msg, a->file, a->line) ; if (a->elem[1].u.data != NULL) { if (a->elem[1].type != SCRIPTVAR_ELEM_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[1].type); ret=E_BUG; break; } if (a->elem[0].type != STR_ST) { LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type); ret=E_BUG; break; } ret = xlog_2(msg,a->elem[0].u.data, a->elem[1].u.data); if (ret < 0) { LM_ERR("error while printing xlog message\n"); break; } } else { 3. Adding a core Pseudo-VariableAll the OpenSIPS core pseudo-variables are defined in pvar.c : static pv_export_t _pv_names_table[] = { {{"avp", (sizeof("avp")-1)}, PVT_AVP, pv_get_avp, pv_set_avp, pv_parse_avp_name, pv_parse_index, 0, 0}, {{"hdr", (sizeof("hdr")-1)}, PVT_HDR, pv_get_hdr, 0, pv_parse_hdr_name, pv_parse_index, 0, 0}, {{"hdrcnt", (sizeof("hdrcnt")-1)}, PVT_HDRCNT, pv_get_hdrcnt, 0, pv_parse_hdr_name, 0, 0, 0}, {{"var", (sizeof("var")-1)}, PVT_SCRIPTVAR, pv_get_scriptvar, pv_set_scriptvar, pv_parse_scriptvar_name, 0, 0, 0}, {{"ai", (sizeof("ai")-1)}, /* */ PVT_PAI_URI, pv_get_pai, 0, 0, 0, 0, 0}, {{"au", (sizeof("au")-1)}, /* */ PVT_AUTH_USERNAME, pv_get_authattr, 0, 0, 0, pv_init_iname, 1}, ... ... ...
/*! \brief * PV spec format: * - $class_name * - $class_name(inner_name) * - $(class_name[index]) * - $(class_name(inner_name)[index]) * - $(class_name{transformation}) * - $(class_name(inner_name){transformation}) * - $(class_name[index]{transformation}) * - $(class_name(inner_name)[index]{transformation}) */ typedef struct _pv_export { str name; /*!< class name of PV */ pv_type_t type; /*!< type of PV */ pv_getf_t getf; /*!< function to get the value */ pv_setf_t setf; /*!< function to set the value */ pv_parse_name_f parse_name; /*!< function to parse the inner name */ pv_parse_index_f parse_index; /*!< function to parse the index of PV */ pv_init_param_f init_param; /*!< function to init the PV spec */ int iparam; /*!< parameter for the init function */ } pv_export_t;
{{"ru", (sizeof("ru")-1)}, /* */ PVT_RURI, pv_get_ruri, pv_set_ruri, 0, 0, 0, 0}, Our new pvar will be accessible from script by using $ru. Read access from the script will lead to pv_get_ruri getting called, while write requests to $ru will make a call to pv_set_ruri.
/* Parameters : msg - the message context to evaluate the current pvar param - the parameter provided for evaluating the pvar res - the output value of our pvar Returns : 0 in case of success, negative in case of error */ static int pv_get_ruri(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { if(msg==NULL || res==NULL) return -1; if(msg->first_line.type == SIP_REPLY) /* REPLY doesnt have a ruri */ return pv_get_null(msg, param, res); if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse the R-URI\n"); return pv_get_null(msg, param, res); } if (msg->new_uri.s!=NULL) return pv_get_strval(msg, param, res, &msg->new_uri); return pv_get_strval(msg, param, res, &msg->first_line.u.request.uri); }
For all read access on the PVARs from contexts where the PVAR does not have any meaningful value (eg. Request-URI from a Reply Context), make sure to use pv_get_null to signal this to the script writer.
/* Parameters : msg - the SIP message to apply the changes to param - the parameter provided for evaluating the pvar op - further indication on the type of write access to be done val - value to be pushed to our pvar Returns : 0 in case of success, negative in case of error */ int pv_set_ruri(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val) { if(msg==NULL || param==NULL || val==NULL) { LM_ERR("bad parameters\n"); return -1; } /* type checking, we can only push strings to R-URI */ if(!(val->flags&PV_VAL_STR)) { LM_ERR("str value required to set R-URI\n"); goto error; } /* populate the message R-URI with the string value from the provided val */ if (set_ruri( msg, &val->rs)!=0) { LM_ERR("failed to set RURI\n"); goto error; } return 0; error: return -1; } |