mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
946 lines
17 KiB
946 lines
17 KiB
/**
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2011 Daniel-Constantin Mierla (asipto.com)
|
|
*
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* Kamailio is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version
|
|
*
|
|
* Kamailio is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "../../sr_module.h"
|
|
#include "../../dprint.h"
|
|
#include "../../ut.h"
|
|
#include "../../mem/mem.h"
|
|
#include "../../data_lump.h"
|
|
#include "../../data_lump_rpl.h"
|
|
#include "../../lib/kcore/cmpapi.h"
|
|
|
|
#include "app_mono_api.h"
|
|
|
|
#include <mono/metadata/mono-config.h>
|
|
|
|
#define SRVERSION "1.0"
|
|
|
|
/**
|
|
*
|
|
*/
|
|
typedef struct _sr_mono_load
|
|
{
|
|
char *script;
|
|
MonoDomain *domain;
|
|
MonoAssembly *assembly;
|
|
struct _sr_mono_load *next;
|
|
} sr_mono_load_t;
|
|
|
|
static sr_mono_load_t *_sr_mono_load_list = NULL;
|
|
|
|
int sr_mono_load_class_core();
|
|
int sr_mono_load_class_pv();
|
|
int sr_mono_load_class_hdr();
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static sr_mono_env_t _sr_M_env;
|
|
|
|
/**
|
|
* @return the static Mono env
|
|
*/
|
|
sr_mono_env_t *sr_mono_env_get(void)
|
|
{
|
|
return &_sr_M_env;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int sr_mono_load_script(char *script)
|
|
{
|
|
sr_mono_load_t *mi;
|
|
|
|
if(_sr_mono_load_list != NULL)
|
|
{
|
|
LM_ERR("only one assembly can be loaded\n");
|
|
return -1;
|
|
}
|
|
mi = (sr_mono_load_t*)pkg_malloc(sizeof(sr_mono_load_t));
|
|
if(mi==NULL)
|
|
{
|
|
LM_ERR("no more pkg\n");
|
|
return -1;
|
|
}
|
|
memset(mi, 0, sizeof(sr_mono_load_t));
|
|
mi->script = script;
|
|
mi->next = _sr_mono_load_list;
|
|
_sr_mono_load_list = mi;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int sr_mono_assembly_loaded(void)
|
|
{
|
|
if(_sr_mono_load_list != NULL)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int sr_mono_register_module(char *mname)
|
|
{
|
|
// if(mono_sr_exp_register_mod(mname)==0)
|
|
// return 0;
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int mono_sr_init_mod(void)
|
|
{
|
|
memset(&_sr_M_env, 0, sizeof(sr_mono_env_t));
|
|
// if(mono_sr_exp_init_mod()<0)
|
|
// return -1;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int mono_sr_init_load(void)
|
|
{
|
|
sr_mono_load_t *mi;
|
|
if(_sr_mono_load_list == NULL) {
|
|
LM_DBG("no assembly to load\n");
|
|
return 0;
|
|
}
|
|
mono_config_parse (NULL);
|
|
mi = _sr_mono_load_list;
|
|
if(mi->domain != NULL)
|
|
{
|
|
LM_ERR("worker mono environment already initialized\n");
|
|
return 0;
|
|
}
|
|
while(mi!=NULL)
|
|
{
|
|
mi->domain = mono_jit_init (mi->script);
|
|
if (mi->domain==NULL) {
|
|
LM_ERR("failed to init domain for: %s\n", mi->script);
|
|
return -1;
|
|
}
|
|
sr_mono_load_class_core();
|
|
sr_mono_load_class_pv();
|
|
sr_mono_load_class_hdr();
|
|
|
|
mi->assembly = mono_domain_assembly_open(mi->domain, mi->script);
|
|
if (mi->assembly==NULL) {
|
|
LM_ERR("failed to open assembly: %s\n", mi->script);
|
|
return -1;
|
|
}
|
|
mi = mi->next;
|
|
/* only one (first) assembly for now */
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int mono_sr_init_probe(void)
|
|
{
|
|
/* todo: test if assemblies exist */
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int mono_sr_init_child(void)
|
|
{
|
|
memset(&_sr_M_env, 0, sizeof(sr_mono_env_t));
|
|
|
|
/*
|
|
* Load the default Mono configuration file, this is needed
|
|
* if you are planning on using the dllmaps defined on the
|
|
* system configuration
|
|
*/
|
|
mono_config_parse (NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
void mono_sr_destroy(void)
|
|
{
|
|
memset(&_sr_M_env, 0, sizeof(sr_mono_env_t));
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int mono_sr_initialized(void)
|
|
{
|
|
if(_sr_M_env.domain==NULL)
|
|
return 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int app_mono_exec(struct sip_msg *msg, char *script, char *param)
|
|
{
|
|
int ret;
|
|
char *argv[2];
|
|
int argc;
|
|
|
|
argc = 1;
|
|
argv[0] = script;
|
|
if(param!=NULL) {
|
|
argc++;
|
|
argv[1] = param;
|
|
}
|
|
LM_DBG("executing Mono assembly: [[%s]]\n", argv[0]);
|
|
_sr_M_env.msg = msg;
|
|
|
|
mono_config_parse (NULL);
|
|
/*
|
|
* mono_jit_init() creates a domain: each assembly is
|
|
* loaded and run in a MonoDomain.
|
|
*/
|
|
_sr_M_env.domain = mono_jit_init (argv[0]);
|
|
/*
|
|
* We add our special internal functions, so that C# code
|
|
* can call us back.
|
|
*/
|
|
sr_mono_load_class_core();
|
|
sr_mono_load_class_pv();
|
|
sr_mono_load_class_hdr();
|
|
|
|
_sr_M_env.assembly = mono_domain_assembly_open(_sr_M_env.domain, argv[0]);
|
|
if (_sr_M_env.assembly==NULL) {
|
|
ret = -1;
|
|
goto done;
|
|
}
|
|
/*
|
|
* mono_jit_exec() will run the Main() method in the assembly.
|
|
* The return value needs to be looked up from
|
|
* System.Environment.ExitCode.
|
|
*/
|
|
mono_jit_exec(_sr_M_env.domain, _sr_M_env.assembly, argc, argv);
|
|
ret = mono_environment_exitcode_get();
|
|
LM_DBG("returned code from mono environment: %d\n", ret);
|
|
|
|
done:
|
|
mono_jit_cleanup(_sr_M_env.domain);
|
|
|
|
memset(&_sr_M_env, 0, sizeof(sr_mono_env_t));
|
|
return (ret==0)?1:-1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int app_mono_run(struct sip_msg *msg, char *arg)
|
|
{
|
|
int ret;
|
|
char *argv[2];
|
|
int argc;
|
|
sr_mono_load_t *mi;
|
|
|
|
if(_sr_mono_load_list == NULL)
|
|
return -1;
|
|
mi = _sr_mono_load_list;
|
|
|
|
LM_DBG("running Mono assembly: [[%s]]\n", mi->script);
|
|
_sr_M_env.msg = msg;
|
|
|
|
_sr_M_env.domain = mi->domain;
|
|
_sr_M_env.assembly = mi->assembly;
|
|
if (_sr_M_env.assembly==NULL) {
|
|
LM_DBG("empty assembly\n");
|
|
memset(&_sr_M_env, 0, sizeof(sr_mono_env_t));
|
|
return -1;
|
|
}
|
|
mono_domain_set(_sr_M_env.domain, 0);
|
|
argc = 1;
|
|
argv[0] = mi->script;
|
|
if(arg!=NULL) {
|
|
argc++;
|
|
argv[1] = arg;
|
|
}
|
|
mono_jit_exec(_sr_M_env.domain, _sr_M_env.assembly, argc, argv);
|
|
ret = mono_environment_exitcode_get();
|
|
LM_DBG("returned code from mono environment: %d\n", ret);
|
|
|
|
memset(&_sr_M_env, 0, sizeof(sr_mono_env_t));
|
|
return (ret==0)?1:-1;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static MonoString* sr_mono_api_version() {
|
|
return mono_string_new (mono_domain_get(), SRVERSION);
|
|
}
|
|
|
|
static void sr_mono_log(int level, MonoString *text) {
|
|
char *logmsg;
|
|
logmsg = mono_string_to_utf8(text);
|
|
LOG(level, "%s", logmsg);
|
|
mono_free(logmsg);
|
|
}
|
|
|
|
static void sr_mono_err(MonoString *text) {
|
|
char *logmsg;
|
|
logmsg = mono_string_to_utf8(text);
|
|
LOG(L_ERR, "%s", logmsg);
|
|
mono_free(logmsg);
|
|
}
|
|
|
|
static void sr_mono_dbg(MonoString *text) {
|
|
char *logmsg;
|
|
logmsg = mono_string_to_utf8(text);
|
|
LOG(L_DBG, "%s", logmsg);
|
|
mono_free(logmsg);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_modf(MonoString *nfunc)
|
|
{
|
|
int ret;
|
|
int mod_type;
|
|
struct run_act_ctx ra_ctx;
|
|
unsigned modver;
|
|
struct action *act = NULL;
|
|
sr31_cmd_export_t* expf;
|
|
sr_mono_env_t *env_M;
|
|
char *func = NULL;
|
|
|
|
env_M = sr_mono_env_get();
|
|
if(env_M->msg==NULL)
|
|
goto error;
|
|
|
|
func = mono_string_to_utf8(nfunc);
|
|
|
|
expf = find_export_record(func, 0, 0, &modver);
|
|
if (expf==NULL) {
|
|
LM_ERR("function '%s' is not available\n", func);
|
|
goto error;
|
|
}
|
|
/* check fixups */
|
|
if (expf->fixup!=NULL && expf->free_fixup==NULL) {
|
|
LM_ERR("function '%s' has fixup - cannot be used\n", func);
|
|
goto error;
|
|
}
|
|
mod_type = MODULE0_T;
|
|
|
|
act = mk_action(mod_type, 1 /* number of (type, value) pairs */,
|
|
MODEXP_ST, expf, /* function */
|
|
NUMBER_ST, 0, /* parameter number */
|
|
STRING_ST, NULL, /* param. 1 */
|
|
STRING_ST, NULL, /* param. 2 */
|
|
STRING_ST, NULL, /* param. 3 */
|
|
STRING_ST, NULL, /* param. 4 */
|
|
STRING_ST, NULL, /* param. 5 */
|
|
STRING_ST, NULL /* param. 6 */
|
|
);
|
|
|
|
if (act==NULL) {
|
|
LM_ERR("action structure could not be created for '%s'\n", func);
|
|
goto error;
|
|
}
|
|
|
|
/* handle fixups */
|
|
if (expf->fixup) {
|
|
/* no parameters */
|
|
if(expf->fixup(0, 0)<0)
|
|
{
|
|
LM_ERR("Error in fixup (0) for '%s'\n", func);
|
|
goto error;
|
|
}
|
|
}
|
|
init_run_actions_ctx(&ra_ctx);
|
|
ret = do_action(&ra_ctx, act, env_M->msg);
|
|
pkg_free(act);
|
|
mono_free(func);
|
|
return ret;
|
|
|
|
error:
|
|
if(func!=NULL)
|
|
mono_free(func);
|
|
if(act!=NULL)
|
|
pkg_free(act);
|
|
return -127;
|
|
}
|
|
|
|
|
|
static const sr_M_export_t _sr_M_export_core[] = {
|
|
{"SR.Core::APIVersion", sr_mono_api_version},
|
|
{"SR.Core::Log", sr_mono_log},
|
|
{"SR.Core::Err", sr_mono_err},
|
|
{"SR.Core::Dbg", sr_mono_dbg},
|
|
{"SR.Core::ModF", sr_mono_modf},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
int sr_mono_load_class_core()
|
|
{
|
|
int i;
|
|
for(i=0; _sr_M_export_core[i].name!=NULL; i++)
|
|
mono_add_internal_call(_sr_M_export_core[i].name, _sr_M_export_core[i].method);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static MonoString *sr_mono_pv_gets (MonoString *pv)
|
|
{
|
|
str pvn = {0};
|
|
pv_spec_t *pvs;
|
|
pv_value_t val;
|
|
sr_mono_env_t *env_M;
|
|
int pl;
|
|
|
|
env_M = sr_mono_env_get();
|
|
|
|
pvn.s = mono_string_to_utf8(pv);
|
|
if(pvn.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
pvn.len = strlen(pvn.s);
|
|
LM_DBG("pv get: %s\n", pvn.s);
|
|
pl = pv_locate_name(&pvn);
|
|
if(pl != pvn.len)
|
|
{
|
|
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
|
|
goto error;
|
|
}
|
|
pvs = pv_cache_get(&pvn);
|
|
if(pvs==NULL)
|
|
{
|
|
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
memset(&val, 0, sizeof(pv_value_t));
|
|
if(pv_get_spec_value(env_M->msg, pvs, &val) != 0)
|
|
{
|
|
LM_ERR("unable to get pv value for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
if((val.flags&PV_VAL_NULL) || !(val.flags&PV_VAL_STR))
|
|
{
|
|
mono_free(pvn.s);
|
|
return NULL;
|
|
}
|
|
mono_free(pvn.s);
|
|
return mono_string_new_len (mono_domain_get(), val.rs.s, val.rs.len);
|
|
|
|
error:
|
|
if(pvn.s!=NULL)
|
|
mono_free(pvn.s);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_pv_geti (MonoString *pv)
|
|
{
|
|
str pvn = {0};
|
|
pv_spec_t *pvs;
|
|
pv_value_t val;
|
|
int pl;
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
pvn.s = mono_string_to_utf8(pv);
|
|
|
|
if(pvn.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
pvn.len = strlen(pvn.s);
|
|
LM_DBG("pv get: %s\n", pvn.s);
|
|
pl = pv_locate_name(&pvn);
|
|
if(pl != pvn.len)
|
|
{
|
|
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
|
|
goto error;
|
|
}
|
|
pvs = pv_cache_get(&pvn);
|
|
if(pvs==NULL)
|
|
{
|
|
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
memset(&val, 0, sizeof(pv_value_t));
|
|
if(pv_get_spec_value(env_M->msg, pvs, &val) != 0)
|
|
{
|
|
LM_ERR("unable to get pv value for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
if((val.flags&PV_VAL_NULL) || !(val.flags&PV_TYPE_INT))
|
|
{
|
|
mono_free(pvn.s);
|
|
return 0;
|
|
}
|
|
mono_free(pvn.s);
|
|
return val.ri;
|
|
|
|
error:
|
|
if(pvn.s!=NULL)
|
|
mono_free(pvn.s);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_pv_seti (MonoString *pv, int iv)
|
|
{
|
|
str pvn = {0};
|
|
pv_spec_t *pvs;
|
|
pv_value_t val;
|
|
int pl;
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
pvn.s = mono_string_to_utf8(pv);
|
|
|
|
if(pvn.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
memset(&val, 0, sizeof(pv_value_t));
|
|
val.ri = iv;
|
|
val.flags |= PV_TYPE_INT|PV_VAL_INT;
|
|
|
|
pvn.len = strlen(pvn.s);
|
|
LM_DBG("pv set: %s\n", pvn.s);
|
|
pl = pv_locate_name(&pvn);
|
|
if(pl != pvn.len)
|
|
{
|
|
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
|
|
goto error;
|
|
}
|
|
pvs = pv_cache_get(&pvn);
|
|
if(pvs==NULL)
|
|
{
|
|
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
if(pv_set_spec_value(env_M->msg, pvs, 0, &val)<0)
|
|
{
|
|
LM_ERR("unable to set pv [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
|
|
mono_free(pvn.s);
|
|
return 0;
|
|
error:
|
|
if(pvn.s!=NULL)
|
|
mono_free(pvn.s);
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_pv_sets (MonoString *pv, MonoString *sv)
|
|
{
|
|
str pvn = {0};
|
|
pv_spec_t *pvs;
|
|
pv_value_t val;
|
|
int pl;
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
pvn.s = mono_string_to_utf8(pv);
|
|
|
|
if(pvn.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
memset(&val, 0, sizeof(pv_value_t));
|
|
val.rs.s = mono_string_to_utf8(sv);
|
|
if(val.rs.s == NULL)
|
|
goto error;
|
|
|
|
val.rs.len = strlen(val.rs.s);
|
|
val.flags |= PV_VAL_STR;
|
|
|
|
pvn.len = strlen(pvn.s);
|
|
LM_DBG("pv set: %s\n", pvn.s);
|
|
pl = pv_locate_name(&pvn);
|
|
if(pl != pvn.len)
|
|
{
|
|
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
|
|
goto error;
|
|
}
|
|
pvs = pv_cache_get(&pvn);
|
|
if(pvs==NULL)
|
|
{
|
|
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
if(pv_set_spec_value(env_M->msg, pvs, 0, &val)<0)
|
|
{
|
|
LM_ERR("unable to set pv [%s]\n", pvn.s);
|
|
return -1;
|
|
}
|
|
|
|
mono_free(pvn.s);
|
|
return 0;
|
|
error:
|
|
if(pvn.s!=NULL)
|
|
mono_free(pvn.s);
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_pv_unset (MonoString *pv)
|
|
{
|
|
str pvn = {0};
|
|
pv_spec_t *pvs;
|
|
pv_value_t val;
|
|
int pl;
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
pvn.s = mono_string_to_utf8(pv);
|
|
|
|
if(pvn.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
pvn.len = strlen(pvn.s);
|
|
LM_DBG("pv unset: %s\n", pvn.s);
|
|
pl = pv_locate_name(&pvn);
|
|
if(pl != pvn.len)
|
|
{
|
|
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
|
|
goto error;
|
|
}
|
|
pvs = pv_cache_get(&pvn);
|
|
if(pvs==NULL)
|
|
{
|
|
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
memset(&val, 0, sizeof(pv_value_t));
|
|
val.flags |= PV_VAL_NULL;
|
|
if(pv_set_spec_value(env_M->msg, pvs, 0, &val)<0)
|
|
{
|
|
LM_ERR("unable to unset pv [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
|
|
mono_free(pvn.s);
|
|
return 0;
|
|
error:
|
|
if(pvn.s!=NULL)
|
|
mono_free(pvn.s);
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_pv_is_null (MonoString *pv)
|
|
{
|
|
str pvn = {0};
|
|
pv_spec_t *pvs;
|
|
pv_value_t val;
|
|
int pl;
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
pvn.s = mono_string_to_utf8(pv);
|
|
|
|
if(pvn.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
pvn.len = strlen(pvn.s);
|
|
LM_DBG("pv is null test: %s\n", pvn.s);
|
|
pl = pv_locate_name(&pvn);
|
|
if(pl != pvn.len)
|
|
{
|
|
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
|
|
goto error;
|
|
}
|
|
pvs = pv_cache_get(&pvn);
|
|
if(pvs==NULL)
|
|
{
|
|
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
memset(&val, 0, sizeof(pv_value_t));
|
|
if(pv_get_spec_value(env_M->msg, pvs, &val) != 0)
|
|
{
|
|
LM_INFO("unable to get pv value for [%s]\n", pvn.s);
|
|
goto error;
|
|
}
|
|
mono_free(pvn.s);
|
|
if(val.flags&PV_VAL_NULL)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
error:
|
|
if(pvn.s!=NULL)
|
|
mono_free(pvn.s);
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static const sr_M_export_t _sr_M_export_pv[] = {
|
|
{"SR.PV::GetS", sr_mono_pv_gets},
|
|
{"SR.PV::GetI", sr_mono_pv_geti},
|
|
{"SR.PV::SetI", sr_mono_pv_seti},
|
|
{"SR.PV::SetS", sr_mono_pv_sets},
|
|
{"SR.PV::Unset", sr_mono_pv_unset},
|
|
{"SR.PV::IsNull", sr_mono_pv_is_null},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
int sr_mono_load_class_pv()
|
|
{
|
|
int i;
|
|
for(i=0; _sr_M_export_pv[i].name!=NULL; i++)
|
|
mono_add_internal_call(_sr_M_export_pv[i].name, _sr_M_export_pv[i].method);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_hdr_append (MonoString *hv)
|
|
{
|
|
struct lump* anchor;
|
|
struct hdr_field *hf;
|
|
char *hdr;
|
|
str txt = {0};
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
txt.s = mono_string_to_utf8(hv);
|
|
|
|
if(txt.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
txt.len = strlen(txt.s);
|
|
|
|
LM_DBG("append hf: %s\n", txt.s);
|
|
if (parse_headers(env_M->msg, HDR_EOH_F, 0) == -1)
|
|
{
|
|
LM_ERR("error while parsing message\n");
|
|
goto error;
|
|
}
|
|
|
|
hf = env_M->msg->last_header;
|
|
hdr = (char*)pkg_malloc(txt.len);
|
|
if(hdr==NULL)
|
|
{
|
|
LM_ERR("no pkg memory left\n");
|
|
goto error;
|
|
}
|
|
memcpy(hdr, txt.s, txt.len);
|
|
anchor = anchor_lump(env_M->msg,
|
|
hf->name.s + hf->len - env_M->msg->buf, 0, 0);
|
|
if(insert_new_lump_before(anchor, hdr, txt.len, 0) == 0)
|
|
{
|
|
LM_ERR("can't insert lump\n");
|
|
pkg_free(hdr);
|
|
goto error;
|
|
}
|
|
mono_free(txt.s);
|
|
return 0;
|
|
|
|
error:
|
|
if(txt.s!=NULL)
|
|
mono_free(txt.s);
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_hdr_remove (MonoString *hv)
|
|
{
|
|
struct lump* anchor;
|
|
struct hdr_field *hf;
|
|
str hname;
|
|
str txt = {0};
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
txt.s = mono_string_to_utf8(hv);
|
|
|
|
if(txt.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
txt.len = strlen(txt.s);
|
|
|
|
LM_DBG("remove hf: %s\n", txt.s);
|
|
if (parse_headers(env_M->msg, HDR_EOH_F, 0) == -1) {
|
|
LM_ERR("error while parsing message\n");
|
|
goto error;
|
|
}
|
|
|
|
hname.s = txt.s;
|
|
hname.len = txt.len;
|
|
for (hf=env_M->msg->headers; hf; hf=hf->next)
|
|
{
|
|
if (cmp_hdrname_str(&hf->name, &hname)==0)
|
|
{
|
|
anchor=del_lump(env_M->msg,
|
|
hf->name.s - env_M->msg->buf, hf->len, 0);
|
|
if (anchor==0)
|
|
{
|
|
LM_ERR("cannot remove hdr %s\n", txt.s);
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
mono_free(txt.s);
|
|
return 0;
|
|
|
|
error:
|
|
if(txt.s!=NULL)
|
|
mono_free(txt.s);
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_hdr_insert (MonoString *hv)
|
|
{
|
|
struct lump* anchor;
|
|
struct hdr_field *hf;
|
|
char *hdr;
|
|
str txt = {0};
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
txt.s = mono_string_to_utf8(hv);
|
|
|
|
if(txt.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
txt.len = strlen(txt.s);
|
|
|
|
LM_DBG("insert hf: %s\n", txt.s);
|
|
hf = env_M->msg->headers;
|
|
hdr = (char*)pkg_malloc(txt.len);
|
|
if(hdr==NULL)
|
|
{
|
|
LM_ERR("no pkg memory left\n");
|
|
goto error;
|
|
}
|
|
memcpy(hdr, txt.s, txt.len);
|
|
anchor = anchor_lump(env_M->msg,
|
|
hf->name.s + hf->len - env_M->msg->buf, 0, 0);
|
|
if(insert_new_lump_before(anchor, hdr, txt.len, 0) == 0)
|
|
{
|
|
LM_ERR("can't insert lump\n");
|
|
pkg_free(hdr);
|
|
goto error;
|
|
}
|
|
mono_free(txt.s);
|
|
return 0;
|
|
|
|
error:
|
|
if(txt.s!=NULL)
|
|
mono_free(txt.s);
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static int sr_mono_hdr_append_to_reply (MonoString *hv)
|
|
{
|
|
str txt = {0};
|
|
sr_mono_env_t *env_M;
|
|
|
|
env_M = sr_mono_env_get();
|
|
txt.s = mono_string_to_utf8(hv);
|
|
|
|
if(txt.s==NULL || env_M->msg==NULL)
|
|
goto error;
|
|
|
|
txt.len = strlen(txt.s);
|
|
|
|
LM_DBG("append to reply: %s\n", txt.s);
|
|
|
|
if(add_lump_rpl(env_M->msg, txt.s, txt.len, LUMP_RPL_HDR)==0)
|
|
{
|
|
LM_ERR("unable to add reply lump\n");
|
|
goto error;
|
|
}
|
|
|
|
mono_free(txt.s);
|
|
return 0;
|
|
|
|
error:
|
|
if(txt.s!=NULL)
|
|
mono_free(txt.s);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
static const sr_M_export_t _sr_M_export_hdr[] = {
|
|
{"SR.HDR::Append", sr_mono_hdr_append},
|
|
{"SR.HDR::Remove", sr_mono_hdr_remove},
|
|
{"SR.HDR::Insert", sr_mono_hdr_insert},
|
|
{"SR.HDR::AppendToReply", sr_mono_hdr_append_to_reply},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
int sr_mono_load_class_hdr()
|
|
{
|
|
int i;
|
|
for(i=0; _sr_M_export_hdr[i].name!=NULL; i++)
|
|
mono_add_internal_call(_sr_M_export_hdr[i].name, _sr_M_export_hdr[i].method);
|
|
return 0;
|
|
}
|
|
|
|
|