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>
|
2008-09-04 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||||
* Minor fix/addition for Content-ID handling
|
* Minor fix/addition for Content-ID handling
|
||||||
* Generalised event logger module (to facilitate alarms, etc)
|
* Generalised event logger module (to facilitate alarms, etc)
|
||||||
|
|
|
@ -131,13 +131,14 @@ MULTI_GROUP(mms-vasp,
|
||||||
OCTSTR(mm7-soap-xmlns)
|
OCTSTR(mm7-soap-xmlns)
|
||||||
OCTSTR(use-mm7-soap-namespace-prefix)
|
OCTSTR(use-mm7-soap-namespace-prefix)
|
||||||
OCTSTR(short-code)
|
OCTSTR(short-code)
|
||||||
|
OCTSTR(short-codes)
|
||||||
OCTSTR(vasp-username)
|
OCTSTR(vasp-username)
|
||||||
OCTSTR(vasp-password)
|
OCTSTR(vasp-password)
|
||||||
OCTSTR(vasp-url)
|
OCTSTR(vasp-url)
|
||||||
OCTSTR(mms-to-email-handler)
|
OCTSTR(mms-to-email-handler)
|
||||||
OCTSTR(mms-to-local-copy-handler)
|
OCTSTR(mms-to-local-copy-handler)
|
||||||
OCTSTR(send-uaprof)
|
OCTSTR(send-uaprof)
|
||||||
|
OCTSTR(throughput)
|
||||||
)
|
)
|
||||||
|
|
||||||
MULTI_GROUP(send-mms-user,
|
MULTI_GROUP(send-mms-user,
|
||||||
|
|
|
@ -40,6 +40,9 @@
|
||||||
#define MMS_SEND_ERROR_TRANSIENT -1
|
#define MMS_SEND_ERROR_TRANSIENT -1
|
||||||
#define MMS_SEND_ERROR_FATAL -2
|
#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" : \
|
#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : \
|
||||||
(e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : \
|
(e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : \
|
||||||
((e) == MMS_SEND_QUEUED ? "Queued" : "Failed"))
|
((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;
|
int i, res = -1;
|
||||||
Octstr *v = http_header_value(headers, octstr_imm("Authorization"));
|
Octstr *v = http_header_value(headers, octstr_imm("Authorization"));
|
||||||
Octstr *p = NULL, *q = NULL;
|
Octstr *p = NULL, *q = NULL;
|
||||||
|
|
||||||
if (user == NULL ||
|
*has_auth_hdr = (v != NULL);
|
||||||
octstr_len(user) == 0) {
|
if (octstr_len(user) == 0) {
|
||||||
res = 0;
|
res = 0;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -563,19 +563,23 @@ static void dispatch_mm7_recv(List *rl)
|
||||||
MmsBoxHTTPClientInfo *h;
|
MmsBoxHTTPClientInfo *h;
|
||||||
|
|
||||||
while ((h = gwlist_consume(rl)) != NULL) {
|
while ((h = gwlist_consume(rl)) != NULL) {
|
||||||
int ret = -1;
|
int ret = -1, has_auth = 0;
|
||||||
MmscGrp *m = h->m;
|
MmscGrp *m = h->m;
|
||||||
if (auth_check(m->incoming.user,
|
if (auth_check(m->incoming.user,
|
||||||
m->incoming.pass,
|
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();
|
List *hh = http_create_empty_headers();
|
||||||
http_header_add(hh, "WWW-Authenticate",
|
http_header_add(hh, "WWW-Authenticate",
|
||||||
"Basic realm=\"" MM_NAME "\"");
|
"Basic realm=\"" MM_NAME "\"");
|
||||||
http_send_reply(h->client, HTTP_UNAUTHORIZED, hh,
|
http_send_reply(h->client, HTTP_UNAUTHORIZED, hh,
|
||||||
octstr_imm("Authentication failed"));
|
octstr_imm("Authentication failed"));
|
||||||
http_destroy_headers(hh);
|
http_destroy_headers(hh);
|
||||||
mms_info(0, "MM7", m->id, "Auth failed, incoming connection, MMC group=[%s]",
|
if (!has_auth)
|
||||||
m->id ? octstr_get_cstr(m->id) : "(none)");
|
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)
|
} else if (h->m->type == SOAP_MMSC)
|
||||||
ret = mm7soap_receive(h);
|
ret = mm7soap_receive(h);
|
||||||
else
|
else
|
||||||
|
@ -632,7 +636,7 @@ void mmsc_receive_func(MmscGrp *m)
|
||||||
} else {
|
} else {
|
||||||
h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
|
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)",
|
m->id ? octstr_get_cstr(m->id) : "(none)",
|
||||||
h.ip ? octstr_get_cstr(h.ip) : "(none)",
|
h.ip ? octstr_get_cstr(h.ip) : "(none)",
|
||||||
h.ua ? octstr_get_cstr(h.ua) : "(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,
|
from, to, transid, linkedid, vasid,
|
||||||
service_code, m, hdrs, err, &retry);
|
service_code, m, hdrs, err, &retry);
|
||||||
else
|
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) : "");
|
mmc->id ? octstr_get_cstr(mmc->id) : "");
|
||||||
|
|
||||||
throughput = mmc->throughput;
|
throughput = mmc->throughput;
|
||||||
|
@ -1023,11 +1027,17 @@ static int sendMsg(MmsEnvelope *e)
|
||||||
if (res == MMS_SEND_ERROR_FATAL)
|
if (res == MMS_SEND_ERROR_FATAL)
|
||||||
to->process = 0; /* No more attempts. */
|
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)
|
||||||
SEND_ERROR_STR(res),
|
mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s]",
|
||||||
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
|
SEND_ERROR_STR(res),
|
||||||
new_msgid ? octstr_get_cstr(new_msgid) : NULL,
|
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
|
||||||
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(new_msgid);
|
||||||
octstr_destroy(err);
|
octstr_destroy(err);
|
||||||
|
|
|
@ -1201,7 +1201,8 @@ static void dispatch_sendmms_recv(List *rl)
|
||||||
Octstr *password;
|
Octstr *password;
|
||||||
Octstr *err = NULL;
|
Octstr *err = NULL;
|
||||||
List *cgivar_ctypes = NULL;
|
List *cgivar_ctypes = NULL;
|
||||||
|
char *etype = NULL;
|
||||||
|
|
||||||
int res = 0, tparse = parse_cgivars(h->headers, h->body, &h->cgivars, &cgivar_ctypes);
|
int res = 0, tparse = parse_cgivars(h->headers, h->body, &h->cgivars, &cgivar_ctypes);
|
||||||
|
|
||||||
username = http_cgi_variable(h->cgivars, "username");
|
username = http_cgi_variable(h->cgivars, "username");
|
||||||
|
@ -1380,10 +1381,11 @@ static void dispatch_sendmms_recv(List *rl)
|
||||||
"username=%s, password=%s!",
|
"username=%s, password=%s!",
|
||||||
username ? octstr_get_cstr(username) : "(null)",
|
username ? octstr_get_cstr(username) : "(null)",
|
||||||
password ? octstr_get_cstr(password) : "(null)");
|
password ? octstr_get_cstr(password) : "(null)");
|
||||||
|
etype = "auth";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err && res != 0)
|
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);
|
octstr_destroy(err);
|
||||||
/* Free the ip and other stuff here. */
|
/* 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;
|
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)
|
int mmsbox_stop_mmsc_conn(Octstr *mmc_id)
|
||||||
{
|
{
|
||||||
MmscGrp *mmc = dict_remove(mmscs, mmc_id); /* remove it so no one else can get it. */
|
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);
|
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. */
|
gwlist_append(mmsc_del_list, mmc); /* to be deleted later. */
|
||||||
|
|
||||||
|
delete_stale_mmsc(0); /* Also delete stale ones on each stop. */
|
||||||
return 0;
|
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)
|
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);
|
sprintf(xport, "%d", (int)m->incoming.port);
|
||||||
else
|
else
|
||||||
sprintf(xport, "n/a");
|
sprintf(xport, "n/a");
|
||||||
octstr_format_append(rbody, "<Mmsc id=\"%S\" type=\"%s\">\n "
|
octstr_format_append(rbody, "<mmsc id=\"%S\" type=\"%s\">\n "
|
||||||
"<Port>%s</Port>\n"
|
"<port>%s</port>\n"
|
||||||
"<Group>%S</Group>\n"
|
"<group>%S</group>\n"
|
||||||
"<Throughput>%.4f</Throughput>\n"
|
"<throughput>%.4f</throughput>\n"
|
||||||
"<Reroute>%s</Reroute>\n"
|
"<re-route>%s</re-route>\n"
|
||||||
"<Reroute-MMSC-ID>%S</Reroute-MMSC-ID>\n"
|
"<reroute-mmsc>%S</reroute-mmsc>\n"
|
||||||
"<Stats>\n"
|
"<stats>\n"
|
||||||
"<Uptime>%s</Uptime>\n"
|
"<uptime>%s</uptime>\n"
|
||||||
"<LastPDU>%s</LastPDU>\n"
|
"<last-pdu>%s</last-pdu>\n"
|
||||||
"<MT><PDUS>%ld</PDUS><ERRORS>%ld</ERRORS></MT>\n"
|
"<mt><pdus>%ld</pdus><errors>%ld</errors></mt>\n"
|
||||||
"<MO><PDUS>%ld</PDUS><ERRORS>%ld</ERRORS></MO>\n"
|
"<mt><pdus>%ld</pdu><errors>%ld</errors></mo>\n"
|
||||||
"</Stats>\n",
|
"</stats>\n",
|
||||||
m->id,
|
m->id,
|
||||||
typ,
|
typ,
|
||||||
xport,
|
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++)
|
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)
|
static void admin_handler(void *unused)
|
||||||
|
@ -931,7 +933,6 @@ static void admin_handler(void *unused)
|
||||||
Octstr *body;
|
Octstr *body;
|
||||||
List *cgivars;
|
List *cgivars;
|
||||||
Octstr *pass;
|
Octstr *pass;
|
||||||
Octstr *cmd;
|
|
||||||
|
|
||||||
|
|
||||||
mms_info(0, "mmsbox", NULL,"Admin Interface -- startup on port %d", (int)admin_port);
|
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;
|
rstatus = HTTP_UNAUTHORIZED;
|
||||||
rbody = octstr_imm("Auth failed");
|
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 {
|
} else {
|
||||||
Octstr *mmc_id = http_cgi_variable(cgivars, "mmsc-id");
|
Octstr *mmc_id = http_cgi_variable(cgivars, "mmsc-id");
|
||||||
List *l = NULL;
|
List *l = NULL;
|
||||||
|
|
||||||
rbody = octstr_create("<?xml version='1.0'?>\n");
|
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.
|
* 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;
|
mCfgGrp *m;
|
||||||
if (mmc_id == NULL)
|
if (mmc_id == NULL)
|
||||||
l = mms_cfg_get_multi(cfg, octstr_imm("mmsc"));
|
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);
|
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;
|
Octstr *x;
|
||||||
if (mmc_id == NULL)
|
if (mmc_id == NULL)
|
||||||
l = dict_keys(mmscs);
|
l = dict_keys(mmscs);
|
||||||
|
@ -1014,7 +1012,7 @@ static void admin_handler(void *unused)
|
||||||
octstr_destroy(x);
|
octstr_destroy(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (octstr_str_case_compare(cmd, "status") == 0) {
|
} else if (octstr_str_case_compare(url, "/status") == 0) {
|
||||||
Octstr *x;
|
Octstr *x;
|
||||||
MmscGrp *mc;
|
MmscGrp *mc;
|
||||||
if (mmc_id == NULL)
|
if (mmc_id == NULL)
|
||||||
|
|
|
@ -14,11 +14,9 @@
|
||||||
#include "mmsc.h"
|
#include "mmsc.h"
|
||||||
#include "mms_uaprof.h"
|
#include "mms_uaprof.h"
|
||||||
|
|
||||||
static mCfg *cfg;
|
|
||||||
MmscSettings *settings;
|
MmscSettings *settings;
|
||||||
List *proxyrelays;
|
List *proxyrelays;
|
||||||
|
|
||||||
|
|
||||||
static void quit_now(int notused)
|
static void quit_now(int notused)
|
||||||
{
|
{
|
||||||
stop_mmsrelay();
|
stop_mmsrelay();
|
||||||
|
@ -51,21 +49,14 @@ int main(int argc, char *argv[])
|
||||||
else
|
else
|
||||||
fname = octstr_create(argv[cfidx]);
|
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, "----------------------------------------");
|
||||||
mms_info(0, "mmsc", NULL," " MM_NAME " MMSC version %s starting", MMSC_VERSION);
|
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)
|
if (!settings)
|
||||||
panic(0, "No MMSC configuration!");
|
panic(0, "No MMSC configuration!");
|
||||||
|
|
||||||
|
|
|
@ -26,35 +26,61 @@
|
||||||
|
|
||||||
#define MMS_PORT 8191 /* Default content fetch port. */
|
#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)
|
void mms_cleanup_mmsc_settings(MmscSettings *settings)
|
||||||
{
|
{
|
||||||
/* eventually we will destroy the object. For now, we only cleanup queue module. */
|
/* eventually we will destroy the object. */
|
||||||
settings->qfs->mms_cleanup_queue_module();
|
|
||||||
|
|
||||||
|
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();
|
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;
|
Octstr *s;
|
||||||
|
|
||||||
List *l;
|
List *l;
|
||||||
mCfgGrp *grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
|
mCfgGrp *grp;
|
||||||
mCfgGrp *cgrp = mms_cfg_get_single(cfg, octstr_imm("core"));
|
mCfgGrp *cgrp;
|
||||||
MmscSettings *m = gw_malloc(sizeof *m);
|
MmscSettings *m;
|
||||||
long port = -1;
|
long port = -1;
|
||||||
Octstr *from, *user, *pass;
|
Octstr *from, *user, *pass;
|
||||||
Octstr *qdir = NULL;
|
Octstr *qdir = NULL;
|
||||||
int i, n, xx = 0;
|
int i, n, xx = 0, ssl = 0;
|
||||||
void *x;
|
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);
|
memset(m, 0, sizeof *m);
|
||||||
|
|
||||||
if (grp == NULL)
|
if (grp == NULL)
|
||||||
panic(0,"Missing required group `mbuni' in config file!");
|
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);
|
mms_load_core_settings(cfg, cgrp);
|
||||||
|
|
||||||
if ((x = _mms_load_module(cfg, grp, "event-logger-module", "event_logger", NULL)) != NULL) {
|
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. */
|
/* Now load the VASP list. */
|
||||||
l = mms_cfg_get_multi(cfg, octstr_imm("mms-vasp"));
|
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++) {
|
for (i=0, n=gwlist_len(l); i<n; i++) {
|
||||||
mCfgGrp *grp = gwlist_get(l, i);
|
List *e = gwlist_create();
|
||||||
MmsVasp *mv = gw_malloc(sizeof *mv);
|
List *w = gwlist_create();
|
||||||
Octstr *s;
|
Octstr *x;
|
||||||
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);
|
|
||||||
|
|
||||||
mv->vasp_username = _mms_cfg_getx(cfg, grp, octstr_imm("vasp-username"));
|
mmsc_load_vasp_from_conf(m, gwlist_get(l, i), e, w);
|
||||||
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)
|
while ((x = gwlist_extract_first(e)) != NULL) {
|
||||||
mv->type = SOAP_VASP;
|
mms_error(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
|
||||||
else if (octstr_case_compare(s, octstr_imm("eaif")) == 0)
|
octstr_destroy(x);
|
||||||
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. */
|
while ((x = gwlist_extract_first(w)) != NULL) {
|
||||||
octstr_destroy(s);
|
mms_warning(0, "mmsc", NULL, "%s", octstr_get_cstr(x));
|
||||||
} else
|
octstr_destroy(x);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
gwlist_destroy(e, NULL);
|
||||||
if ((s = mms_cfg_get(cfg, grp, octstr_imm("send-uaprof"))) != NULL){
|
gwlist_destroy(w, 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(l, 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;
|
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 *mms_proxy_relays(mCfg *cfg, Octstr *myhostname)
|
||||||
{
|
{
|
||||||
List *gl = mms_cfg_get_multi(cfg, octstr_imm("mmsproxy"));
|
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(tmp3);
|
||||||
octstr_destroy(tmp4);
|
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 {
|
typedef struct MmsVasp {
|
||||||
Octstr *id;
|
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;
|
enum {SOAP_VASP, EAIF_VASP, NONE_VASP} type;
|
||||||
Octstr *vasp_username, *vasp_password;
|
Octstr *vasp_username, *vasp_password;
|
||||||
Octstr *vasp_url;
|
Octstr *vasp_url;
|
||||||
enum {UAProf_None, UAProf_URL, UAProf_UA} send_uaprof;
|
enum {UAProf_None, UAProf_URL, UAProf_UA} send_uaprof;
|
||||||
MM7Version_t ver;
|
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;
|
} MmsVasp;
|
||||||
|
|
||||||
typedef struct MmscSettings {
|
typedef struct MmscSettings {
|
||||||
|
@ -106,15 +115,26 @@ typedef struct MmscSettings {
|
||||||
Octstr *wap_gw_msisdn_header;
|
Octstr *wap_gw_msisdn_header;
|
||||||
Octstr *wap_gw_ip_header;
|
Octstr *wap_gw_ip_header;
|
||||||
|
|
||||||
List *vasp_list; /* of MmsVasp * */
|
Dict *vasp_list; /* of MmsVasp *, indexed by ID */
|
||||||
|
|
||||||
MmsVasp *mms2email, *mms2mobile;
|
|
||||||
|
|
||||||
|
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;
|
} MmscSettings;
|
||||||
|
|
||||||
/* Returns mmsc settings. */
|
/* 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. */
|
/* do final cleanup. */
|
||||||
void mms_cleanup_mmsc_settings(MmscSettings *settings);
|
void mms_cleanup_mmsc_settings(MmscSettings *settings);
|
||||||
/* Returns list of MmsProxyRelay */
|
/* 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 void strip_quotes(Octstr *s);
|
||||||
|
|
||||||
|
|
||||||
static mCfg *cfg;
|
|
||||||
static List *proxyrelays;
|
static List *proxyrelays;
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,24 +76,15 @@ int main(int argc, char *argv[])
|
||||||
else
|
else
|
||||||
fname = octstr_create(argv[cfidx]);
|
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, "----------------------------------------");
|
||||||
mms_info(0, "mmsfromemail", NULL, " MMSC Email2MMS/MM4 Incoming Tool version %s starting", MMSC_VERSION);
|
mms_info(0, "mmsfromemail", NULL, " MMSC Email2MMS/MM4 Incoming Tool version %s starting", MMSC_VERSION);
|
||||||
|
|
||||||
/* Load settings. */
|
/* Load settings. */
|
||||||
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
|
settings = mms_load_mmsc_settings(fname, &proxyrelays);
|
||||||
|
|
||||||
mms_cfg_destroy(cfg);
|
|
||||||
|
|
||||||
if (!settings)
|
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) {
|
if (!xto || !xfrom) {
|
||||||
mms_error(0, "mmsfromemail", NULL, "usage: %s -f from -t to!", argv[0]);
|
mms_error(0, "mmsfromemail", NULL, "usage: %s -f from -t to!", argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -52,12 +52,14 @@ static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId
|
||||||
List *qh,
|
List *qh,
|
||||||
MmsMsg *m, Octstr **error);
|
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 */
|
/* Send errors */
|
||||||
#define MMS_SEND_OK 0
|
#define MMS_SEND_OK 0
|
||||||
#define MMS_SEND_ERROR_TRANSIENT -1
|
#define MMS_SEND_ERROR_TRANSIENT -1
|
||||||
#define MMS_SEND_ERROR_FATAL -2
|
#define MMS_SEND_ERROR_FATAL -2
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NMAX 256
|
#define NMAX 256
|
||||||
static char qdir[NMAX];
|
static char qdir[NMAX];
|
||||||
|
@ -201,7 +203,8 @@ static int sendMsg(MmsEnvelope *e)
|
||||||
Octstr *mmsc;
|
Octstr *mmsc;
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
MmsVasp *vasp;
|
MmsVasp *vasp;
|
||||||
|
List *vlist;
|
||||||
|
|
||||||
/* If it is an IP, send to mobile handler, else if number, look for recipient. */
|
/* If it is an IP, send to mobile handler, else if number, look for recipient. */
|
||||||
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
|
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
|
||||||
phonenum = octstr_copy(to->rcpt, 0, j);
|
phonenum = octstr_copy(to->rcpt, 0, j);
|
||||||
|
@ -237,9 +240,10 @@ static int sendMsg(MmsEnvelope *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search VASP list, see what you can find... */
|
/* Search VASP list, see what you can find... */
|
||||||
for (j = 0, m = gwlist_len(settings->vasp_list); j < m; j++)
|
vlist = dict_keys(settings->vasp_list);
|
||||||
if ((vasp = gwlist_get(settings->vasp_list, j)) != NULL &&
|
for (j = 0, m = gwlist_len(vlist); j < m; j++)
|
||||||
_x_octstr_int_compare(vasp->short_code, phonenum) == 0) {
|
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,
|
res = mms_sendtovasp(vasp, e->from, to->rcpt,
|
||||||
e->msgId,
|
e->msgId,
|
||||||
e->hdrs,
|
e->hdrs,
|
||||||
|
@ -248,7 +252,8 @@ static int sendMsg(MmsEnvelope *e)
|
||||||
sent = 1;
|
sent = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
gwlist_destroy(vlist, (void *)octstr_destroy);
|
||||||
|
|
||||||
if (sent != 1) { /* Not yet, sent, find the receiver MMSC. */
|
if (sent != 1) { /* Not yet, sent, find the receiver MMSC. */
|
||||||
/* Normalise the number, then see if we can resolve home MMSC for this recipient. */
|
/* Normalise the number, then see if we can resolve home MMSC for this recipient. */
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -322,9 +327,12 @@ static int sendMsg(MmsEnvelope *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sent != 1) /* try mm7 delivery. Again. */
|
if (sent != 1) { /* try mm7 delivery. Again. */
|
||||||
for (j = 0, m = gwlist_len(settings->vasp_list); j < m; j++)
|
List *vlist = dict_keys(settings->vasp_list);
|
||||||
if ((vasp = gwlist_get(settings->vasp_list, j)) != NULL &&
|
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 &&
|
vasp->id &&
|
||||||
octstr_compare(vasp->id, mmsc) == 0) {
|
octstr_compare(vasp->id, mmsc) == 0) {
|
||||||
res = mms_sendtovasp(vasp, e->from, to->rcpt,
|
res = mms_sendtovasp(vasp, e->from, to->rcpt,
|
||||||
|
@ -335,6 +343,9 @@ static int sendMsg(MmsEnvelope *e)
|
||||||
sent = 1;
|
sent = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gwlist_destroy(vlist, (void *)octstr_destroy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
octstr_destroy(mmsc);
|
octstr_destroy(mmsc);
|
||||||
}
|
}
|
||||||
|
@ -390,12 +401,19 @@ static int sendMsg(MmsEnvelope *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write to log */
|
/* 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)
|
||||||
SEND_ERROR_STR(res),
|
mms_error(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: %s",
|
||||||
e->xqfname,
|
SEND_ERROR_STR(res),
|
||||||
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
|
e->xqfname,
|
||||||
err ? octstr_get_cstr(err) : "(null)");
|
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 &&
|
if (res == MMS_SEND_OK &&
|
||||||
(e->msgtype == MMS_MSGTYPE_SEND_REQ ||
|
(e->msgtype == MMS_MSGTYPE_SEND_REQ ||
|
||||||
e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF)) { /* Do CDR writing. */
|
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,
|
static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
|
||||||
List *qh,
|
List *qh,
|
||||||
MmsMsg *m, Octstr **error)
|
MmsMsg *m, Octstr **error, int *got_conn_error)
|
||||||
{
|
{
|
||||||
int ret = MMS_SEND_ERROR_TRANSIENT;
|
int ret = MMS_SEND_ERROR_TRANSIENT;
|
||||||
int mtype = mms_messagetype(m);
|
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);
|
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) {
|
if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
|
||||||
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d!",
|
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d!",
|
||||||
octstr_get_cstr(vasp->vasp_url), hstatus);
|
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,
|
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 ret = MMS_SEND_ERROR_TRANSIENT;
|
||||||
int mtype = mms_messagetype(m);
|
int mtype = mms_messagetype(m);
|
||||||
|
@ -745,9 +763,10 @@ static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
|
||||||
} else
|
} else
|
||||||
mms_info(0, "MM7", vasp->id, "Sent to VASP[%s], code=[%d]", octstr_get_cstr(vasp->id), hstatus);
|
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;
|
ret = MMS_SEND_ERROR_TRANSIENT;
|
||||||
else {
|
*got_conn_error = (hstatus < 0);
|
||||||
|
} else {
|
||||||
hstatus = http_status_class(hstatus);
|
hstatus = http_status_class(hstatus);
|
||||||
if (hstatus == HTTP_STATUS_CLIENT_ERROR)
|
if (hstatus == HTTP_STATUS_CLIENT_ERROR)
|
||||||
ret = MMS_SEND_ERROR_TRANSIENT;
|
ret = MMS_SEND_ERROR_TRANSIENT;
|
||||||
|
@ -771,16 +790,36 @@ static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid
|
||||||
List *qh,
|
List *qh,
|
||||||
MmsMsg *m, Octstr **err)
|
MmsMsg *m, Octstr **err)
|
||||||
{
|
{
|
||||||
|
int ret, conn_err = 0;
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
*err = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
|
*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)
|
} 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)
|
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 {
|
else {
|
||||||
mms_error(0, "MM7", vasp->id, "Vasp[%s] of unknown type, can't send!",
|
mms_error(0, "MM7", vasp->id, "Vasp[%s] of unknown type, can't send!",
|
||||||
vasp->id ? octstr_get_cstr(vasp->id) : "");
|
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. */
|
/* 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 *v = http_header_value(headers, octstr_imm("Authorization"));
|
||||||
Octstr *p = NULL, *q = NULL;
|
Octstr *p = NULL, *q = NULL, *x;
|
||||||
MmsVasp *m = NULL;
|
MmsVasp *m = NULL;
|
||||||
int i, n;
|
List *vlist;
|
||||||
|
int i;
|
||||||
|
|
||||||
#if 0
|
*has_auth = (v != NULL);
|
||||||
return gwlist_get(vasps,0); /* XXX for testing... */
|
|
||||||
#endif
|
|
||||||
if (!v ||
|
if (!v ||
|
||||||
octstr_search(v, octstr_imm("Basic "), 0) != 0)
|
octstr_search(v, octstr_imm("Basic "), 0) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1496,15 +1496,20 @@ static MmsVasp *find_mm7sender(List *headers, List *vasps)
|
||||||
octstr_delete(p, i, octstr_len(p));
|
octstr_delete(p, i, octstr_len(p));
|
||||||
|
|
||||||
/* p = user, q = pass. */
|
/* p = user, q = pass. */
|
||||||
for (i = 0, n = gwlist_len(vasps); i<n; i++) {
|
vlist = dict_keys(vasps);
|
||||||
MmsVasp *x = gwlist_get(vasps, i);
|
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) {
|
octstr_destroy(x);
|
||||||
m = x;
|
|
||||||
|
if (mv &&
|
||||||
|
octstr_compare(mv->vasp_username, p) == 0 &&
|
||||||
|
octstr_compare(mv->vasp_password, q) == 0) {
|
||||||
|
m = mv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
gwlist_destroy(vlist, NULL);
|
||||||
|
|
||||||
/* if it can't authenticate, returns 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] <-- ",
|
" --> Enterred mm7dispatch interface, mreq=[%s] mtype=[%s] <-- ",
|
||||||
mreq ? "Ok" : "Null",
|
mreq ? "Ok" : "Null",
|
||||||
mreq ? (char *)msgtype : "Null");
|
mreq ? (char *)msgtype : "Null");
|
||||||
|
|
||||||
if (!mreq) {
|
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;
|
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)) {
|
switch (mm7_msgtype(mreq)) {
|
||||||
case MM7_TAG_SubmitReq:
|
case MM7_TAG_SubmitReq:
|
||||||
mm7_get_envelope(mreq, &from, &to, &subject, &vasid, &expiryt, &delivert, NULL, NULL);
|
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);
|
mresp = mm7_make_resp(mreq, status, NULL,0);
|
||||||
break;
|
break;
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
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)
|
if (mresp && mm7_soapmsg_to_httpmsg(mresp, &h->vasp->ver, &rh, &reply_body) == 0)
|
||||||
http_send_reply(h->client, hstatus, rh, reply_body);
|
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)
|
static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
|
||||||
{
|
{
|
||||||
/* if no vasp, return 4001 error. */
|
|
||||||
MmsMsg *m = NULL;
|
MmsMsg *m = NULL;
|
||||||
List *mh = NULL;
|
List *mh = NULL;
|
||||||
int hstatus = HTTP_NO_CONTENT;
|
int hstatus = HTTP_NO_CONTENT;
|
||||||
|
@ -1749,6 +1760,9 @@ static void mm7eaif_dispatch(MmsHTTPClientInfo *h)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h->vasp->stats.mo_pdus++;
|
||||||
|
h->vasp->stats.last_pdu = time(NULL);
|
||||||
|
|
||||||
mms_remove_headers(m, "Message-ID");
|
mms_remove_headers(m, "Message-ID");
|
||||||
mh = mms_message_headers(m);
|
mh = mms_message_headers(m);
|
||||||
/* Now get sender and receiver data.
|
/* 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(""));
|
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);
|
http_destroy_headers(hto);
|
||||||
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
|
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
|
||||||
octstr_destroy(hfrom);
|
octstr_destroy(hfrom);
|
||||||
|
@ -1858,15 +1875,16 @@ static void mm7proxy(void *unused)
|
||||||
&h.body, &h.cgivars)) != NULL)
|
&h.body, &h.cgivars)) != NULL)
|
||||||
if (is_allowed_ip(settings->allow_ip, settings->deny_ip, h.ip)) {
|
if (is_allowed_ip(settings->allow_ip, settings->deny_ip, h.ip)) {
|
||||||
MmsHTTPClientInfo *hx = gw_malloc(sizeof *hx);
|
MmsHTTPClientInfo *hx = gw_malloc(sizeof *hx);
|
||||||
|
int has_auth = 0;
|
||||||
|
double tdur;
|
||||||
|
|
||||||
|
|
||||||
/* Clear some stuff. */
|
/* Clear some stuff. */
|
||||||
h.client_addr = NULL;
|
h.client_addr = NULL;
|
||||||
h.base_client_addr = NULL;
|
h.base_client_addr = NULL;
|
||||||
h.profile_url = NULL;
|
h.profile_url = NULL;
|
||||||
|
|
||||||
/* Get the MM7 sender address. */
|
/* 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"));
|
h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
|
||||||
debug("mmsproxy", 0,
|
debug("mmsproxy", 0,
|
||||||
" MM7 Request, ip=%s, vasp=%s ",
|
" MM7 Request, ip=%s, vasp=%s ",
|
||||||
|
@ -1888,7 +1906,21 @@ static void mm7proxy(void *unused)
|
||||||
octstr_imm(""));
|
octstr_imm(""));
|
||||||
http_destroy_headers(hh);
|
http_destroy_headers(hh);
|
||||||
free_clientInfo(hx, 1);
|
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)
|
} else if (h.vasp->type == SOAP_VASP)
|
||||||
gwthread_create((gwthread_func_t *)mm7soap_dispatch, hx);
|
gwthread_create((gwthread_func_t *)mm7soap_dispatch, hx);
|
||||||
else
|
else
|
||||||
|
|
|
@ -57,7 +57,6 @@ static int find_own(int i, int argc, char *argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mCfg *cfg;
|
|
||||||
static MmscSettings *settings;
|
static MmscSettings *settings;
|
||||||
static List *proxyrelays;
|
static List *proxyrelays;
|
||||||
static MmsMsg *m;
|
static MmsMsg *m;
|
||||||
|
@ -84,25 +83,17 @@ int main(int argc, char *argv[])
|
||||||
else
|
else
|
||||||
fname = octstr_create(argv[cfidx]);
|
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, "----------------------------------------");
|
||||||
mms_info(0, "mmssend", NULL, " MMSC Message sender runner version %s starting", MMSC_VERSION);
|
mms_info(0, "mmssend", NULL, " MMSC Message sender runner version %s starting", MMSC_VERSION);
|
||||||
|
|
||||||
|
|
||||||
/* Load settings. */
|
/* Load settings. */
|
||||||
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
|
settings = mms_load_mmsc_settings(fname, &proxyrelays);
|
||||||
|
|
||||||
mms_cfg_destroy(cfg);
|
|
||||||
|
|
||||||
if (!settings)
|
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 ||
|
if (from == NULL ||
|
||||||
to == NULL) {
|
to == NULL) {
|
||||||
mms_error(0, "mmssend", NULL, "Sender and recipient addresses required!\n");
|
mms_error(0, "mmssend", NULL, "Sender and recipient addresses required!\n");
|
||||||
|
|
Loading…
Reference in New Issue