mmsc admin interface
This commit is contained in:
parent
f55d24567f
commit
5afec26e5d
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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,18 +563,22 @@ 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]",
|
||||
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);
|
||||
|
@ -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",
|
||||
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,
|
||||
err ? octstr_get_cstr(err) : "(none)");
|
||||
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);
|
||||
|
|
|
@ -1201,6 +1201,7 @@ 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);
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
mms_cfg_destroy(cfg);
|
||||
settings = mms_load_mmsc_settings(fname,&proxyrelays);
|
||||
|
||||
octstr_destroy(fname);
|
||||
if (!settings)
|
||||
panic(0, "No MMSC configuration!");
|
||||
|
||||
|
|
|
@ -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,16 +304,127 @@ 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();
|
||||
m->vasp_list = dict_create(53, NULL);
|
||||
for (i=0, n=gwlist_len(l); i<n; i++) {
|
||||
mCfgGrp *grp = gwlist_get(l, i);
|
||||
MmsVasp *mv = gw_malloc(sizeof *mv);
|
||||
List *e = gwlist_create();
|
||||
List *w = gwlist_create();
|
||||
Octstr *x;
|
||||
|
||||
mmsc_load_vasp_from_conf(m, gwlist_get(l, i), e, w);
|
||||
|
||||
while ((x = gwlist_extract_first(e)) != NULL) {
|
||||
mms_error(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
|
||||
octstr_destroy(x);
|
||||
}
|
||||
|
||||
while ((x = gwlist_extract_first(w)) != NULL) {
|
||||
mms_warning(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
|
||||
octstr_destroy(x);
|
||||
}
|
||||
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"));
|
||||
mv->short_code = -1;
|
||||
mms_cfg_get_int(cfg, grp, octstr_imm("short-code"), &mv->short_code);
|
||||
|
||||
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"));
|
||||
|
@ -335,13 +472,13 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays)
|
|||
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.");
|
||||
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)
|
||||
mms_warning(0, "mmsc", NULL,"mms-to-mobile copy handler VASP specified more than once! Only last config taken.");
|
||||
WARNING("mms-to-mobile copy handler VASP re-set.");
|
||||
m->mms2mobile = mv;
|
||||
}
|
||||
|
||||
|
@ -351,16 +488,22 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays)
|
|||
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\"!",
|
||||
WARNING("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(l, NULL);
|
||||
return m;
|
||||
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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 * */
|
||||
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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,6 +203,7 @@ 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)
|
||||
|
@ -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,6 +252,7 @@ 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. */
|
||||
|
@ -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,7 +401,14 @@ 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",
|
||||
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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
*has_auth = (v != NULL);
|
||||
|
||||
#if 0
|
||||
return gwlist_get(vasps,0); /* XXX for testing... */
|
||||
#endif
|
||||
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);
|
||||
vlist = dict_keys(vasps);
|
||||
while ((x = gwlist_extract_first(vlist)) != NULL) {
|
||||
MmsVasp *mv = dict_get(vasps, x);
|
||||
|
||||
if (octstr_compare(x->vasp_username, p) == 0 &&
|
||||
octstr_compare(x->vasp_password, q) == 0) {
|
||||
m = 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. */
|
||||
|
||||
|
@ -1545,11 +1550,15 @@ static void mm7soap_dispatch(MmsHTTPClientInfo *h)
|
|||
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,7 +1875,8 @@ 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;
|
||||
|
@ -1866,7 +1884,7 @@ static void mm7proxy(void *unused)
|
|||
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
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue