361 lines
12 KiB
C
361 lines
12 KiB
C
/*
|
|
* Mbuni - Open Source MMS Gateway
|
|
*
|
|
* MMSBox CFG: MMBox 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 "mmsbox_cfg.h"
|
|
#include "mms_queue.h"
|
|
|
|
List *sendmms_users = NULL; /* list of SendMmsUser structs */
|
|
List *mms_services = NULL; /* list of MMS Services */
|
|
List *mmscs = NULL;
|
|
Octstr *incoming_qdir, *outgoing_qdir, *dlr_dir;
|
|
long mmsbox_maxsendattempts, mmsbox_send_back_off;
|
|
long maxthreads = 0;
|
|
double queue_interval = -1;
|
|
Octstr *unified_prefix;
|
|
|
|
struct SendMmsPortInfo sendmms_port;
|
|
|
|
int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
|
|
{
|
|
mCfgGrp *grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
|
|
mCfgGrp *cgrp = mms_cfg_get_single(cfg, octstr_imm("core"));
|
|
Octstr *gdir, *s;
|
|
int send_port_ssl = 0;
|
|
List *l;
|
|
int i, n;
|
|
void *catchall = NULL;
|
|
|
|
if (grp == NULL)
|
|
panic(0,"Missing required group `mbuni' in config file!");
|
|
|
|
mms_load_core_settings(cgrp);
|
|
|
|
sendmms_users = gwlist_create();
|
|
mms_services = gwlist_create();
|
|
mmscs = gwlist_create();
|
|
|
|
gdir = mms_cfg_get(grp, octstr_imm("storage-directory"));
|
|
|
|
if (gdir == NULL)
|
|
gdir = octstr_imm(".");
|
|
|
|
if (mkdir(octstr_get_cstr(gdir),
|
|
S_IRWXU|S_IRWXG) < 0 &&
|
|
errno != EEXIST)
|
|
panic(0, "Failed to create MMSBox storage directory: %s - %s!",
|
|
octstr_get_cstr(gdir), strerror(errno));
|
|
|
|
incoming_qdir = octstr_format("%S/mmsbox_incoming", gdir);
|
|
outgoing_qdir = octstr_format("%S/mmsbox_outgoing", gdir);
|
|
dlr_dir = octstr_format("%S/mmsbox_dlr", gdir);
|
|
|
|
if (mms_init_queuedir(incoming_qdir) < 0)
|
|
panic(0, "Failed to initialise incoming queue directory: %s - %s!",
|
|
octstr_get_cstr(incoming_qdir), strerror(errno));
|
|
|
|
if (mms_init_queuedir(outgoing_qdir) < 0)
|
|
panic(0, "Failed to initialise outgoing queue directory: %s - %s!",
|
|
octstr_get_cstr(outgoing_qdir), strerror(errno));
|
|
|
|
if (mms_init_queuedir(dlr_dir) < 0)
|
|
panic(0, "Failed to initialise dlr storage directory: %s - %s!",
|
|
octstr_get_cstr(dlr_dir), strerror(errno));
|
|
|
|
if (mms_cfg_get_int(grp,
|
|
octstr_imm("maximum-send-attempts"), &mmsbox_maxsendattempts) < 0)
|
|
mmsbox_maxsendattempts = MAXQTRIES;
|
|
|
|
if (mms_cfg_get_int(grp,
|
|
octstr_imm("send-attempt-back-off"), &mmsbox_send_back_off) == -1)
|
|
mmsbox_send_back_off = BACKOFF_FACTOR;
|
|
|
|
|
|
if (mms_cfg_get_int(grp, octstr_imm("max-send-threads"), &maxthreads) == -1)
|
|
maxthreads = 10;
|
|
|
|
s = mms_cfg_get(grp, octstr_imm("queue-run-interval"));
|
|
if (s) {
|
|
queue_interval = atof(octstr_get_cstr(s));
|
|
octstr_destroy(s);
|
|
}
|
|
if (queue_interval <= 0)
|
|
queue_interval = QUEUERUN_INTERVAL;
|
|
|
|
|
|
|
|
// unified_prefix = _mms_cfg_getx(grp, octstr_imm("unified-prefix"));
|
|
|
|
mms_cfg_get_int(grp, octstr_imm("sendmms-port"), &sendmms_port.port);
|
|
#ifdef HAVE_LIBSSL
|
|
mms_cfg_get_bool(grp, octstr_imm("sendmms-port-ssl"), &send_port_ssl);
|
|
#endif
|
|
if (http_open_port(sendmms_port.port, send_port_ssl) < 0)
|
|
error(0, "MMSBox: Failed to start sendmms HTTP server on %ld: %s!",
|
|
sendmms_port.port,
|
|
strerror(errno));
|
|
|
|
sendmms_port.allow_ip = mms_cfg_get(grp, octstr_imm("allow-ip"));
|
|
sendmms_port.deny_ip = mms_cfg_get(grp, octstr_imm("deny-ip"));
|
|
|
|
/* Now get sendmms users. */
|
|
|
|
l = mms_cfg_get_multi(cfg, octstr_imm("send-mms-user"));
|
|
for (i = 0, n = gwlist_len(l); i < n; i++) {
|
|
mCfgGrp *x = gwlist_get(l, i);
|
|
SendMmsUser *u = gw_malloc(sizeof *u);
|
|
|
|
memset(u, 0, sizeof *u);
|
|
|
|
u->user = _mms_cfg_getx(x, octstr_imm("username"));
|
|
u->pass = _mms_cfg_getx(x, octstr_imm("password"));
|
|
u->faked_sender = mms_cfg_get(x, octstr_imm("faked-sender"));
|
|
u->dlr_url = _mms_cfg_getx(x, octstr_imm("delivery-report-url"));
|
|
u->rr_url = _mms_cfg_getx(x, octstr_imm("read-report-url"));
|
|
gwlist_append(sendmms_users, u);
|
|
}
|
|
gwlist_destroy(l, NULL);
|
|
|
|
/* Get mmsc list. */
|
|
l = mms_cfg_get_multi(cfg, octstr_imm("mmsc"));
|
|
for (i = 0, n = gwlist_len(l); i < n; i++) {
|
|
mCfgGrp *x = gwlist_get(l, i);
|
|
MmscGrp *m = gw_malloc(sizeof *m);
|
|
int ssl = 0;
|
|
Octstr *type;
|
|
Octstr *xver;
|
|
|
|
memset(m, 0, sizeof *m);
|
|
|
|
m->id = _mms_cfg_getx(x, octstr_imm("id"));
|
|
if (octstr_len(m->id) < 1)
|
|
panic(0,"Missing required value `id' in config file!");
|
|
m->group_id = _mms_cfg_getx(x, octstr_imm("group-id"));
|
|
if (octstr_len(m->group_id) < 1)
|
|
m->group_id = octstr_duplicate(m->id);
|
|
|
|
m->mmsc_url = _mms_cfg_getx(x, octstr_imm("mmsc-url"));
|
|
|
|
m->allowed_prefix = mms_cfg_get(x, octstr_imm("allowed-prefix"));
|
|
m->denied_prefix = mms_cfg_get(x, octstr_imm("denied-prefix"));
|
|
|
|
m->incoming.allow_ip = mms_cfg_get(x, octstr_imm("allow-ip"));
|
|
m->incoming.deny_ip = mms_cfg_get(x, octstr_imm("deny-ip"));
|
|
|
|
info(0, "MMSC[%s], allow=[%s], deny=[%s] group_id=[%s]",
|
|
octstr_get_cstr(m->id),
|
|
octstr_get_cstr(m->incoming.allow_ip),
|
|
octstr_get_cstr(m->incoming.deny_ip),
|
|
octstr_get_cstr(m->group_id));
|
|
|
|
m->incoming.user = _mms_cfg_getx(x, octstr_imm("incoming-username"));
|
|
m->incoming.pass = _mms_cfg_getx(x, octstr_imm("incoming-password"));
|
|
mms_cfg_get_int(x, octstr_imm("incoming-port"), &m->incoming.port);
|
|
#ifdef HAVE_LIBSSL
|
|
mms_cfg_get_bool(x, octstr_imm("incoming-port-ssl"), &ssl);
|
|
#endif
|
|
mms_cfg_get_int(x, octstr_imm("max-throughput"), &m->throughput);
|
|
|
|
type = _mms_cfg_getx(x, octstr_imm("type"));
|
|
if (octstr_case_compare(type, octstr_imm("eaif")) == 0)
|
|
m->type = EAIF_MMSC;
|
|
else if (octstr_case_compare(type, octstr_imm("soap")) == 0)
|
|
m->type = SOAP_MMSC;
|
|
else
|
|
warning(0, "MMSBox: Unknown MMSC type [%s]!",
|
|
octstr_get_cstr(type));
|
|
if ((xver = _mms_cfg_getx(x, octstr_imm("mm7-version"))) != NULL &&
|
|
octstr_len(xver) > 0)
|
|
sscanf(octstr_get_cstr(xver),
|
|
"%d.%d.%d",
|
|
&m->ver.major, &m->ver.minor1, &m->ver.minor2);
|
|
else { /* Put in some defaults. */
|
|
if (m->type == SOAP_MMSC) {
|
|
m->ver.major = 5;
|
|
m->ver.minor1 = 1;
|
|
m->ver.minor2 = 2;
|
|
} else if (m->type == EAIF_MMSC) {
|
|
m->ver.major = 3;
|
|
m->ver.minor1 = 0;
|
|
}
|
|
}
|
|
|
|
octstr_destroy(xver);
|
|
octstr_destroy(type);
|
|
|
|
if (m->incoming.port > 0 &&
|
|
http_open_port(m->incoming.port, ssl) < 0) {
|
|
warning(0, "MMSBox: Failed to start HTTP server on receive port for "
|
|
" MMSC %s, port %ld: %s!",
|
|
octstr_get_cstr(m->id), m->incoming.port,
|
|
strerror(errno));
|
|
m->incoming.port = 0; /* so we don't listen on it. */
|
|
}
|
|
|
|
if (mmsc_handler_func && m->incoming.port > 0) { /* Only start threads if func passed and ... */
|
|
if ((m->threadid = gwthread_create(mmsc_handler_func, m)) < 0)
|
|
error(0, "MMSBox: Failed to start MMSC handler thread for MMSC[%s]: %s!",
|
|
octstr_get_cstr(m->id), strerror(errno));
|
|
} else
|
|
m->threadid = -1;
|
|
|
|
m->mutex = mutex_create();
|
|
gwlist_append(mmscs, m);
|
|
}
|
|
gwlist_destroy(l, NULL);
|
|
|
|
|
|
l = mms_cfg_get_multi(cfg, octstr_imm("mms-service"));
|
|
for (i = 0, n = gwlist_len(l); i < n; i++) {
|
|
mCfgGrp *x = gwlist_get(l, i);
|
|
MmsService *m = gw_malloc(sizeof *m);
|
|
Octstr *s;
|
|
|
|
m->name = _mms_cfg_getx(x, octstr_imm("name"));
|
|
if ((m->url = mms_cfg_get(x, octstr_imm("get-url"))) != NULL)
|
|
m->type = TRANS_TYPE_GET_URL;
|
|
else if ((m->url = mms_cfg_get(x, octstr_imm("post-url"))) != NULL)
|
|
m->type = TRANS_TYPE_POST_URL;
|
|
else if ((m->url = mms_cfg_get(x, octstr_imm("file"))) != NULL)
|
|
m->type = TRANS_TYPE_FILE;
|
|
else if ((m->url = mms_cfg_get(x, octstr_imm("exec"))) != NULL)
|
|
m->type = TRANS_TYPE_EXEC;
|
|
else if ((m->url = mms_cfg_get(x, octstr_imm("text"))) != NULL)
|
|
m->type = TRANS_TYPE_TEXT;
|
|
else
|
|
panic(0, "MMSBox: Service [%s] has no url!", octstr_get_cstr(m->name));
|
|
|
|
m->faked_sender = mms_cfg_get(x, octstr_imm("faked-sender"));
|
|
mms_cfg_get_bool(x, octstr_imm("catch-all"), &m->isdefault);
|
|
|
|
if (m->isdefault) {
|
|
if (catchall)
|
|
warning(0, "MMSBox: Multiple default mms services defined!");
|
|
catchall = m;
|
|
}
|
|
|
|
if (mms_cfg_get_bool(x, octstr_imm("omit-empty"), &m->omitempty) < 0)
|
|
m->omitempty = 0;
|
|
if (mms_cfg_get_bool(x, octstr_imm("suppress-reply"), &m->noreply) < 0)
|
|
m->noreply = 0;
|
|
mms_cfg_get_bool(x, octstr_imm("accept-x-mbuni-headers"), &m->accept_x_headers);
|
|
|
|
if ((s = mms_cfg_get(x, octstr_imm("pass-thro-headers"))) != NULL) {
|
|
m->passthro_headers = octstr_split(s, octstr_imm(","));
|
|
octstr_destroy(s);
|
|
} else
|
|
m->passthro_headers = NULL;
|
|
|
|
mms_cfg_get_bool(x, octstr_imm("assume-plain-text"), &m->assume_plain_text);
|
|
|
|
if ((s = mms_cfg_get(x, octstr_imm("accepted-mmscs"))) != NULL) {
|
|
m->allowed_mmscs = octstr_split(s, octstr_imm(";"));
|
|
octstr_destroy(s);
|
|
} else
|
|
m->allowed_mmscs = NULL; /* means allow all. */
|
|
|
|
if ((s = mms_cfg_get(x, octstr_imm("denied-mmscs"))) != NULL) {
|
|
m->denied_mmscs = octstr_split(s, octstr_imm(";"));
|
|
octstr_destroy(s);
|
|
} else
|
|
m->denied_mmscs = NULL; /* means allow all. */
|
|
|
|
/* Get key words. Start with aliases to make life easier. */
|
|
if ((s = mms_cfg_get(x, octstr_imm("aliases"))) != NULL) {
|
|
m->keywords = octstr_split(s, octstr_imm(";"));
|
|
octstr_destroy(s);
|
|
} else
|
|
m->keywords = gwlist_create();
|
|
|
|
s = mms_cfg_get(x, octstr_imm("keyword"));
|
|
if (!s)
|
|
panic(0, "MMSBox: Service [%s] has no keyword!", octstr_get_cstr(m->name));
|
|
else
|
|
gwlist_append(m->keywords, s);
|
|
|
|
if ((s = mms_cfg_get(x, octstr_imm("http-post-parameters"))) != NULL) {
|
|
List *r = octstr_split(s, octstr_imm("&"));
|
|
int i, n;
|
|
m->params = gwlist_create();
|
|
if (m->type != TRANS_TYPE_POST_URL)
|
|
warning(0, "MMSBox: Service [%s] specifies HTTP Post parameters "
|
|
"without specifying post-url type/url!", octstr_get_cstr(m->name));
|
|
for (i = 0, n = gwlist_len(r); i < n; i++) {
|
|
Octstr *y = gwlist_get(r, i);
|
|
int ii = octstr_search_char(y, '=', 0);
|
|
if (ii < 0)
|
|
ii = octstr_len(y);
|
|
|
|
if (ii > 0) {
|
|
MmsServiceUrlParam *p = gw_malloc(sizeof *p);
|
|
int ch;
|
|
p->name = octstr_copy(y, 0, ii);
|
|
p->value = NULL;
|
|
|
|
if (octstr_get_char(y, ii+1) == '%') {
|
|
switch(ch = octstr_get_char(y, ii+2)) {
|
|
case 'a':
|
|
p->type = AUDIO_PART; break;
|
|
case 'b':
|
|
p->type = WHOLE_BINARY; break;
|
|
case 'i':
|
|
p->type = IMAGE_PART; break;
|
|
case 'v':
|
|
p->type = VIDEO_PART; break;
|
|
case 't':
|
|
p->type = TEXT_PART; break;
|
|
case 's':
|
|
p->type = SMIL_PART; break;
|
|
case 'o':
|
|
p->type = OTHER_PART; break;
|
|
case 'z':
|
|
p->type = ANY_PART; break;
|
|
case '%':
|
|
p->type = NO_PART; break;
|
|
default:
|
|
warning(0, "MMSBox: Unknown conversion character %c "
|
|
"in http-post-parameters. Service [%s]!",
|
|
ch, octstr_get_cstr(m->name));
|
|
p->type = NO_PART;
|
|
break;
|
|
}
|
|
p->value = octstr_copy(y, ii+3, octstr_len(y));
|
|
} else /* No conversion spec. */
|
|
p->value = octstr_copy(y, ii+1, octstr_len(y));
|
|
gwlist_append(m->params, p);
|
|
} else
|
|
warning(0, "MMSBox: Missing http-post-parameter name? Service [%s]!",
|
|
octstr_get_cstr(m->name));
|
|
}
|
|
gwlist_destroy(r, (gwlist_item_destructor_t *)octstr_destroy);
|
|
octstr_destroy(s);
|
|
} else
|
|
m->params = NULL;
|
|
|
|
m->service_code = mms_cfg_get(x, octstr_imm("service-code"));
|
|
|
|
gwlist_append(mms_services, m);
|
|
}
|
|
gwlist_destroy(l, NULL);
|
|
|
|
return 0;
|
|
}
|