Added admin interface for mmsbox
This commit is contained in:
parent
30d9e2c0d4
commit
1a3aa4c9aa
|
@ -1,3 +1,5 @@
|
|||
2008-09-02 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||
* Added admin interface to mmsbox (can now start/stop and see status of any mmsc connection)
|
||||
2008-09-01 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||
* Rolled mmsrelay + mmsproxy into one item (for easier online management)
|
||||
2008-08-29 P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||
|
|
|
@ -100,6 +100,14 @@ SINGLE_GROUP(mbuni,
|
|||
|
||||
OCTSTR(mmsbox-mt-filter-library)
|
||||
OCTSTR(mmsbox-mt-always-multipart)
|
||||
|
||||
OCTSTR(mmsbox-admin-port)
|
||||
OCTSTR(mmsc-admin-port)
|
||||
OCTSTR(admin-port-ssl)
|
||||
OCTSTR(admin-password)
|
||||
|
||||
OCTSTR(admin-allow-ip)
|
||||
OCTSTR(admin-deny-ip)
|
||||
)
|
||||
|
||||
MULTI_GROUP(mmsproxy,
|
||||
|
|
|
@ -140,7 +140,7 @@ int mmsbox_send_report(Octstr *from, char *report_type,
|
|||
}
|
||||
|
||||
/* These functions are very similar to those in mmsproxy */
|
||||
static void mm7soap_receive(MmsBoxHTTPClientInfo *h)
|
||||
static int mm7soap_receive(MmsBoxHTTPClientInfo *h)
|
||||
{
|
||||
|
||||
MSoapMsg_t *mreq = NULL, *mresp = NULL;
|
||||
|
@ -167,6 +167,7 @@ static void mm7soap_receive(MmsBoxHTTPClientInfo *h)
|
|||
|
||||
if (!mreq) {
|
||||
mresp = mm7_make_resp(NULL, MM7_SOAP_FORMAT_CORRUPT, NULL,1);
|
||||
status = 4000;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -315,6 +316,7 @@ static void mm7soap_receive(MmsBoxHTTPClientInfo *h)
|
|||
|
||||
default:
|
||||
mresp = mm7_make_resp(mreq, MM7_SOAP_UNSUPPORTED_OPERATION, NULL,1);
|
||||
status = MM7_SOAP_UNSUPPORTED_OPERATION;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -342,9 +344,11 @@ static void mm7soap_receive(MmsBoxHTTPClientInfo *h)
|
|||
mm7_soap_destroy(mreq);
|
||||
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
octstr_destroy(mmc_id);
|
||||
|
||||
return MM7_SOAP_STATUS_OK(status) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void mm7eaif_receive(MmsBoxHTTPClientInfo *h)
|
||||
static int mm7eaif_receive(MmsBoxHTTPClientInfo *h)
|
||||
{
|
||||
MmsMsg *m = NULL;
|
||||
List *mh = NULL;
|
||||
|
@ -547,7 +551,9 @@ static void mm7eaif_receive(MmsBoxHTTPClientInfo *h)
|
|||
octstr_destroy(mmc_id);
|
||||
|
||||
http_destroy_headers(mh);
|
||||
mms_destroy(m);
|
||||
mms_destroy(m);
|
||||
|
||||
return http_status_class(hstatus) == HTTP_STATUS_SUCCESSFUL ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -557,6 +563,7 @@ static void dispatch_mm7_recv(List *rl)
|
|||
MmsBoxHTTPClientInfo *h;
|
||||
|
||||
while ((h = gwlist_consume(rl)) != NULL) {
|
||||
int ret = -1;
|
||||
MmscGrp *m = h->m;
|
||||
if (auth_check(m->incoming.user,
|
||||
m->incoming.pass,
|
||||
|
@ -570,10 +577,16 @@ static void dispatch_mm7_recv(List *rl)
|
|||
info(0, "MMSBox: Auth failed, incoming connection, MMC group=[%s]",
|
||||
m->id ? octstr_get_cstr(m->id) : "(none)");
|
||||
} else if (h->m->type == SOAP_MMSC)
|
||||
mm7soap_receive(h);
|
||||
ret = mm7soap_receive(h);
|
||||
else
|
||||
mm7eaif_receive(h);
|
||||
ret = mm7eaif_receive(h);
|
||||
|
||||
h->m->last_pdu = time(NULL);
|
||||
|
||||
if (ret == 0)
|
||||
h->m->mo_pdus++;
|
||||
else
|
||||
h->m->mo_errors++;
|
||||
free_mmsbox_http_clientInfo(h, 1);
|
||||
}
|
||||
}
|
||||
|
@ -583,11 +596,12 @@ void mmsc_receive_func(MmscGrp *m)
|
|||
int i;
|
||||
MmsBoxHTTPClientInfo h = {NULL};
|
||||
List *mmsc_incoming_reqs = gwlist_create();
|
||||
long *thids = gw_malloc((maxthreads + 1)*sizeof thids[0]);
|
||||
|
||||
gwlist_add_producer(mmsc_incoming_reqs);
|
||||
|
||||
for (i = 0; i<maxthreads; i++)
|
||||
gwthread_create((gwthread_func_t *)dispatch_mm7_recv, mmsc_incoming_reqs);
|
||||
thids[i] = gwthread_create((gwthread_func_t *)dispatch_mm7_recv, mmsc_incoming_reqs);
|
||||
|
||||
h.m = m;
|
||||
while(rstop == 0 &&
|
||||
|
@ -628,12 +642,17 @@ void mmsc_receive_func(MmscGrp *m)
|
|||
free_mmsbox_http_clientInfo(&h, 0);
|
||||
}
|
||||
|
||||
debug("proxy", 0, "MMSBox: MM7 receiver Shutting down...");
|
||||
debug("proxy", 0, "MMSBox: MM7 receiver [mmc=%s] Shutting down...", octstr_get_cstr(m->id));
|
||||
gwlist_remove_producer(mmsc_incoming_reqs);
|
||||
gwthread_join_every((void *)dispatch_mm7_recv);
|
||||
gwlist_destroy(mmsc_incoming_reqs, NULL);
|
||||
|
||||
debug("proxy", 0, "MMSBox: MM7 receiver Shutting down complete.");
|
||||
for (i = 0; i<maxthreads; i++)
|
||||
if (thids[i] >= 0)
|
||||
gwthread_join(thids[i]);
|
||||
|
||||
gwlist_destroy(mmsc_incoming_reqs, NULL);
|
||||
gw_free(thids);
|
||||
|
||||
debug("proxy", 0, "MMSBox: MM7 receiver [mmc=%s] Shutting down complete.", octstr_get_cstr(m->id));
|
||||
}
|
||||
|
||||
|
||||
|
@ -984,7 +1003,11 @@ static int sendMsg(MmsEnvelope *e)
|
|||
e->hdrs,
|
||||
&new_msgid,
|
||||
&err);
|
||||
|
||||
if (res == MMS_SEND_OK)
|
||||
mmc->mt_pdus++;
|
||||
else
|
||||
mmc->mt_errors++;
|
||||
mmc->last_pdu = time(NULL);
|
||||
return_mmsc_conn(mmc); /* important. */
|
||||
done:
|
||||
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
|
||||
|
|
|
@ -574,7 +574,6 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
Octstr *fname;
|
||||
int cfidx;
|
||||
mCfg *cfg;
|
||||
|
||||
long qthread = 0, sthread = 0;
|
||||
|
||||
|
@ -588,11 +587,9 @@ int main(int argc, char *argv[])
|
|||
fname = octstr_imm("mbuni.conf");
|
||||
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));
|
||||
if (mms_load_mmsbox_settings(fname,(gwthread_func_t *)mmsc_receive_func) < 0)
|
||||
panic(0, "Configuration file loading failed, file: %s", octstr_get_cstr(fname));
|
||||
|
||||
octstr_destroy(fname);
|
||||
|
||||
|
@ -600,10 +597,6 @@ int main(int argc, char *argv[])
|
|||
info(0, " " MM_NAME " MMSBox version %s starting", MMSC_VERSION);
|
||||
|
||||
|
||||
mms_load_mmsbox_settings(cfg,(gwthread_func_t *)mmsc_receive_func);
|
||||
|
||||
mms_cfg_destroy(cfg);
|
||||
|
||||
signal(SIGHUP, relog_now);
|
||||
signal(SIGTERM, quit_now);
|
||||
signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/
|
||||
|
@ -622,7 +615,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
info(0, "Shutdown started..");
|
||||
|
||||
mmsbox_cleanup_settings();
|
||||
sleep(2);
|
||||
/* Wait for the sender thread, then quit. */
|
||||
gwthread_join(qthread); /* Wait for it to die... */
|
||||
|
|
|
@ -43,30 +43,51 @@ MmsBoxResolverFuncStruct *rfs; /* resolver functions. */
|
|||
void *rfs_data;
|
||||
Octstr *rfs_settings;
|
||||
|
||||
|
||||
static mCfg *cfg; /* Config. */
|
||||
static Dict *mmscs = NULL; /* MMSC's indexed by ID. */
|
||||
static List *mmsc_del_list = NULL; /* List of items to be deleted. */
|
||||
|
||||
|
||||
/* admin handler variables. */
|
||||
static long admin_port;
|
||||
static long admin_thread = -1;
|
||||
static Octstr *admin_pass = NULL;
|
||||
static Octstr *admin_allow_ip = NULL;
|
||||
static Octstr *admin_deny_ip = NULL;
|
||||
|
||||
static gwthread_func_t *mmsc_receiver_func;
|
||||
|
||||
struct SendMmsPortInfo sendmms_port;
|
||||
|
||||
struct MmsBoxMTfilter *mt_filter = NULL;
|
||||
|
||||
static void free_mmsc_struct (MmscGrp *m);
|
||||
static void mmsbox_start_mmsc_conn(MmscGrp *m, gwthread_func_t *mmsc_handler_func);
|
||||
static void mmsbox_stop_mmsc_conn_real(MmscGrp *mmc);
|
||||
int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
|
||||
|
||||
static void admin_handler(void *unused);
|
||||
|
||||
int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func)
|
||||
{
|
||||
mCfgGrp *grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
|
||||
mCfgGrp *cgrp = mms_cfg_get_single(cfg, octstr_imm("core"));
|
||||
mCfgGrp *grp;
|
||||
mCfgGrp *cgrp;
|
||||
Octstr *gdir = NULL, *s;
|
||||
|
||||
int send_port_ssl = 0;
|
||||
int send_port_ssl = 0, admin_port_ssl = 0;
|
||||
List *l;
|
||||
int i, n, xx;
|
||||
void *catchall = NULL;
|
||||
|
||||
if (grp == NULL)
|
||||
panic(0,"Missing required group `mbuni' in config file!");
|
||||
|
||||
if ((cfg = mms_cfg_read(fname)) == NULL) {
|
||||
error(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
|
||||
return -1;
|
||||
}
|
||||
|
||||
grp = mms_cfg_get_single(cfg, octstr_imm("mbuni"));
|
||||
cgrp = mms_cfg_get_single(cfg, octstr_imm("core"));
|
||||
|
||||
if (grp == NULL) {
|
||||
error(0,"Missing required group `mbuni' in config file!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mms_load_core_settings(cfg, cgrp);
|
||||
|
||||
|
@ -201,10 +222,29 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
|
|||
}
|
||||
gwlist_destroy(l, NULL);
|
||||
|
||||
/* Get mmsc list. */
|
||||
mmsc_receiver_func = mmsc_handler_func; /* save it. */
|
||||
|
||||
/* Start MMSCs. */
|
||||
l = mms_cfg_get_multi(cfg, octstr_imm("mmsc"));
|
||||
for (i = 0, n = gwlist_len(l); i < n; i++)
|
||||
start_mmsc_from_conf(cfg, gwlist_get(l, i), mmsc_handler_func);
|
||||
for (i = 0, n = gwlist_len(l); i < n; i++) {
|
||||
List *errors = gwlist_create();
|
||||
List *warnings = gwlist_create();
|
||||
Octstr *x;
|
||||
|
||||
start_mmsc_from_conf(cfg, gwlist_get(l, i), mmsc_handler_func, errors, warnings);
|
||||
|
||||
while ((x = gwlist_extract_first(errors)) != NULL) {
|
||||
error(0, "%s", octstr_get_cstr(x));
|
||||
octstr_destroy(x);
|
||||
}
|
||||
|
||||
while ((x = gwlist_extract_first(warnings)) != NULL) {
|
||||
warning(0, "%s", octstr_get_cstr(x));
|
||||
octstr_destroy(x);
|
||||
}
|
||||
gwlist_destroy(errors, NULL);
|
||||
gwlist_destroy(warnings, NULL);
|
||||
}
|
||||
|
||||
gwlist_destroy(l, NULL);
|
||||
|
||||
|
@ -348,13 +388,37 @@ int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func)
|
|||
|
||||
gwlist_append(mms_services, m);
|
||||
}
|
||||
|
||||
/* Finally load admin-port config and start the thingie */
|
||||
|
||||
mms_cfg_get_int(cfg, grp, octstr_imm("mmsbox-admin-port"), &admin_port);
|
||||
#ifdef HAVE_LIBSSL
|
||||
mms_cfg_get_bool(cfg, grp, octstr_imm("admin-port-ssl"), &admin_port_ssl);
|
||||
#endif
|
||||
admin_pass = mms_cfg_get(cfg, grp, octstr_imm("admin-password"));
|
||||
|
||||
admin_allow_ip = mms_cfg_get(cfg, grp, octstr_imm("admin-allow-ip"));
|
||||
admin_deny_ip = mms_cfg_get(cfg, grp, octstr_imm("admin-deny-ip"));
|
||||
|
||||
if (admin_port > 0 &&
|
||||
http_open_port(admin_port, admin_port_ssl)< 0)
|
||||
error(0, "Failed to start admin server on port %d: %s",
|
||||
(int)admin_port, strerror(errno));
|
||||
else if (admin_port > 0 &&
|
||||
(admin_thread = gwthread_create((gwthread_func_t *)admin_handler, NULL)) < 0) {
|
||||
error(0, "Failed to start admin server thread: %s",
|
||||
strerror(errno));
|
||||
http_close_port(admin_port);
|
||||
} else if (admin_pass == NULL)
|
||||
warning(0, "Empty or no password supplied for admin port. All requests will be allowed!");
|
||||
|
||||
gwlist_destroy(l, NULL);
|
||||
octstr_destroy(gdir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do nothing func. */
|
||||
/* do nothing func: Vital it returns 0! */
|
||||
static int do_nothing_func (void) {return 0;}
|
||||
|
||||
static MmsBoxMmscFuncs dummy_mmsc_funcs = {
|
||||
|
@ -363,7 +427,62 @@ static MmsBoxMmscFuncs dummy_mmsc_funcs = {
|
|||
(void *)do_nothing_func
|
||||
};
|
||||
|
||||
void start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_func)
|
||||
#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)
|
||||
|
||||
|
||||
|
||||
static void mmsbox_stop_mmsc_conn_real(MmscGrp *mmc)
|
||||
{
|
||||
|
||||
if (mmc->type == CUSTOM_MMSC && mmc->fns
|
||||
&& mmc->custom_started) {
|
||||
mmc->fns->stop_conn(mmc->data);
|
||||
mmc->custom_started = 0;
|
||||
} else if (mmc->incoming.port > 0) {
|
||||
http_close_port(mmc->incoming.port);
|
||||
if (mmc->threadid >= 0)
|
||||
gwthread_join(mmc->threadid);
|
||||
mmc->threadid = -1;
|
||||
}
|
||||
info(0, "Shutdown for mmsc [%s] complete", octstr_get_cstr(mmc->id));
|
||||
}
|
||||
|
||||
|
||||
static void mmsbox_start_mmsc_conn(MmscGrp *m, gwthread_func_t *mmsc_handler_func,
|
||||
List *errors, List *warnings)
|
||||
{
|
||||
if (m->type == CUSTOM_MMSC) {
|
||||
if (m->fns->start_conn(m, qfs, unified_prefix, strip_prefixes, &m->data) != 0) {
|
||||
WARNING("MMSBox: Failed to start custom MMSC [%s]", octstr_get_cstr(m->id));
|
||||
m->custom_started = 0;
|
||||
} else
|
||||
m->custom_started = 1;
|
||||
} else {
|
||||
if (m->incoming.port > 0 &&
|
||||
http_open_port(m->incoming.port, m->incoming.ssl) < 0) {
|
||||
WARNING("MMSBox: Failed to start HTTP server on receive port for "
|
||||
" MMSC %s, port %ld: %s!",
|
||||
octstr_get_cstr(m->id), m->incoming.port,
|
||||
strerror(errno));
|
||||
m->incoming.port = 0; /* so we don't listen on it. */
|
||||
}
|
||||
|
||||
if (mmsc_handler_func && m->incoming.port > 0) { /* Only start threads if func passed and ... */
|
||||
if ((m->threadid = gwthread_create(mmsc_handler_func, m)) < 0)
|
||||
ERROR("MMSBox: Failed to start MMSC handler thread for MMSC[%s]: %s!",
|
||||
octstr_get_cstr(m->id), strerror(errno));
|
||||
} else
|
||||
m->threadid = -1;
|
||||
}
|
||||
|
||||
info(0, "Startup for mmsc [%s] complete", octstr_get_cstr(m->id));
|
||||
}
|
||||
|
||||
|
||||
|
||||
MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_func,
|
||||
List *warnings, List *errors)
|
||||
{
|
||||
|
||||
MmscGrp *m = gw_malloc(sizeof *m);
|
||||
|
@ -373,14 +492,14 @@ void start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_f
|
|||
Octstr *s;
|
||||
|
||||
memset(m, 0, sizeof *m);
|
||||
|
||||
|
||||
m->id = _mms_cfg_getx(cfg, x, octstr_imm("id"));
|
||||
if (octstr_len(m->id) < 1) {
|
||||
error(0,"mmsbox.mmsc_config: Missing required field value `id' in config file!");
|
||||
ERROR("mmsbox.mmsc_config: Missing required field value `id' in config file!");
|
||||
octstr_destroy(m->id);
|
||||
gw_free(m);
|
||||
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m->group_id = mms_cfg_get(cfg, x, octstr_imm("group-id"));
|
||||
|
@ -432,7 +551,7 @@ void start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_f
|
|||
m->fns = &dummy_mmsc_funcs;
|
||||
}
|
||||
} else
|
||||
warning(0, "MMSBox: Unknown MMSC type [%s]!",
|
||||
WARNING("MMSBox: Unknown MMSC type [%s]!",
|
||||
octstr_get_cstr(type));
|
||||
if ((xver = _mms_cfg_getx(cfg, x, octstr_imm("mm7-version"))) != NULL &&
|
||||
octstr_len(xver) > 0)
|
||||
|
@ -468,11 +587,11 @@ void start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_f
|
|||
if (mt_filter)
|
||||
m->use_mt_filter = (mt_filter->init(m->mmsc_url, m->id, s) == 1);
|
||||
else
|
||||
panic(0, "MMSBox: mt-filter-params set for MMSC[%s] but no MT-filter lib "
|
||||
ERROR("MMSBox: mt-filter-params set for MMSC[%s] but no MT-filter lib "
|
||||
"specified!",
|
||||
octstr_get_cstr(m->id));
|
||||
if (!m->use_mt_filter)
|
||||
warning(0, "MMSBox: MT MMS filter turned off for MMSC[%s]. Init failed",
|
||||
WARNING( "MMSBox: MT MMS filter turned off for MMSC[%s]. Init failed",
|
||||
octstr_get_cstr(m->id));
|
||||
octstr_destroy(s);
|
||||
} else
|
||||
|
@ -482,77 +601,38 @@ void start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_f
|
|||
mms_cfg_get_bool(cfg, x, octstr_imm("reroute-add-sender-to-subject"), &m->reroute_mod_subject);
|
||||
m->reroute_mmsc_id = mms_cfg_get(cfg, x, octstr_imm("reroute-mmsc-id"));
|
||||
if (m->reroute_mmsc_id != NULL && m->reroute == 0)
|
||||
warning(0, "MMSBox: reroute-mmsc-id parameter set but reroute=false!");
|
||||
WARNING("MMSBox: reroute-mmsc-id parameter set but reroute=false!");
|
||||
|
||||
mms_cfg_get_bool(cfg, x, octstr_imm("no-sender-address"), &m->no_senderaddress);
|
||||
m->mutex = mutex_create();
|
||||
m->incoming.ssl = ssl;
|
||||
|
||||
m->start_time = time(NULL);
|
||||
|
||||
/* finally start the thingie. */
|
||||
mmsbox_start_mmsc_conn(m, mmsc_handler_func);
|
||||
mmsbox_start_mmsc_conn(m, mmsc_handler_func, errors, warnings);
|
||||
if (dict_put_once(mmscs, m->id, m) == 0) {
|
||||
error(0, "Failed to load mmsc <%s>. ID is not unique!", octstr_get_cstr(m->id));
|
||||
WARNING("Failed to load mmsc <%s>. ID is not unique!", octstr_get_cstr(m->id));
|
||||
mmsbox_stop_mmsc_conn_real(m);
|
||||
free_mmsc_struct(m);
|
||||
}
|
||||
}
|
||||
|
||||
static void mmsbox_start_mmsc_conn(MmscGrp *m, gwthread_func_t *mmsc_handler_func)
|
||||
{
|
||||
if (m->type == CUSTOM_MMSC) {
|
||||
if (m->fns->start_conn(m, qfs, unified_prefix, strip_prefixes, &m->data) != 0) {
|
||||
warning(0, "MMSBox: Failed to start custom MMSC [%s]", octstr_get_cstr(m->id));
|
||||
m->custom_started = 0;
|
||||
} else
|
||||
m->custom_started = 1;
|
||||
} else {
|
||||
if (m->incoming.port > 0 &&
|
||||
http_open_port(m->incoming.port, m->incoming.ssl) < 0) {
|
||||
warning(0, "MMSBox: Failed to start HTTP server on receive port for "
|
||||
" MMSC %s, port %ld: %s!",
|
||||
octstr_get_cstr(m->id), m->incoming.port,
|
||||
strerror(errno));
|
||||
m->incoming.port = 0; /* so we don't listen on it. */
|
||||
}
|
||||
|
||||
if (mmsc_handler_func && m->incoming.port > 0) { /* Only start threads if func passed and ... */
|
||||
if ((m->threadid = gwthread_create(mmsc_handler_func, m)) < 0)
|
||||
error(0, "MMSBox: Failed to start MMSC handler thread for MMSC[%s]: %s!",
|
||||
octstr_get_cstr(m->id), strerror(errno));
|
||||
} else
|
||||
m->threadid = -1;
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
info(0, "Startup for mmsc [%s] complete", octstr_get_cstr(m->id));
|
||||
return m;
|
||||
}
|
||||
|
||||
static void mmsbox_stop_mmsc_conn_real(MmscGrp *mmc)
|
||||
{
|
||||
|
||||
if (mmc->type == CUSTOM_MMSC && mmc->fns
|
||||
&& mmc->custom_started) {
|
||||
mmc->fns->stop_conn(mmc->data);
|
||||
mmc->custom_started = 0;
|
||||
} else if (mmc->incoming.port > 0) {
|
||||
http_close_port(mmc->incoming.port);
|
||||
if (mmc->threadid >= 0)
|
||||
gwthread_join(mmc->threadid);
|
||||
mmc->threadid = -1;
|
||||
}
|
||||
info(0, "Shutdown for mmsc [%s] complete", octstr_get_cstr(mmc->id));
|
||||
}
|
||||
|
||||
void 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. */
|
||||
|
||||
if (mmc == NULL)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
mmsbox_stop_mmsc_conn_real(mmc);
|
||||
|
||||
mmc->delete_after = time(NULL) + 5*60; /* delete after 5 minutes. */
|
||||
gwlist_append(mmsc_del_list, mmc); /* to be deleted later. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mmsbox_stop_all_mmsc_conn(void)
|
||||
|
@ -663,6 +743,18 @@ void mmsbox_settings_cleanup(void)
|
|||
{
|
||||
delete_stale_mmsc(1);
|
||||
|
||||
/* eventually we will destroy the object. For now, we only cleanup queue module. */
|
||||
if (qfs)
|
||||
qfs->mms_cleanup_queue_module();
|
||||
|
||||
if (admin_port > 0) {
|
||||
http_close_port(admin_port);
|
||||
gwthread_join(admin_thread);
|
||||
info(0, "MmsBox: Admin port on %d, shutdown", (int)admin_port);
|
||||
}
|
||||
|
||||
|
||||
mms_cfg_destroy(cfg); /* only delete at end of session. */
|
||||
/* More cleanups to follow. */
|
||||
}
|
||||
|
||||
|
@ -736,11 +828,223 @@ Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mmsbox_cleanup_settings(void)
|
||||
static void append_mmsc_status(Octstr *rbody, MmscGrp *m, List *warnings)
|
||||
{
|
||||
/* eventually we will destroy the object. For now, we only cleanup queue module. */
|
||||
if (qfs)
|
||||
qfs->mms_cleanup_queue_module();
|
||||
time_t t = time(NULL);
|
||||
int i, n;
|
||||
unsigned long tdiff;
|
||||
char lbuf[128], ubuf[128], tmp[64], xport[32];
|
||||
|
||||
char *typ;
|
||||
|
||||
if (m->type == SOAP_MMSC)
|
||||
typ = "SOAP";
|
||||
else if (m->type == EAIF_MMSC)
|
||||
typ = "EAIF";
|
||||
else if (m->type == CUSTOM_MMSC)
|
||||
typ = "CUSTOM";
|
||||
else
|
||||
typ = "none";
|
||||
|
||||
if (m->last_pdu > 0) {
|
||||
struct tm tm = gw_localtime(m->last_pdu);
|
||||
gw_strftime(lbuf,sizeof lbuf, "%x %X", &tm);
|
||||
} else
|
||||
strcpy(lbuf, "n/a");
|
||||
|
||||
/* Compute uptime */
|
||||
tdiff = t - m->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->type != CUSTOM_MMSC)
|
||||
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",
|
||||
m->id,
|
||||
typ,
|
||||
xport,
|
||||
m->group_id ? m->group_id : octstr_imm("n/a"),
|
||||
m->throughput,
|
||||
m->reroute ? "true" : "false",
|
||||
m->reroute_mmsc_id ? m->reroute_mmsc_id : octstr_imm("N/A"),
|
||||
ubuf,
|
||||
lbuf,
|
||||
(long)m->mt_pdus, (long)m->mt_errors,
|
||||
(long)m->mo_pdus, (long)m->mo_errors);
|
||||
|
||||
|
||||
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, "</Mmsc>\n");
|
||||
}
|
||||
|
||||
static void admin_handler(void *unused)
|
||||
{
|
||||
HTTPClient *client;
|
||||
Octstr *ip;
|
||||
List *headers;
|
||||
Octstr *url;
|
||||
Octstr *body;
|
||||
List *cgivars;
|
||||
Octstr *pass;
|
||||
Octstr *cmd;
|
||||
|
||||
|
||||
info(0, "MmsBox: Admin Interface -- startup on port %d", (int)admin_port);
|
||||
|
||||
while((client = http_accept_request(admin_port,
|
||||
&ip, &url, &headers,
|
||||
&body, &cgivars)) != NULL) {
|
||||
int flg = -1;
|
||||
Octstr *rbody = NULL;
|
||||
int rstatus = HTTP_OK;
|
||||
|
||||
if (!(flg = is_allowed_ip(admin_allow_ip, admin_deny_ip, ip)) ||
|
||||
((pass = http_cgi_variable(cgivars, "password")) == NULL && admin_pass != NULL) ||
|
||||
(admin_pass && octstr_compare(pass, admin_pass) != 0)) {
|
||||
error(0, "MmsBox: 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 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.
|
||||
* mmsc-id is either empty (meaning ALL) or an ID of an existing MMSC connection.
|
||||
*/
|
||||
|
||||
if (octstr_str_case_compare(cmd, "start") == 0) {
|
||||
mCfgGrp *m;
|
||||
if (mmc_id == NULL)
|
||||
l = mms_cfg_get_multi(cfg, octstr_imm("mmsc"));
|
||||
else if ((m = mms_get_multi_by_field(cfg,
|
||||
octstr_imm("mmsc"),
|
||||
octstr_imm("id"),
|
||||
mmc_id)) != NULL) {
|
||||
l = gwlist_create();
|
||||
gwlist_append(l, m);
|
||||
}
|
||||
/* Start MMSCs. */
|
||||
|
||||
while ((m = gwlist_extract_first(l)) != NULL) {
|
||||
List *e = gwlist_create();
|
||||
List *w = gwlist_create();
|
||||
Octstr *x;
|
||||
MmscGrp *mc = start_mmsc_from_conf(cfg, m, mmsc_receiver_func, e, w);
|
||||
|
||||
if (mc != NULL)
|
||||
append_mmsc_status(rbody, mc, w);
|
||||
else if (gwlist_len(e) > 0)
|
||||
while ((x = gwlist_extract_first(e)) != NULL) {
|
||||
octstr_format_append(rbody,
|
||||
"<Start-Mmsc><Error>%S</Error></Start-Mmsc>\n",
|
||||
x);
|
||||
octstr_destroy(x);
|
||||
}
|
||||
gwlist_destroy(e, (void *)octstr_destroy);
|
||||
gwlist_destroy(w, (void *)octstr_destroy);
|
||||
|
||||
}
|
||||
} else if (octstr_str_case_compare(cmd, "stop") == 0) {
|
||||
Octstr *x;
|
||||
if (mmc_id == NULL)
|
||||
l = dict_keys(mmscs);
|
||||
else {
|
||||
l = gwlist_create();
|
||||
gwlist_append(l, octstr_duplicate(mmc_id));
|
||||
}
|
||||
|
||||
while ((x = gwlist_extract_first(l)) != NULL) {
|
||||
int ret = mmsbox_stop_mmsc_conn(x);
|
||||
octstr_format_append(rbody,
|
||||
"<Stop-Mmsc><%s/></Stop-Mmsc>\n",
|
||||
ret == 0 ? "Success" : "Failed");
|
||||
octstr_destroy(x);
|
||||
}
|
||||
|
||||
} else if (octstr_str_case_compare(cmd, "status") == 0) {
|
||||
Octstr *x;
|
||||
MmscGrp *mc;
|
||||
if (mmc_id == NULL)
|
||||
l = dict_keys(mmscs);
|
||||
else {
|
||||
l = gwlist_create();
|
||||
gwlist_append(l, octstr_duplicate(mmc_id));
|
||||
}
|
||||
|
||||
while ((x = gwlist_extract_first(l)) != NULL) {
|
||||
if ((mc = dict_get(mmscs, x)) != NULL)
|
||||
append_mmsc_status(rbody, mc, 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);
|
||||
}
|
||||
|
||||
info(0, "MmsBox: Admin Interface -- shuttind down on port %d", (int)admin_port);
|
||||
}
|
||||
|
||||
void free_mmsbox_http_clientInfo(MmsBoxHTTPClientInfo *h, int freeh)
|
||||
|
|
|
@ -49,6 +49,14 @@ typedef struct MmscGrp {
|
|||
void *data; /* data for above module. */
|
||||
int custom_started; /* set to 1 if custom mmc started. */
|
||||
|
||||
unsigned long mt_pdus; /* number of MT PDUs since start. */
|
||||
unsigned long mo_pdus; /* number of MO PDUs since start. */
|
||||
unsigned long mt_errors; /* number of MT errors since start */
|
||||
unsigned long mo_errors; /* number of MO errors since start */
|
||||
|
||||
time_t last_pdu; /* time of last PDU */
|
||||
time_t start_time; /* when was this connection started */
|
||||
|
||||
int use_count; /* use counter. */
|
||||
time_t delete_after; /* used to control deletion of object -- not ver clean, but... */
|
||||
} MmscGrp;
|
||||
|
@ -131,16 +139,16 @@ extern void *rfs_data;
|
|||
extern Octstr *rfs_settings;
|
||||
|
||||
|
||||
extern int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func);
|
||||
extern int mms_load_mmsbox_settings(Octstr *fname, gwthread_func_t *mmsc_handler_func);
|
||||
extern void mmsbox_settings_cleanup(void);
|
||||
extern MmscGrp *get_handler_mmc(Octstr *id, Octstr *to, Octstr *from);
|
||||
extern void return_mmsc_conn(MmscGrp *m);
|
||||
|
||||
extern Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m,
|
||||
Octstr **mmc_id);
|
||||
extern void mmsbox_cleanup_settings(void);
|
||||
void start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_func);
|
||||
void mmsbox_stop_mmsc_conn(Octstr *mmc);
|
||||
MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, gwthread_func_t *mmsc_handler_func,
|
||||
List *errors, List *warnings);
|
||||
int mmsbox_stop_mmsc_conn(Octstr *mmc);
|
||||
void mmsbox_stop_all_mmsc_conn(void);
|
||||
typedef struct MmsBoxHTTPClientInfo {
|
||||
HTTPClient *client;
|
||||
|
|
Loading…
Reference in New Issue