1
0
Fork 0
mbuni/mbuni/mmsc/mmsc_cfg.c

400 lines
13 KiB
C

/*
* Mbuni - Open Source MMS Gateway
*
* MMSC CFG: MMC configuration and misc. functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <sys/file.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mmsc_cfg.h"
#include "mms_queue.h"
#define MAXQTRIES 100
#define BACKOFF_FACTOR 5*60 /* In seconds */
#define QUEUERUN_INTERVAL 15*60 /* 15 minutes. */
#define DEFAULT_EXPIRE 3600*24*7 /* One week */
#define MMS_PORT 8191 /* Default content fetch port. */
static void *load_module(CfgGroup *grp, char *config_key, char *symbolname)
{
Octstr *s;
void *retval = NULL;
s = cfg_get(grp, octstr_imm(config_key));
if (s) {
void *x = dlopen(octstr_get_cstr(s), RTLD_LAZY);
void *y = NULL;
#ifdef __APPLE__
char sbuf[512];
sprintf(sbuf, "_%s", symbolname);
#endif
if (x == NULL || ((y = dlsym(x, symbolname)) == NULL
#ifdef __APPLE__ /* fink version of dlsym has issues it seems. */
&& (y = dlsym(x, sbuf)) == NULL
#endif
))
panic(0,
"Error, unable to load dynamic libary (%s): "
"libhandle is %s, funcs is %s, err=%s",
octstr_get_cstr(s),
x ? "OK" : "Not OK", y ? "OK" : "Not OK", dlerror());
else
retval = y;
octstr_destroy(s);
}
return retval;
}
MmscSettings *mms_load_mmsc_settings(Cfg *cfg, List **proxyrelays)
{
Octstr *s;
List *l;
CfgGroup *grp = cfg_get_single_group(cfg, octstr_imm("mmsbox"));
CfgGroup *cgrp = cfg_get_single_group(cfg, octstr_imm("core"));
MmscSettings *m = gw_malloc(sizeof *m);
long port = -1;
Octstr *from, *user, *pass;
Octstr *qdir = NULL;
int i, n;
memset(m, 0, sizeof *m);
mms_load_core_settings(cgrp);
if (proxyrelays)
*proxyrelays = mms_proxy_relays(cfg);
s = _mms_cfg_getx(grp, octstr_imm("local-mmsc-domains"));
if (s) {
l = octstr_split(s, octstr_imm(","));
octstr_destroy(s);
} else
l = list_create();
m->local_domains = l;
if (cfg_get_integer(&m->maxthreads, grp, octstr_imm("max-send-threads")) == -1)
m->maxthreads = 10;
m->unified_prefix = _mms_cfg_getx(grp, octstr_imm("unified-prefix"));
m->local_prefix = _mms_cfg_getx(grp, octstr_imm("local-prefixes"));
m->hostname = _mms_cfg_getx(grp, octstr_imm("hostname"));
if (m->hostname == NULL || octstr_len(m->hostname) == 0)
m->hostname = octstr_create("localhost");
m->name = _mms_cfg_getx(grp, octstr_imm("name"));
m->host_alias = _mms_cfg_getx(grp, octstr_imm("host-alias"));
m->sendmail = _mms_cfg_getx(grp, octstr_imm("send-mail-prog"));
qdir = _mms_cfg_getx(grp, octstr_imm("storage-directory"));
if (mkdir(octstr_get_cstr(qdir),
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST)
panic(0, "Failed to create queue directory: %s - %s!",
octstr_get_cstr(qdir), strerror(errno));
m->global_queuedir = octstr_format("%S/global", qdir);
m->mm1_queuedir = octstr_format("%S/mm1", qdir);
m->mm4_queuedir = octstr_format("%S/mm4", qdir);
if (mms_init_queuedir(m->mm1_queuedir) < 0)
panic(0, "Failed to initialise local queue directory: %s - %s!",
octstr_get_cstr(m->mm1_queuedir), strerror(errno));
else if (mms_init_queuedir(m->global_queuedir) < 0)
panic(0, "Failed to initialise global queue directory: %s - %s!",
octstr_get_cstr(m->global_queuedir), strerror(errno));
else if (mms_init_queuedir(m->mm4_queuedir) < 0)
panic(0, "Failed to initialise global queue directory: %s - %s!",
octstr_get_cstr(m->mm4_queuedir), strerror(errno));
m->mmbox_rootdir = octstr_format("%S/mmbox", qdir);
if (mmbox_root_init(octstr_get_cstr(m->mmbox_rootdir)) != 0)
panic(0, "Failed to initialise mmbox root directory, error: %s!",
strerror(errno));
m->ua_profile_cache_dir = octstr_format("%S/UserAgent_Profiles", qdir);
if (mkdir(octstr_get_cstr(m->ua_profile_cache_dir),
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST)
panic(0, "Failed to initialise UA Profile directory, error: %s!",
strerror(errno));
if (cfg_get_integer(&m->maxsendattempts, grp, octstr_imm("maximum-send-attempts")) == -1)
m->maxsendattempts = MAXQTRIES;
if (cfg_get_integer(&m->default_msgexpiry, grp, octstr_imm("default-message-expiry")) == -1)
m->default_msgexpiry = DEFAULT_EXPIRE;
s = _mms_cfg_getx(grp, octstr_imm("queue-run-interval"));
if (!s || (m->queue_interval = atof(octstr_get_cstr(s))) <= 0)
m->queue_interval = QUEUERUN_INTERVAL;
if (cfg_get_integer(&m->send_back_off, grp, octstr_imm("send-attempt-back-off")) == -1)
m->send_back_off = BACKOFF_FACTOR;
/* Make send sms url. */
m->sendsms_url = _mms_cfg_getx(grp, octstr_imm("sendsms-url"));
user = _mms_cfg_getx(grp, octstr_imm("sendsms-username"));
pass = _mms_cfg_getx(grp, octstr_imm("sendsms-password"));
from = cfg_get(grp, octstr_imm("sendsms-global-sender"));
if (user && octstr_len(user) > 1)
octstr_url_encode(user);
if (pass && octstr_len(pass) > 1)
octstr_url_encode(pass);
if (from && octstr_len(from) > 1)
octstr_url_encode(from);
octstr_format_append(m->sendsms_url,
(from && octstr_len(from) > 1) ?
"?username=%S&password=%S&from=%S" :
"?username=%S&password=%S",
user,
pass,from);
m->system_user = octstr_format("system-user@%S",
m->hostname);
octstr_destroy(user);
octstr_destroy(pass);
if (from) octstr_destroy(from);
cfg_get_integer(&port, grp, octstr_imm("mms-port"));
m->port = (port > 0) ? port : MMS_PORT;
m->mm7port = -1;
cfg_get_integer(&m->mm7port, grp, octstr_imm("mm7-port"));
m->allow_ip = _mms_cfg_getx(grp, octstr_imm("allow-ip"));
m->deny_ip = _mms_cfg_getx(grp, octstr_imm("deny-ip"));
m->email2mmsrelay_prefixes = _mms_cfg_getx(grp,
octstr_imm("email2mms-relay-prefixes"));
m->prov_notify = _mms_cfg_getx(grp,octstr_imm("prov-server-notify-script"));
m->prov_getstatus = _mms_cfg_getx(grp,octstr_imm("prov-server-sub-status-script"));
m->mms_notify_txt = _mms_cfg_getx(grp, octstr_imm("mms-notify-text"));
m->mms_notify_unprov_txt = _mms_cfg_getx(grp, octstr_imm("mms-notify-unprovisioned-text"));
m->mms_email_txt = _mms_cfg_getx(grp, octstr_imm("mms-to-email-txt"));
m->mms_email_html = _mms_cfg_getx(grp, octstr_imm("mms-to-email-html"));
m->mms_toolarge = _mms_cfg_getx(grp, octstr_imm("mms-message-too-large-txt"));
m->wap_gw_msisdn_header = cfg_get(grp, octstr_imm("mms-client-msisdn-header"));
if (!m->wap_gw_msisdn_header) m->wap_gw_msisdn_header = octstr_imm(XMSISDN_HEADER);
m->wap_gw_ip_header = cfg_get(grp, octstr_imm("mms-client-ip-header"));
if (!m->wap_gw_ip_header) m->wap_gw_ip_header = octstr_imm(XIP_HEADER);
cfg_get_bool(&m->notify_unprovisioned, grp, octstr_imm("notify-unprovisioned"));
m->billing_params = _mms_cfg_getx(grp,
octstr_imm("billing-module-parameters"));
/* Get and load the billing lib if any. */
if ((m->mms_billfuncs = load_module(grp, "billing-library", "mms_billfuncs"))) {
if (m->mms_billfuncs->mms_billingmodule_init == NULL ||
m->mms_billfuncs->mms_billmsg == NULL ||
m->mms_billfuncs->mms_billingmodule_fini == NULL ||
m->mms_billfuncs->mms_logcdr == NULL)
panic(0, "Missing or NULL functions in billing module!");
} else
m->mms_billfuncs = &mms_billfuncs; /* The default one. */
m->mms_bill_module_data = m->mms_billfuncs->mms_billingmodule_init(octstr_get_cstr(m->billing_params));
m->resolver_params = _mms_cfg_getx(grp,
octstr_imm("resolver-module-parameters"));
/* Get and load the resolver lib if any. */
if ((m->mms_resolvefuncs = load_module(grp, "resolver-library", "mms_resolvefuncs"))) {
if (m->mms_resolvefuncs->mms_resolvermodule_init == NULL ||
m->mms_resolvefuncs->mms_resolve == NULL ||
m->mms_resolvefuncs->mms_resolvermodule_fini == NULL)
panic(0, "Missing or NULL functions in resolver module!");
} else
m->mms_resolvefuncs = &mms_resolvefuncs; /* The default one. */
m->mms_resolver_module_data = m->mms_resolvefuncs->mms_resolvermodule_init(octstr_get_cstr(m->resolver_params));
m->detokenizer_params = _mms_cfg_getx(grp, octstr_imm("detokenizer-module-parameters"));
/* Get and load the detokenizer lib if any. */
if ((m->mms_detokenizefuncs = load_module(grp, "detokenizer-library", "mms_detokenizefuncs"))) {
if (m->mms_detokenizefuncs->mms_detokenizer_init == NULL ||
m->mms_detokenizefuncs->mms_detokenize == NULL ||
m->mms_detokenizefuncs->mms_gettoken == NULL ||
m->mms_detokenizefuncs->mms_detokenizer_fini == NULL)
panic(0, "Missing or NULL functions in detokenizer module!");
if (m->mms_detokenizefuncs->mms_detokenizer_init(octstr_get_cstr(m->detokenizer_params)))
panic(0, "Detokenizer module failed to initialize");
} else
m->mms_detokenizefuncs = NULL;
if (cfg_get_bool(&m->allow_ip_type, grp, octstr_imm("allow-ip-type")) < 0)
m->allow_ip_type = 1;
cfg_get_bool(&m->optimize_notification_size, grp, octstr_imm("optimize-notification-size"));
if (cfg_get_bool(&m->content_adaptation, grp, octstr_imm("content-adaptation")) < 0)
m->content_adaptation = 1;
if (qdir)
octstr_destroy(qdir);
/* Now load the VASP list. */
l = cfg_get_multi_group(cfg, octstr_imm("mms-vasp"));
m->vasp_list = list_create();
for (i=0, n=list_len(l); i<n; i++) {
CfgGroup *grp = list_get(l, i);
MmsVasp *mv = gw_malloc(sizeof *mv);
Octstr *s;
mv->id = _mms_cfg_getx(grp, octstr_imm("vasp-id"));
mv->short_code = -1;
cfg_get_integer(&mv->short_code, grp, octstr_imm("short-code"));
mv->vasp_username = _mms_cfg_getx(grp, octstr_imm("vasp-username"));
mv->vasp_password = _mms_cfg_getx(grp, octstr_imm("vasp-password"));
mv->vasp_url = _mms_cfg_getx(grp, octstr_imm("vasp-url"));
mv->mmsc_username = _mms_cfg_getx(grp, octstr_imm("mmsc-username"));
mv->mmsc_password = _mms_cfg_getx(grp, octstr_imm("mmsc-password"));
s = _mms_cfg_getx(grp, octstr_imm("type"));
if (octstr_case_compare(s, octstr_imm("soap")) == 0)
mv->type = SOAP_VASP;
else if (octstr_case_compare(s, octstr_imm("eaif")) == 0)
mv->type = EAIF_VASP;
else
mv->type = NONE_VASP;
octstr_destroy(s);
list_append(m->vasp_list, mv);
}
list_destroy(l, NULL);
return m;
}
List *mms_proxy_relays(Cfg *cfg)
{
List *gl = cfg_get_multi_group(cfg, octstr_imm("mmsproxy"));
int i, n;
List *l = list_create();
for (i = 0, n = list_len(gl); i < n; i++) {
CfgGroup *grp = list_get(gl, i);
MmsProxyRelay *m = gw_malloc(sizeof *m);
m->host = _mms_cfg_getx(grp, octstr_imm("host"));
m->name = _mms_cfg_getx(grp, octstr_imm("name"));
m->allowed_prefix = _mms_cfg_getx(grp, octstr_imm("allowed-prefix"));
m->denied_prefix = _mms_cfg_getx(grp, octstr_imm("denied-prefix"));
list_append(l, m);
}
list_destroy(gl, NULL);
return l;
}
Octstr *mms_makefetchurl(char *qf, Octstr *token, int loc,
Octstr *to,
MmscSettings *settings)
{
Octstr *url = octstr_create("");
Octstr *host_alias = settings->host_alias;
Octstr *hstr;
Octstr *endtoken, *x;
MmsDetokenizerFuncStruct *tfs = settings->mms_detokenizefuncs;
if (host_alias && octstr_len(host_alias) > 0)
hstr = octstr_duplicate(host_alias);
else
hstr = octstr_format("%S:%d",
settings->hostname, settings->port);
octstr_format_append(url, "http://%S/%s@%d",
hstr,
qf, loc);
if (tfs && tfs->mms_gettoken) { /* we append the recipient token or we append the message token. */
endtoken = tfs->mms_gettoken(to);
if (!endtoken)
endtoken = octstr_imm("x");
} else {
if (!token)
endtoken = octstr_imm("x");
else
endtoken = octstr_duplicate(token);
}
x = octstr_duplicate(endtoken); /* might be immutable, so we duplicate it. */
octstr_url_encode(x);
octstr_format_append(url, "/%S", x);
octstr_destroy(endtoken);
octstr_destroy(x);
octstr_destroy(hstr);
return url;
}
Octstr *mms_find_sender_msisdn(Octstr *send_url, List *request_hdrs, Octstr *msisdn_header,
MmsDetokenizerFuncStruct* detokenizerfuncs)
{
/* Either we have a WAP gateway header as defined, or we look for
* last part of url, pass it to detokenizer lib if defined, and back comes our number.
*/
Octstr *phonenum = http_header_value(request_hdrs,
msisdn_header);
if (!phonenum || octstr_len(phonenum) == 0) {
List *l = octstr_split(send_url, octstr_imm("/"));
if (l && list_len(l) > 1) {
if (detokenizerfuncs)
phonenum = detokenizerfuncs->mms_detokenize(list_get(l, list_len(l) - 1));
}
if (l)
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
}
return phonenum;
}