1
0
Fork 0

mmsc admin interface

This commit is contained in:
bagyenda 2008-09-08 11:50:24 +00:00
parent f55d24567f
commit 5afec26e5d
13 changed files with 712 additions and 233 deletions

View File

@ -1,3 +1,6 @@
2008-09-08 P. A. Bagyenda <bagyenda@dsmagic.com>
* MMSC admin interface added (start/stop/status of each VASP connection)
* MMSC VASP can now have multiple short codes
2008-09-04 P. A. Bagyenda <bagyenda@dsmagic.com>
* Minor fix/addition for Content-ID handling
* Generalised event logger module (to facilitate alarms, etc)

View File

@ -131,13 +131,14 @@ MULTI_GROUP(mms-vasp,
OCTSTR(mm7-soap-xmlns)
OCTSTR(use-mm7-soap-namespace-prefix)
OCTSTR(short-code)
OCTSTR(short-codes)
OCTSTR(vasp-username)
OCTSTR(vasp-password)
OCTSTR(vasp-url)
OCTSTR(mms-to-email-handler)
OCTSTR(mms-to-local-copy-handler)
OCTSTR(send-uaprof)
OCTSTR(throughput)
)
MULTI_GROUP(send-mms-user,

View File

@ -40,6 +40,9 @@
#define MMS_SEND_ERROR_TRANSIENT -1
#define MMS_SEND_ERROR_FATAL -2
/* Aging of old (internal) records... */
#define DEFAULT_DELETE_AGE 10*60
#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : \
(e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : \
((e) == MMS_SEND_QUEUED ? "Queued" : "Failed"))

View File

@ -42,14 +42,14 @@
static int auth_check(Octstr *user, Octstr *pass, List *headers)
static int auth_check(Octstr *user, Octstr *pass, List *headers, int *has_auth_hdr)
{
int i, res = -1;
Octstr *v = http_header_value(headers, octstr_imm("Authorization"));
Octstr *p = NULL, *q = NULL;
if (user == NULL ||
octstr_len(user) == 0) {
*has_auth_hdr = (v != NULL);
if (octstr_len(user) == 0) {
res = 0;
goto done;
}
@ -563,19 +563,23 @@ static void dispatch_mm7_recv(List *rl)
MmsBoxHTTPClientInfo *h;
while ((h = gwlist_consume(rl)) != NULL) {
int ret = -1;
int ret = -1, has_auth = 0;
MmscGrp *m = h->m;
if (auth_check(m->incoming.user,
m->incoming.pass,
h->headers) != 0) { /* Ask it to authenticate... */
h->headers, &has_auth) != 0) { /* Ask it to authenticate... */
List *hh = http_create_empty_headers();
http_header_add(hh, "WWW-Authenticate",
"Basic realm=\"" MM_NAME "\"");
http_send_reply(h->client, HTTP_UNAUTHORIZED, hh,
octstr_imm("Authentication failed"));
http_destroy_headers(hh);
mms_info(0, "MM7", m->id, "Auth failed, incoming connection, MMC group=[%s]",
m->id ? octstr_get_cstr(m->id) : "(none)");
if (!has_auth)
mms_info_ex("auth",0, "MM7", m->id, "Auth failed, incoming connection, MMC group=[%s]",
m->id ? octstr_get_cstr(m->id) : "(none)");
else
mms_error_ex("auth",0, "MM7", m->id, "Auth failed, incoming connection, MMC group=[%s]",
m->id ? octstr_get_cstr(m->id) : "(none)");
} else if (h->m->type == SOAP_MMSC)
ret = mm7soap_receive(h);
else
@ -632,7 +636,7 @@ void mmsc_receive_func(MmscGrp *m)
} else {
h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
mms_error(0, "MM7", m->id, "HTTP: Incoming IP denied MMSC[%s] ip=[%s], ua=[%s], disconnected",
mms_error_ex("auth",0, "MM7", m->id, "HTTP: Incoming IP denied MMSC[%s] ip=[%s], ua=[%s], disconnected",
m->id ? octstr_get_cstr(m->id) : "(none)",
h.ip ? octstr_get_cstr(h.ip) : "(none)",
h.ua ? octstr_get_cstr(h.ua) : "(none)");
@ -894,7 +898,7 @@ static int mms_sendtommsc(MmscGrp *mmc, Octstr *from, Octstr *to, Octstr *transi
from, to, transid, linkedid, vasid,
service_code, m, hdrs, err, &retry);
else
mms_error(0, "MM7", mmc->id, "MMC[%s] of unknown type, can't send!",
mms_error_ex("MT", 0, "MM7", mmc->id, "MMC[%s] of unknown type, can't send!",
mmc->id ? octstr_get_cstr(mmc->id) : "");
throughput = mmc->throughput;
@ -1023,11 +1027,17 @@ static int sendMsg(MmsEnvelope *e)
if (res == MMS_SEND_ERROR_FATAL)
to->process = 0; /* No more attempts. */
mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s], err=%s",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
new_msgid ? octstr_get_cstr(new_msgid) : NULL,
err ? octstr_get_cstr(err) : "(none)");
if (err == NULL)
mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s]",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
new_msgid ? octstr_get_cstr(new_msgid) : NULL);
else
mms_error_ex("MT", 0,
"MM7", NULL,
"%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize);
octstr_destroy(new_msgid);
octstr_destroy(err);

View File

@ -1201,7 +1201,8 @@ static void dispatch_sendmms_recv(List *rl)
Octstr *password;
Octstr *err = NULL;
List *cgivar_ctypes = NULL;
char *etype = NULL;
int res = 0, tparse = parse_cgivars(h->headers, h->body, &h->cgivars, &cgivar_ctypes);
username = http_cgi_variable(h->cgivars, "username");
@ -1380,10 +1381,11 @@ static void dispatch_sendmms_recv(List *rl)
"username=%s, password=%s!",
username ? octstr_get_cstr(username) : "(null)",
password ? octstr_get_cstr(password) : "(null)");
etype = "auth";
}
if (err && res != 0)
mms_error(0, "mmsbox", NULL, "%s", octstr_get_cstr(err));
mms_error_ex(etype, 0, "mmsbox", NULL, "%s", octstr_get_cstr(err));
octstr_destroy(err);
/* Free the ip and other stuff here. */

View File

@ -628,6 +628,26 @@ MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handl
return m;
}
static void delete_stale_mmsc(int delete_all)
{
MmscGrp *mmc;
int n = gwlist_len(mmsc_del_list);
while (n-- > 0 &&
(mmc = gwlist_extract_first(mmsc_del_list)) != NULL)
if (delete_all ||
(mmc->use_count <= 0 &&
mmc->delete_after <= time(NULL)))
free_mmsc_struct(mmc);
else
gwlist_append(mmsc_del_list, mmc); /* put it back. */
if (delete_all) {
gwlist_destroy(mmsc_del_list, NULL);
mmsc_del_list = NULL;
}
}
int mmsbox_stop_mmsc_conn(Octstr *mmc_id)
{
MmscGrp *mmc = dict_remove(mmscs, mmc_id); /* remove it so no one else can get it. */
@ -637,9 +657,10 @@ int mmsbox_stop_mmsc_conn(Octstr *mmc_id)
mmsbox_stop_mmsc_conn_real(mmc);
mmc->delete_after = time(NULL) + 5*60; /* delete after 5 minutes. */
mmc->delete_after = time(NULL) + DEFAULT_DELETE_AGE; /* delete after X minutes. */
gwlist_append(mmsc_del_list, mmc); /* to be deleted later. */
delete_stale_mmsc(0); /* Also delete stale ones on each stop. */
return 0;
}
@ -727,25 +748,6 @@ done:
}
static void delete_stale_mmsc(int delete_all)
{
MmscGrp *mmc;
int n = gwlist_len(mmsc_del_list);
while (n-- > 0 &&
(mmc = gwlist_extract_first(mmsc_del_list)) != NULL)
if (delete_all ||
(mmc->use_count <= 0 &&
mmc->delete_after <= time(NULL)))
free_mmsc_struct(mmc);
else
gwlist_append(mmsc_del_list, mmc); /* put it back. */
if (delete_all) {
gwlist_destroy(mmsc_del_list, NULL);
mmsc_del_list = NULL;
}
}
void mmsbox_settings_cleanup(void)
{
@ -891,18 +893,18 @@ static void append_mmsc_status(Octstr *rbody, MmscGrp *m, List *warnings)
sprintf(xport, "%d", (int)m->incoming.port);
else
sprintf(xport, "n/a");
octstr_format_append(rbody, "<Mmsc id=\"%S\" type=\"%s\">\n "
"<Port>%s</Port>\n"
"<Group>%S</Group>\n"
"<Throughput>%.4f</Throughput>\n"
"<Reroute>%s</Reroute>\n"
"<Reroute-MMSC-ID>%S</Reroute-MMSC-ID>\n"
"<Stats>\n"
"<Uptime>%s</Uptime>\n"
"<LastPDU>%s</LastPDU>\n"
"<MT><PDUS>%ld</PDUS><ERRORS>%ld</ERRORS></MT>\n"
"<MO><PDUS>%ld</PDUS><ERRORS>%ld</ERRORS></MO>\n"
"</Stats>\n",
octstr_format_append(rbody, "<mmsc id=\"%S\" type=\"%s\">\n "
"<port>%s</port>\n"
"<group>%S</group>\n"
"<throughput>%.4f</throughput>\n"
"<re-route>%s</re-route>\n"
"<reroute-mmsc>%S</reroute-mmsc>\n"
"<stats>\n"
"<uptime>%s</uptime>\n"
"<last-pdu>%s</last-pdu>\n"
"<mt><pdus>%ld</pdus><errors>%ld</errors></mt>\n"
"<mt><pdus>%ld</pdu><errors>%ld</errors></mo>\n"
"</stats>\n",
m->id,
typ,
xport,
@ -917,9 +919,9 @@ static void append_mmsc_status(Octstr *rbody, MmscGrp *m, List *warnings)
for (i = 0, n = gwlist_len(warnings); i<n; i++)
octstr_format_append(rbody, "<Warning>%S</Warning>\n", gwlist_get(warnings, i));
octstr_format_append(rbody, "<warning>%S</warning>\n", gwlist_get(warnings, i));
octstr_append_cstr(rbody, "</Mmsc>\n");
octstr_append_cstr(rbody, "</mmsc>\n");
}
static void admin_handler(void *unused)
@ -931,7 +933,6 @@ static void admin_handler(void *unused)
Octstr *body;
List *cgivars;
Octstr *pass;
Octstr *cmd;
mms_info(0, "mmsbox", NULL,"Admin Interface -- startup on port %d", (int)admin_port);
@ -953,19 +954,16 @@ static void admin_handler(void *unused)
rstatus = HTTP_UNAUTHORIZED;
rbody = octstr_imm("Auth failed");
}
} else if ((cmd = http_cgi_variable(cgivars, "command")) == NULL) {
rbody = octstr_imm("Missing Command Parameter");
rstatus = HTTP_BAD_REQUEST;
} else {
Octstr *mmc_id = http_cgi_variable(cgivars, "mmsc-id");
List *l = NULL;
rbody = octstr_create("<?xml version='1.0'?>\n");
/* Command is one of: status, start, stop.
/* URI is one of: /status, /start, /stop.
* mmsc-id is either empty (meaning ALL) or an ID of an existing MMSC connection.
*/
if (octstr_str_case_compare(cmd, "start") == 0) {
if (octstr_str_case_compare(url, "/start") == 0) {
mCfgGrp *m;
if (mmc_id == NULL)
l = mms_cfg_get_multi(cfg, octstr_imm("mmsc"));
@ -997,7 +995,7 @@ static void admin_handler(void *unused)
gwlist_destroy(w, (void *)octstr_destroy);
}
} else if (octstr_str_case_compare(cmd, "stop") == 0) {
} else if (octstr_str_case_compare(url, "/stop") == 0) {
Octstr *x;
if (mmc_id == NULL)
l = dict_keys(mmscs);
@ -1014,7 +1012,7 @@ static void admin_handler(void *unused)
octstr_destroy(x);
}
} else if (octstr_str_case_compare(cmd, "status") == 0) {
} else if (octstr_str_case_compare(url, "/status") == 0) {
Octstr *x;
MmscGrp *mc;
if (mmc_id == NULL)

View File

@ -14,11 +14,9 @@
#include "mmsc.h"
#include "mms_uaprof.h"
static mCfg *cfg;
MmscSettings *settings;
List *proxyrelays;
static void quit_now(int notused)
{
stop_mmsrelay();
@ -51,21 +49,14 @@ int main(int argc, char *argv[])
else
fname = octstr_create(argv[cfidx]);
cfg = mms_cfg_read(fname);
if (cfg == NULL)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
octstr_destroy(fname);
mms_info(0, "mmsc", NULL, "----------------------------------------");
mms_info(0, "mmsc", NULL," " MM_NAME " MMSC version %s starting", MMSC_VERSION);
settings = mms_load_mmsc_settings(cfg,&proxyrelays);
settings = mms_load_mmsc_settings(fname,&proxyrelays);
mms_cfg_destroy(cfg);
octstr_destroy(fname);
if (!settings)
panic(0, "No MMSC configuration!");

View File

@ -26,35 +26,61 @@
#define MMS_PORT 8191 /* Default content fetch port. */
static void free_vasp(MmsVasp *m);
static void delete_stale_vasps(MmscSettings *settings, int delete_all);
static void admin_handler(MmscSettings *settings);
void mms_cleanup_mmsc_settings(MmscSettings *settings)
{
/* eventually we will destroy the object. For now, we only cleanup queue module. */
settings->qfs->mms_cleanup_queue_module();
/* eventually we will destroy the object. */
if (settings->admin_port > 0) {
http_close_port(settings->admin_port);
if (settings->admin_thread >= 0)
gwthread_join(settings->admin_thread);
mms_info(0, "mmsc", NULL,"Admin port on %d, shutdown", (int)settings->admin_port);
}
settings->qfs->mms_cleanup_queue_module();
delete_stale_vasps(settings, 1);
mms_event_logger_cleanup();
}
MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays)
MmscSettings *mms_load_mmsc_settings(Octstr *fname, List **proxyrelays)
{
mCfg *cfg;
Octstr *s;
List *l;
mCfgGrp *grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
mCfgGrp *cgrp = mms_cfg_get_single(cfg, octstr_imm("core"));
MmscSettings *m = gw_malloc(sizeof *m);
mCfgGrp *grp;
mCfgGrp *cgrp;
MmscSettings *m;
long port = -1;
Octstr *from, *user, *pass;
Octstr *qdir = NULL;
int i, n, xx = 0;
int i, n, xx = 0, ssl = 0;
void *x;
cfg = mms_cfg_read(fname);
if (cfg == NULL)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
cgrp = mms_cfg_get_single(cfg, octstr_imm("core"));
grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
m = gw_malloc(sizeof *m);
memset(m, 0, sizeof *m);
if (grp == NULL)
panic(0,"Missing required group `mbuni' in config file!");
m->cfg = cfg; /* store it since admin thread needs it. */
m->vasp_del_list = gwlist_create();
mms_load_core_settings(cfg, cgrp);
if ((x = _mms_load_module(cfg, grp, "event-logger-module", "event_logger", NULL)) != NULL) {
@ -278,91 +304,208 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays)
/* Now load the VASP list. */
l = mms_cfg_get_multi(cfg, octstr_imm("mms-vasp"));
m->vasp_list = gwlist_create();
for (i=0, n=gwlist_len(l); i<n; i++) {
mCfgGrp *grp = gwlist_get(l, i);
MmsVasp *mv = gw_malloc(sizeof *mv);
Octstr *s;
int ibool = 0;
mv->id = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-id"));
mv->short_code = -1;
mms_cfg_get_int(cfg, grp, octstr_imm("short-code"), &mv->short_code);
m->vasp_list = dict_create(53, NULL);
for (i=0, n=gwlist_len(l); i<n; i++) {
List *e = gwlist_create();
List *w = gwlist_create();
Octstr *x;
mv->vasp_username = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-username"));
mv->vasp_password = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-password"));
mv->vasp_url = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-url"));
s = _mms_cfg_getx(cfg, grp, octstr_imm("type"));
mmsc_load_vasp_from_conf(m, gwlist_get(l, i), e, w);
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);
mv->ver.major = mv->ver.minor1 = mv->ver.minor2 = 0;
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mm7-version"))) != NULL &&
octstr_len(s) > 0)
sscanf(octstr_get_cstr(s), "%d.%d.%d", &mv->ver.major, &mv->ver.minor1, &mv->ver.minor2);
else {
if (mv->type == SOAP_VASP) {
mv->ver.major = MAJOR_VERSION(DEFAULT_MM7_VERSION);
mv->ver.minor1 = MINOR1_VERSION(DEFAULT_MM7_VERSION);
mv->ver.minor2 = MINOR2_VERSION(DEFAULT_MM7_VERSION);
} else if (mv->type == EAIF_VASP) {
mv->ver.major = 3;
mv->ver.minor1 = 0;
}
while ((x = gwlist_extract_first(e)) != NULL) {
mms_error(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
octstr_destroy(x);
}
octstr_destroy(s);
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mm7-soap-xmlns"))) != NULL) {
strncpy(mv->ver.xmlns, octstr_get_cstr(s), sizeof mv->ver.xmlns);
mv->ver.xmlns[-1 + sizeof mv->ver.xmlns] = 0; /* NULL terminate, just in case. */
octstr_destroy(s);
} else
mv->ver.xmlns[0] = 0;
mv->ver.use_mm7_namespace = 1;
mms_cfg_get_bool(cfg, grp, octstr_imm("use-mm7-soap-namespace-prefix"), &mv->ver.use_mm7_namespace);
/* Set the handler vasp accounts. */
if (mms_cfg_get_bool(cfg, grp, octstr_imm("mms-to-email-handler"), &ibool) == 0 &&
ibool) {
if (m->mms2email)
mms_warning(0, "mmsc", NULL,"mms-to-email handler VASP specified more than once! Only last config taken.");
m->mms2email = mv;
}
if (mms_cfg_get_bool(cfg, grp, octstr_imm("mms-to-local-copy-handler"), &ibool) == 0 &&
ibool) {
if (m->mms2mobile)
mms_warning(0, "mmsc", NULL,"mms-to-mobile copy handler VASP specified more than once! Only last config taken.");
m->mms2mobile = mv;
while ((x = gwlist_extract_first(w)) != NULL) {
mms_warning(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
octstr_destroy(x);
}
if ((s = mms_cfg_get(cfg, grp, octstr_imm("send-uaprof"))) != NULL){
if (octstr_str_case_compare(s, "url") == 0)
mv->send_uaprof = UAProf_URL;
else if (octstr_str_case_compare(s, "ua") == 0)
mv->send_uaprof = UAProf_UA;
else {
mms_warning(0, "mmsc", NULL,"unknown send-uaprof value '%s'. Must be \"ua\" or \"url\"!",
octstr_get_cstr(s));
mv->send_uaprof = UAProf_None;
}
octstr_destroy(s);
}
gwlist_append(m->vasp_list, mv);
gwlist_destroy(e, NULL);
gwlist_destroy(w, NULL);
}
gwlist_destroy(l, NULL);
/* Now load & start admin interface. */
mms_cfg_get_int(cfg, grp, octstr_imm("mmsc-admin-port"), &m->admin_port);
#ifdef HAVE_LIBSSL
mms_cfg_get_bool(cfg, grp, octstr_imm("admin-port-ssl"), &ssl);
#endif
m->admin_pass = mms_cfg_get(cfg, grp, octstr_imm("admin-password"));
m->admin_allow_ip = mms_cfg_get(cfg, grp, octstr_imm("admin-allow-ip"));
m->admin_deny_ip = mms_cfg_get(cfg, grp, octstr_imm("admin-deny-ip"));
if (m->admin_port > 0 &&
http_open_port(m->admin_port, ssl)< 0) {
mms_error(0, "mmsc", NULL, "Failed to start admin server on port %d: %s",
(int)m->admin_port, strerror(errno));
m->admin_port = -1;
} else if (m->admin_port > 0 &&
(m->admin_thread = gwthread_create((gwthread_func_t *)admin_handler, m)) < 0) {
mms_error(0, "mmsc", NULL, "Failed to start admin server thread: %s",
strerror(errno));
http_close_port(m->admin_port);
m->admin_port = -1;
} else if (m->admin_pass == NULL)
mms_warning(0, "mmsc", NULL, "Empty or no password supplied for admin port. All requests will be allowed!");
return m;
}
int mmsc_unload_vasp(MmscSettings *m, Octstr *id)
{
MmsVasp *mv = dict_remove(m->vasp_list, id);
if (mv == NULL)
return -1;
if (m->mms2email == mv)
m->mms2email = NULL;
if (m->mms2mobile == mv)
m->mms2mobile = NULL;
mv->delete_after = time(NULL) + DEFAULT_DELETE_AGE;
gwlist_append(m->vasp_del_list, mv);
delete_stale_vasps(m, 0);
return 0;
}
#define ERROR(fmt,...) do {if (errors) gwlist_append(errors, octstr_format((fmt), ##__VA_ARGS__));} while(0)
#define WARNING(fmt,...) do {if (warnings) gwlist_append(warnings, octstr_format((fmt), ##__VA_ARGS__));}while(0)
MmsVasp *mmsc_load_vasp_from_conf(MmscSettings *m, mCfgGrp *grp, List *errors, List *warnings)
{
mCfg *cfg = m->cfg;
MmsVasp *mv = gw_malloc(sizeof *mv), *ret = NULL;
Octstr *s;
int ibool = 0;
long short_code;
memset(mv, 0, sizeof mv[0]);
mv->throughput = -1;
mv->num_short_codes = 0;
mv->id = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-id"));
if (mms_cfg_get_int(cfg, grp, octstr_imm("short-code"), &short_code) == 0) {
WARNING("'short-code' is deprecated, please use 'short-codes'");
mv->num_short_codes = 1;
mv->short_codes = gw_malloc(sizeof mv->short_codes[0]);
mv->short_codes[0] = short_code;
} else if ((s = mms_cfg_get(cfg, grp, octstr_imm("short-codes"))) != NULL) {
List *l = octstr_split(s, octstr_imm(";"));
Octstr *x;
mv->short_codes = gw_malloc((gwlist_len(l) + 1) * sizeof mv->short_codes[0]);
while ((x = gwlist_extract_first(l)) != NULL) {
if ((short_code = strtoul(octstr_get_cstr(x), NULL, 10)) == 0 &&
(errno == EINVAL || errno == ERANGE))
ERROR("Invalid short-code format: %S", x);
else
mv->short_codes[mv->num_short_codes++] = short_code;
octstr_destroy(x);
}
gwlist_destroy(l, NULL);
octstr_destroy(s);
}
if (mv->num_short_codes == 0) {
ERROR("No valid short codes defined, VASP cannot be loaded");
free_vasp(mv);
goto done;
}
if ((s = mms_cfg_get(cfg, grp, octstr_imm("throughput"))) != NULL) {
mv->throughput = atof(octstr_get_cstr(s));
octstr_destroy(s);
}
mv->vasp_username = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-username"));
mv->vasp_password = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-password"));
mv->vasp_url = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-url"));
s = _mms_cfg_getx(cfg, 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);
mv->ver.major = mv->ver.minor1 = mv->ver.minor2 = 0;
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mm7-version"))) != NULL &&
octstr_len(s) > 0)
sscanf(octstr_get_cstr(s), "%d.%d.%d", &mv->ver.major, &mv->ver.minor1, &mv->ver.minor2);
else {
if (mv->type == SOAP_VASP) {
mv->ver.major = MAJOR_VERSION(DEFAULT_MM7_VERSION);
mv->ver.minor1 = MINOR1_VERSION(DEFAULT_MM7_VERSION);
mv->ver.minor2 = MINOR2_VERSION(DEFAULT_MM7_VERSION);
} else if (mv->type == EAIF_VASP) {
mv->ver.major = 3;
mv->ver.minor1 = 0;
}
}
octstr_destroy(s);
if ((s = mms_cfg_get(cfg, grp, octstr_imm("mm7-soap-xmlns"))) != NULL) {
strncpy(mv->ver.xmlns, octstr_get_cstr(s), sizeof mv->ver.xmlns);
mv->ver.xmlns[-1 + sizeof mv->ver.xmlns] = 0; /* NULL terminate, just in case. */
octstr_destroy(s);
} else
mv->ver.xmlns[0] = 0;
mv->ver.use_mm7_namespace = 1;
mms_cfg_get_bool(cfg, grp, octstr_imm("use-mm7-soap-namespace-prefix"), &mv->ver.use_mm7_namespace);
/* Set the handler vasp accounts. */
if (mms_cfg_get_bool(cfg, grp, octstr_imm("mms-to-email-handler"), &ibool) == 0 &&
ibool) {
if (m->mms2email)
WARNING("mms-to-email handler VASP res-et!.");
m->mms2email = mv;
}
if (mms_cfg_get_bool(cfg, grp, octstr_imm("mms-to-local-copy-handler"), &ibool) == 0 &&
ibool) {
if (m->mms2mobile)
WARNING("mms-to-mobile copy handler VASP re-set.");
m->mms2mobile = mv;
}
if ((s = mms_cfg_get(cfg, grp, octstr_imm("send-uaprof"))) != NULL){
if (octstr_str_case_compare(s, "url") == 0)
mv->send_uaprof = UAProf_URL;
else if (octstr_str_case_compare(s, "ua") == 0)
mv->send_uaprof = UAProf_UA;
else {
WARNING("unknown send-uaprof value '%s'. Must be \"ua\" or \"url\"!",
octstr_get_cstr(s));
mv->send_uaprof = UAProf_None;
}
octstr_destroy(s);
}
mv->stats.start_time = time(NULL);
if (dict_put_once(m->vasp_list, mv->id, mv) == 0) {
ERROR("Failed to load vasp <%S>. ID is not unique!", mv->id);
free_vasp(mv);
} else
ret = mv;
done:
return ret;
}
List *mms_proxy_relays(mCfg *cfg, Octstr *myhostname)
{
List *gl = mms_cfg_get_multi(cfg, octstr_imm("mmsproxy"));
@ -622,3 +765,260 @@ void notify_prov_server(char *cmd, char *from, char *event, char *arg, Octstr *m
octstr_destroy(tmp3);
octstr_destroy(tmp4);
}
static void free_vasp(MmsVasp *m)
{
if (m == NULL)
return;
octstr_destroy(m->id);
octstr_destroy(m->vasp_username);
octstr_destroy(m->vasp_password);
octstr_destroy(m->vasp_url);
if (m->short_codes)
gw_free(m->short_codes);
gw_free(m);
}
static void delete_stale_vasps(MmscSettings *settings, int delete_all)
{
MmsVasp *mv;
int n = gwlist_len(settings->vasp_del_list);
while (n-- > 0 &&
(mv = gwlist_extract_first(settings->vasp_del_list)) != NULL)
if (delete_all ||
mv->delete_after <= time(NULL))
free_vasp(mv);
else
gwlist_append(settings->vasp_del_list, mv); /* put it back. */
if (delete_all) {
gwlist_destroy(settings->vasp_del_list, NULL);
settings->vasp_del_list = NULL;
}
}
static void append_vasp_status(Octstr *rbody, MmsVasp *m, List *warnings)
{
time_t t = time(NULL);
int i, n;
unsigned long tdiff;
char lbuf[128], ubuf[128], tmp[64], mm7ver[64] = "n/a";
char *typ;
if (m->type == SOAP_VASP) {
typ = "SOAP";
sprintf(mm7ver, "%d.%d.%d", m->ver.major, m->ver.minor1, m->ver.minor2);
} else if (m->type == EAIF_VASP) {
typ = "EAIF";
sprintf(mm7ver, EAIF_VERSION, m->ver.major, m->ver.minor1);
} else
typ = "none";
if (m->stats.last_pdu > 0) {
struct tm tm = gw_localtime(m->stats.last_pdu);
gw_strftime(lbuf,sizeof lbuf, "%x %X", &tm);
} else
strcpy(lbuf, "n/a");
/* Compute uptime */
tdiff = t - m->stats.start_time;
if (tdiff >= 24*3600) {/* we have some days */
sprintf(ubuf, "%ld days", tdiff/(24*3600));
tdiff %= 24*3600;
} else
ubuf[0] = 0;
if (tdiff >= 3600) {
long x = tdiff/3600;
sprintf(tmp, "%s%ld hrs", ubuf[0] ? " " : "", x);
strcat(ubuf, tmp);
tdiff %= 3600;
}
if (tdiff >= 60) {
sprintf(tmp, "%s%ld mins", ubuf[0] ? " " : "", tdiff/60);
strcat(ubuf, tmp);
tdiff %= 60;
}
if (tdiff > 0) {
sprintf(tmp, "%s%ld secs", ubuf[0] ? " " : "", tdiff);
strcat(ubuf, tmp);
}
if (m->throughput > 0)
sprintf(tmp, "%.2f", m->throughput);
else
sprintf(tmp, "n/a");
octstr_format_append(rbody, "<vasp id=\"%S\" type=\"%s\">\n "
"<vasp-url>%S</vasp-url>\n"
"<incoming-username>%S</incoming-username>\n"
"<throughput>%s</throughput>\n"
"<mm7-version>%s</mm7-version>\n"
"<send-ua-prof>%s</send-ua-prof>\n"
"<stats>\n"
"<uptime>%s</uptime>\n"
"<last-pdu>%s</last-pdu>\n"
"<outgoing><pdus>%ld</pdus><errors>%ld</errors></outgoing>\n"
"<incoming><pdus>%ld</pdus><errors>%ld</errors></incoming>\n"
"</stats>\n"
"<short-codes>\n" ,
m->id,
typ,
m->vasp_url,
m->vasp_username,
tmp,
mm7ver,
m->send_uaprof == UAProf_URL ?
"url" : (m->send_uaprof == UAProf_UA ? "user-agent" : "n/a"),
ubuf,
lbuf,
(long)m->stats.mt_pdus, (long)m->stats.mt_errors,
(long)m->stats.mo_pdus, (long)m->stats.mo_errors);
for (i = 0; i<m->num_short_codes; i++)
octstr_format_append(rbody, "<short-code>%ld</short-code>\n", m->short_codes[i]);
octstr_append_cstr(rbody, "</short-codes>\n");
for (i = 0, n = gwlist_len(warnings); i<n; i++)
octstr_format_append(rbody, "<warning>%S</warning>\n", gwlist_get(warnings, i));
octstr_append_cstr(rbody, "</vasp>\n");
}
static void admin_handler(MmscSettings *settings)
{
HTTPClient *client;
Octstr *ip;
List *headers;
Octstr *url;
Octstr *body;
List *cgivars;
Octstr *pass;
mms_info(0, "mmsc", NULL,"Admin Interface -- startup on port %d", (int)settings->admin_port);
while((client = http_accept_request(settings->admin_port,
&ip, &url, &headers,
&body, &cgivars)) != NULL) {
int flg = -1;
Octstr *rbody = NULL;
int rstatus = HTTP_OK;
if (!(flg = is_allowed_ip(settings->admin_allow_ip, settings->admin_deny_ip, ip)) ||
((pass = http_cgi_variable(cgivars, "password")) == NULL &&
settings->admin_pass != NULL) ||
(settings->admin_pass && octstr_compare(pass, settings->admin_pass) != 0)) {
mms_error(0, "mmsc", NULL, "Improper access to mmsbox admin interface from IP[%s]: %s",
octstr_get_cstr(ip),
flg ? "Invalid/empty password" : "IP not allowed");
if (flg) {/* means it is allowed by IP */
rstatus = HTTP_UNAUTHORIZED;
rbody = octstr_imm("Auth failed");
}
} else {
Octstr *vasp_id = http_cgi_variable(cgivars, "vasp-id");
List *l = NULL;
rbody = octstr_create("<?xml version='1.0'?>\n");
/* Command URI is one of: /status, /start, /stop.
* vasp-id is either empty (meaning ALL) or an ID of an existing VASPs connection.
*/
if (octstr_str_case_compare(url, "/start") == 0) {
mCfgGrp *m;
if (vasp_id == NULL)
l = mms_cfg_get_multi(settings->cfg, octstr_imm("mms-vasp"));
else if ((m = mms_get_multi_by_field(settings->cfg,
octstr_imm("mms-vasp"),
octstr_imm("vasp-id"),
vasp_id)) != NULL) {
l = gwlist_create();
gwlist_append(l, m);
}
/* Start MMS VASPs. */
while ((m = gwlist_extract_first(l)) != NULL) {
Octstr *x;
List *e = gwlist_create();
List *w = gwlist_create();
MmsVasp *mv = mmsc_load_vasp_from_conf(settings, m, e, w);
if (mv != NULL)
append_vasp_status(rbody, mv, w);
else if (gwlist_len(e) > 0)
while ((x = gwlist_extract_first(e)) != NULL) {
octstr_format_append(rbody,
"<load-vasp><Error>%S</Error></load-vasp>\n",
x);
octstr_destroy(x);
}
gwlist_destroy(e, (void *)octstr_destroy);
gwlist_destroy(w, (void *)octstr_destroy);
}
} else if (octstr_str_case_compare(url, "/stop") == 0) {
Octstr *x;
if (vasp_id == NULL)
l = dict_keys(settings->vasp_list);
else {
l = gwlist_create();
gwlist_append(l, octstr_duplicate(vasp_id));
}
while ((x = gwlist_extract_first(l)) != NULL) {
int ret = mmsc_unload_vasp(settings, x);
octstr_format_append(rbody,
"<unload-vasp><%s/></unload-vasp>\n",
ret == 0 ? "Success" : "Failed");
octstr_destroy(x);
}
} else if (octstr_str_case_compare(url, "/status") == 0) {
Octstr *x;
MmsVasp *mv;
if (vasp_id == NULL)
l = dict_keys(settings->vasp_list);
else {
l = gwlist_create();
gwlist_append(l, octstr_duplicate(vasp_id));
}
while ((x = gwlist_extract_first(l)) != NULL) {
if ((mv = dict_get(settings->vasp_list, x)) != NULL)
append_vasp_status(rbody, mv, NULL);
octstr_destroy(x);
}
}
gwlist_destroy(l, NULL);
}
if (rbody) {
List *rh = http_create_empty_headers();
http_header_add(rh, "Content-Type", "text/xml");
http_send_reply(client, rstatus, rh, rbody);
http_destroy_headers(rh);
} else
http_close_client(client);
octstr_destroy(rbody);
octstr_destroy(ip);
octstr_destroy(url);
octstr_destroy(body);
http_destroy_cgiargs(cgivars);
http_destroy_headers(headers);
}
mms_info(0, "mmsbox", NULL,"Admin Interface -- shuttind down on port %d", (int)settings->admin_port);
}

View File

@ -33,12 +33,21 @@ typedef struct MmsProxyRelay {
typedef struct MmsVasp {
Octstr *id;
long short_code;
long *short_codes; /* array of short codes. */
int num_short_codes; /* number of short codes above. */
enum {SOAP_VASP, EAIF_VASP, NONE_VASP} type;
Octstr *vasp_username, *vasp_password;
Octstr *vasp_url;
enum {UAProf_None, UAProf_URL, UAProf_UA} send_uaprof;
MM7Version_t ver;
double throughput;
time_t delete_after; /* Set, when thingie should be deleted. */
struct {
unsigned long mo_pdus, mt_pdus;
unsigned long mo_errors, mt_errors;
time_t start_time, last_pdu;
} stats;
} MmsVasp;
typedef struct MmscSettings {
@ -106,15 +115,26 @@ typedef struct MmscSettings {
Octstr *wap_gw_msisdn_header;
Octstr *wap_gw_ip_header;
List *vasp_list; /* of MmsVasp * */
MmsVasp *mms2email, *mms2mobile;
Dict *vasp_list; /* of MmsVasp *, indexed by ID */
List *vasp_del_list; /* stuff to be deleted! */
MmsVasp *mms2email, *mms2mobile;
/* Stuff for the admin interface. */
long admin_port;
Octstr *admin_allow_ip, *admin_deny_ip;
Octstr *admin_pass;
long admin_thread;
mCfg *cfg; /* have a pointer to it. */
} MmscSettings;
/* Returns mmsc settings. */
MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays);
MmscSettings *mms_load_mmsc_settings(Octstr *fname, List **proxyrelays);
MmsVasp *mmsc_load_vasp_from_conf(MmscSettings *m, mCfgGrp *grp,
List *errors, List *warnings);
int mmsc_unload_vasp(MmscSettings *m, Octstr *id);
/* do final cleanup. */
void mms_cleanup_mmsc_settings(MmscSettings *settings);
/* Returns list of MmsProxyRelay */

View File

@ -50,8 +50,6 @@ static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid,
static void strip_quotes(Octstr *s);
static mCfg *cfg;
static List *proxyrelays;
@ -78,24 +76,15 @@ int main(int argc, char *argv[])
else
fname = octstr_create(argv[cfidx]);
cfg = mms_cfg_read(fname);
if (cfg == NULL)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
octstr_destroy(fname);
mms_info(0, "mmsfromemail", NULL, "----------------------------------------");
mms_info(0, "mmsfromemail", NULL, " MMSC Email2MMS/MM4 Incoming Tool version %s starting", MMSC_VERSION);
/* Load settings. */
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
mms_cfg_destroy(cfg);
settings = mms_load_mmsc_settings(fname, &proxyrelays);
if (!settings)
panic(0, "No global MMSC configuration!");
panic(0, "No global MMSC configuration, or failed to read conf from <%s>!", octstr_get_cstr(fname));
octstr_destroy(fname);
if (!xto || !xfrom) {
mms_error(0, "mmsfromemail", NULL, "usage: %s -f from -t to!", argv[0]);
return -1;

View File

@ -52,12 +52,14 @@ static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId
List *qh,
MmsMsg *m, Octstr **error);
static int _x_octstr_int_compare(int n, Octstr *s);
static int match_short_codes(Octstr *phonenum, long short_codes[], int num_codes);
#if 0
/* Send errors */
#define MMS_SEND_OK 0
#define MMS_SEND_ERROR_TRANSIENT -1
#define MMS_SEND_ERROR_FATAL -2
#endif
#define NMAX 256
static char qdir[NMAX];
@ -201,7 +203,8 @@ static int sendMsg(MmsEnvelope *e)
Octstr *mmsc;
int sent = 0;
MmsVasp *vasp;
List *vlist;
/* If it is an IP, send to mobile handler, else if number, look for recipient. */
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
phonenum = octstr_copy(to->rcpt, 0, j);
@ -237,9 +240,10 @@ static int sendMsg(MmsEnvelope *e)
}
/* Search VASP list, see what you can find... */
for (j = 0, m = gwlist_len(settings->vasp_list); j < m; j++)
if ((vasp = gwlist_get(settings->vasp_list, j)) != NULL &&
_x_octstr_int_compare(vasp->short_code, phonenum) == 0) {
vlist = dict_keys(settings->vasp_list);
for (j = 0, m = gwlist_len(vlist); j < m; j++)
if ((vasp = dict_get(settings->vasp_list, gwlist_get(vlist, j))) != NULL &&
match_short_codes(phonenum, vasp->short_codes, vasp->num_short_codes)) {
res = mms_sendtovasp(vasp, e->from, to->rcpt,
e->msgId,
e->hdrs,
@ -248,7 +252,8 @@ static int sendMsg(MmsEnvelope *e)
sent = 1;
break;
}
gwlist_destroy(vlist, (void *)octstr_destroy);
if (sent != 1) { /* Not yet, sent, find the receiver MMSC. */
/* Normalise the number, then see if we can resolve home MMSC for this recipient. */
#if 0
@ -322,9 +327,12 @@ static int sendMsg(MmsEnvelope *e)
}
}
if (sent != 1) /* try mm7 delivery. Again. */
for (j = 0, m = gwlist_len(settings->vasp_list); j < m; j++)
if ((vasp = gwlist_get(settings->vasp_list, j)) != NULL &&
if (sent != 1) { /* try mm7 delivery. Again. */
List *vlist = dict_keys(settings->vasp_list);
Octstr *vid;
for (j = 0, m = gwlist_len(vlist); j < m; j++)
if ((vid = gwlist_get(vlist, j)) != NULL &&
(vasp = dict_get(settings->vasp_list, vid)) != NULL &&
vasp->id &&
octstr_compare(vasp->id, mmsc) == 0) {
res = mms_sendtovasp(vasp, e->from, to->rcpt,
@ -335,6 +343,9 @@ static int sendMsg(MmsEnvelope *e)
sent = 1;
break;
}
gwlist_destroy(vlist, (void *)octstr_destroy);
}
}
octstr_destroy(mmsc);
}
@ -390,12 +401,19 @@ static int sendMsg(MmsEnvelope *e)
}
/* Write to log */
mms_info(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: err=%s",
SEND_ERROR_STR(res),
e->xqfname,
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
err ? octstr_get_cstr(err) : "(null)");
if (res == MMS_SEND_ERROR_FATAL)
mms_error(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: %s",
SEND_ERROR_STR(res),
e->xqfname,
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
err ? octstr_get_cstr(err) : "(null)");
else
mms_info(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: %s",
SEND_ERROR_STR(res),
e->xqfname,
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
err ? octstr_get_cstr(err) : "(null)");
if (res == MMS_SEND_OK &&
(e->msgtype == MMS_MSGTYPE_SEND_REQ ||
e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF)) { /* Do CDR writing. */
@ -598,7 +616,7 @@ static int _x_octstr_int_compare(int n, Octstr *s)
static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
List *qh,
MmsMsg *m, Octstr **error)
MmsMsg *m, Octstr **error, int *got_conn_error)
{
int ret = MMS_SEND_ERROR_TRANSIENT;
int mtype = mms_messagetype(m);
@ -641,7 +659,7 @@ static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
}
hstatus = mms_url_fetch_content(HTTP_METHOD_POST, vasp->vasp_url, rh, body, &ph, &rbody);
*got_conn_error = (hstatus < 0);
if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d!",
octstr_get_cstr(vasp->vasp_url), hstatus);
@ -700,7 +718,7 @@ static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
}
static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
MmsMsg *m, Octstr **error)
MmsMsg *m, Octstr **error, int *got_conn_error)
{
int ret = MMS_SEND_ERROR_TRANSIENT;
int mtype = mms_messagetype(m);
@ -745,9 +763,10 @@ static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
} else
mms_info(0, "MM7", vasp->id, "Sent to VASP[%s], code=[%d]", octstr_get_cstr(vasp->id), hstatus);
if (hstatus < 0)
if (hstatus < 0) {
ret = MMS_SEND_ERROR_TRANSIENT;
else {
*got_conn_error = (hstatus < 0);
} else {
hstatus = http_status_class(hstatus);
if (hstatus == HTTP_STATUS_CLIENT_ERROR)
ret = MMS_SEND_ERROR_TRANSIENT;
@ -771,16 +790,36 @@ static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid
List *qh,
MmsMsg *m, Octstr **err)
{
int ret, conn_err = 0;
if (m == NULL) {
*err = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
return MMS_SEND_ERROR_FATAL;
ret = MMS_SEND_ERROR_FATAL;
} else if (vasp->type == SOAP_VASP)
return mm7soap_send(vasp, from, to, msgid, qh, m, err);
ret = mm7soap_send(vasp, from, to, msgid, qh, m, err, &conn_err);
else if (vasp->type == EAIF_VASP)
return mm7eaif_send(vasp, from, to, msgid, m, err);
ret = mm7eaif_send(vasp, from, to, msgid, m, err, &conn_err);
else {
mms_error(0, "MM7", vasp->id, "Vasp[%s] of unknown type, can't send!",
vasp->id ? octstr_get_cstr(vasp->id) : "");
return MMS_SEND_ERROR_FATAL;
ret = MMS_SEND_ERROR_FATAL;
}
if (ret < 0) /* failed. */
vasp->stats.mt_errors++;
if (!conn_err) {
vasp->stats.mt_pdus++;
vasp->stats.last_pdu = time(NULL);
}
return ret;
}
static int match_short_codes(Octstr *phonenum, long short_codes[], int num_codes)
{
int i;
for (i = 0; i<num_codes;i++)
if (_x_octstr_int_compare(short_codes[i], phonenum) == 0)
return 1;
return 0;
}

View File

@ -1475,16 +1475,16 @@ static void sendmms_proxy(MmsHTTPClientInfo *h)
}
/* Find sender credentials: only auth-basic supported for now. */
static MmsVasp *find_mm7sender(List *headers, List *vasps)
static MmsVasp *find_mm7sender(List *headers, Dict *vasps, int *has_auth)
{
Octstr *v = http_header_value(headers, octstr_imm("Authorization"));
Octstr *p = NULL, *q = NULL;
Octstr *p = NULL, *q = NULL, *x;
MmsVasp *m = NULL;
int i, n;
List *vlist;
int i;
#if 0
return gwlist_get(vasps,0); /* XXX for testing... */
#endif
*has_auth = (v != NULL);
if (!v ||
octstr_search(v, octstr_imm("Basic "), 0) != 0)
goto done;
@ -1496,15 +1496,20 @@ static MmsVasp *find_mm7sender(List *headers, List *vasps)
octstr_delete(p, i, octstr_len(p));
/* p = user, q = pass. */
for (i = 0, n = gwlist_len(vasps); i<n; i++) {
MmsVasp *x = gwlist_get(vasps, i);
if (octstr_compare(x->vasp_username, p) == 0 &&
octstr_compare(x->vasp_password, q) == 0) {
m = x;
vlist = dict_keys(vasps);
while ((x = gwlist_extract_first(vlist)) != NULL) {
MmsVasp *mv = dict_get(vasps, x);
octstr_destroy(x);
if (mv &&
octstr_compare(mv->vasp_username, p) == 0 &&
octstr_compare(mv->vasp_password, q) == 0) {
m = mv;
break;
}
}
gwlist_destroy(vlist, NULL);
/* if it can't authenticate, returns NULL. */
@ -1543,13 +1548,17 @@ static void mm7soap_dispatch(MmsHTTPClientInfo *h)
" --> Enterred mm7dispatch interface, mreq=[%s] mtype=[%s] <-- ",
mreq ? "Ok" : "Null",
mreq ? (char *)msgtype : "Null");
if (!mreq) {
mresp = mm7_make_resp(NULL, MM7_SOAP_FORMAT_CORRUPT, NULL,0);
status = MM7_SOAP_FORMAT_CORRUPT;
mresp = mm7_make_resp(NULL, status, NULL,0);
goto done;
}
sender = octstr_format("%d/TYPE=PLMN", h->vasp->short_code);
h->vasp->stats.mo_pdus++;
h->vasp->stats.last_pdu = time(NULL);
sender = octstr_format("%d/TYPE=PLMN", h->vasp->short_codes[0]); /* defaults to first short code. */
switch (mm7_msgtype(mreq)) {
case MM7_TAG_SubmitReq:
mm7_get_envelope(mreq, &from, &to, &subject, &vasid, &expiryt, &delivert, NULL, NULL);
@ -1684,12 +1693,15 @@ static void mm7soap_dispatch(MmsHTTPClientInfo *h)
mresp = mm7_make_resp(mreq, status, NULL,0);
break;
default:
mresp = mm7_make_resp(mreq, MM7_SOAP_UNSUPPORTED_OPERATION, NULL,0);
status = MM7_SOAP_UNSUPPORTED_OPERATION;
mresp = mm7_make_resp(mreq, status, NULL,0);
break;
}
done:
if (!MM7_SOAP_STATUS_OK(status))
h->vasp->stats.mo_errors++; /* increment error count. */
if (mresp && mm7_soapmsg_to_httpmsg(mresp, &h->vasp->ver, &rh, &reply_body) == 0)
http_send_reply(h->client, hstatus, rh, reply_body);
@ -1720,7 +1732,6 @@ static void mm7soap_dispatch(MmsHTTPClientInfo *h)
static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
{
/* if no vasp, return 4001 error. */
MmsMsg *m = NULL;
List *mh = NULL;
int hstatus = HTTP_NO_CONTENT;
@ -1749,6 +1760,9 @@ static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
goto done;
}
h->vasp->stats.mo_pdus++;
h->vasp->stats.last_pdu = time(NULL);
mms_remove_headers(m, "Message-ID");
mh = mms_message_headers(m);
/* Now get sender and receiver data.
@ -1840,6 +1854,9 @@ static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
http_send_reply(h->client, hstatus, rh, octstr_imm(""));
if (http_status_class(hstatus) != HTTP_OK)
h->vasp->stats.mo_errors++;
http_destroy_headers(hto);
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
octstr_destroy(hfrom);
@ -1858,15 +1875,16 @@ static void mm7proxy(void *unused)
&h.body, &h.cgivars)) != NULL)
if (is_allowed_ip(settings->allow_ip, settings->deny_ip, h.ip)) {
MmsHTTPClientInfo *hx = gw_malloc(sizeof *hx);
int has_auth = 0;
double tdur;
/* Clear some stuff. */
h.client_addr = NULL;
h.base_client_addr = NULL;
h.profile_url = NULL;
/* Get the MM7 sender address. */
h.vasp = find_mm7sender(h.headers, settings->vasp_list);
h.vasp = find_mm7sender(h.headers, settings->vasp_list, &has_auth);
h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
debug("mmsproxy", 0,
" MM7 Request, ip=%s, vasp=%s ",
@ -1888,7 +1906,21 @@ static void mm7proxy(void *unused)
octstr_imm(""));
http_destroy_headers(hh);
free_clientInfo(hx, 1);
mms_info(0, "MM7", NULL, "MMSC: Auth failed/VASP not found in MM7 incoming connection!");
if (!has_auth)
mms_info_ex("auth", 0, "MM7", NULL, "MMSC: Auth failed/VASP not found in MM7 incoming connection!");
else
mms_error_ex("auth", 0, "MM7", NULL, "MMSC: Auth failed/VASP not found in MM7 incoming connection!");
} else if (h.vasp->throughput > 0 &&
(tdur = h.vasp->stats.start_time - time(NULL)) > 0 &&
h.vasp->stats.mo_pdus/tdur > h.vasp->throughput) { /* throttling error, do not even process the message. */
List *hh = http_create_empty_headers();
http_send_reply(hx->client, 409, hh, /* respond with HTTP Conflict code. */
octstr_imm("Throttling limit exceeded. Try again later"));
http_destroy_headers(hh);
free_clientInfo(hx, 1);
mms_error_ex("throttle", 0, "MM7", h.vasp->id,
"MMSC: VASP Exceeded throttling limit (%.2f PDU/sec). Connection reset!",
h.vasp->throughput);
} else if (h.vasp->type == SOAP_VASP)
gwthread_create((gwthread_func_t *)mm7soap_dispatch, hx);
else

View File

@ -57,7 +57,6 @@ static int find_own(int i, int argc, char *argv[])
return -1;
}
static mCfg *cfg;
static MmscSettings *settings;
static List *proxyrelays;
static MmsMsg *m;
@ -84,25 +83,17 @@ int main(int argc, char *argv[])
else
fname = octstr_create(argv[cfidx]);
cfg = mms_cfg_read(fname);
if (cfg == NULL)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
octstr_destroy(fname);
mms_info(0, "mmssend", NULL, "----------------------------------------");
mms_info(0, "mmssend", NULL, " MMSC Message sender runner version %s starting", MMSC_VERSION);
/* Load settings. */
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
mms_cfg_destroy(cfg);
settings = mms_load_mmsc_settings(fname, &proxyrelays);
if (!settings)
panic(0, "No global MMSC configuration!");
panic(0, "No global MMSC configuration, or failed to read conf from <%s>!", octstr_get_cstr(fname));
octstr_destroy(fname);
if (from == NULL ||
to == NULL) {
mms_error(0, "mmssend", NULL, "Sender and recipient addresses required!\n");