898 lines
26 KiB
C
898 lines
26 KiB
C
/*
|
|
* MMS proxy gateway: Receives MMS messages from clients, dispatches to
|
|
* delivery queues. Also provides interface for collecting messages.
|
|
*/
|
|
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
|
|
#include "mms_msg.h"
|
|
#include "mms_queue.h"
|
|
|
|
#include "mms_uaprof.h"
|
|
#include "mms_util.h"
|
|
|
|
static Cfg *cfg;
|
|
static List *proxyrelays;
|
|
static MmsBoxSettings *settings;
|
|
|
|
static int rstop = 0;
|
|
static void quit_now(int notused)
|
|
{
|
|
rstop = 1;
|
|
if (settings)
|
|
http_close_port(settings->port);
|
|
}
|
|
|
|
typedef struct MmsHTTPClientInfo {
|
|
HTTPClient *client;
|
|
Octstr *ua;
|
|
Octstr *ip;
|
|
List *headers;
|
|
Octstr *url;
|
|
Octstr *body;
|
|
List *cgivars;
|
|
MmsUaProfile *prof;
|
|
Octstr *base_client_addr;
|
|
Octstr *client_addr;
|
|
} MmsHTTPClientInfo;
|
|
|
|
static void fetchmms_proxy(MmsHTTPClientInfo *h);
|
|
static void sendmms_proxy(MmsHTTPClientInfo *h);
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int cfidx;
|
|
Octstr *fname;
|
|
CfgGroup *grp;
|
|
Octstr *log, *alog;
|
|
long loglevel;
|
|
|
|
MmsHTTPClientInfo h;
|
|
|
|
mms_lib_init();
|
|
srandom(time(NULL));
|
|
|
|
cfidx = get_and_set_debugs(argc, argv, NULL);
|
|
|
|
if (argv[cfidx] == NULL)
|
|
fname = octstr_imm("mmsc.conf");
|
|
else
|
|
fname = octstr_create(argv[cfidx]);
|
|
|
|
cfg = cfg_create(fname);
|
|
|
|
if (cfg_read(cfg) == -1)
|
|
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
|
|
|
|
octstr_destroy(fname);
|
|
|
|
info(0, "----------------------------------------");
|
|
info(0, " MMSC Proxy Relay server version %s starting", MMSC_VERSION);
|
|
|
|
grp = cfg_get_single_group(cfg, octstr_imm("core"));
|
|
log = cfg_get(grp, octstr_imm("log-file"));
|
|
if (log != NULL) {
|
|
if (cfg_get_integer(&loglevel, grp, octstr_imm("log-level")) == -1)
|
|
loglevel = 0;
|
|
log_open(octstr_get_cstr(log), loglevel, GW_NON_EXCL);
|
|
octstr_destroy(log);
|
|
}
|
|
|
|
/* Get access log and open it. */
|
|
alog = cfg_get(grp, octstr_imm("access-log"));
|
|
if (alog) {
|
|
alog_open(octstr_get_cstr(alog), 1, 1);
|
|
octstr_destroy(alog);
|
|
}
|
|
/* Load proxy relays. */
|
|
|
|
proxyrelays = mms_proxy_relays(cfg);
|
|
|
|
/* Load settings. */
|
|
settings = mms_load_mmsbox_settings(cfg);
|
|
|
|
if (!settings)
|
|
panic(0, "No global MMSC configuration!");
|
|
|
|
|
|
signal(SIGHUP, quit_now);
|
|
signal(SIGTERM, quit_now);
|
|
|
|
/* Start cache engine. */
|
|
mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir));
|
|
|
|
/* Now open port and start dispatching requests. */
|
|
|
|
if (http_open_port(settings->port, 0) < 0) {
|
|
error(0, "MMS Proxy: Failed to start http server: %d => %s!",
|
|
errno, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
while(rstop == 0 && (h.client = http_accept_request(settings->port,
|
|
&h.ip, &h.url, &h.headers,
|
|
&h.body, &h.cgivars)) != NULL)
|
|
if (is_allowed_ip(settings->deny_ip, settings->allow_ip, h.ip)) {
|
|
MmsHTTPClientInfo *hx = gw_malloc(sizeof *hx);
|
|
Octstr *profile_url;
|
|
|
|
h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
|
|
|
|
/* Get the profile URL and store it. Has effect of fetching if missing. */
|
|
if ((profile_url = http_header_value(h.headers,
|
|
octstr_imm("X-Wap-Profile"))) == NULL)
|
|
profile_url = http_header_value(h.headers, octstr_imm("Profile"));
|
|
|
|
if (profile_url) {
|
|
octstr_strip_nonalphanums(profile_url);
|
|
h.prof = mms_get_ua_profile(octstr_get_cstr(profile_url));
|
|
octstr_destroy(profile_url);
|
|
} else
|
|
|
|
h.prof = mms_make_ua_profile(h.headers);
|
|
|
|
/* Get the sender address. */
|
|
|
|
h.base_client_addr = mms_find_sender_msisdn(&h.url, h.headers, settings->wap_gw_msisdn_header);
|
|
|
|
if (!h.base_client_addr) { /* Set to IP sender... XXXX assumes ipv4 only for now*/
|
|
int ipv6 = 0;
|
|
h.base_client_addr = mms_find_sender_ip(h.headers,
|
|
settings->wap_gw_ip_header,
|
|
h.ip, &ipv6);
|
|
h.client_addr = octstr_format("%S/TYPE=IPv%s",
|
|
h.ip, ipv6 ? "6" : "4");
|
|
} else {
|
|
normalize_number(octstr_get_cstr(settings->unified_prefix), &h.base_client_addr);
|
|
h.client_addr = octstr_format("%S/TYPE=PLMN", h.base_client_addr);
|
|
}
|
|
|
|
/* Dump headers, url etc. */
|
|
#if 0
|
|
http_header_dump(h.headers);
|
|
if (h.body) octstr_dump(h.body, 0);
|
|
if (h.ip) octstr_dump(h.ip, 0);
|
|
#endif
|
|
/* Determine if this is the fetch interface or the send interface being used,
|
|
* by checking if http request has a body.
|
|
* then call relevant function in a thread (use threads because these functions
|
|
* can block)
|
|
*/
|
|
*hx = h; /* Copy it all over. */
|
|
if (hx->body == NULL || octstr_len(hx->body) == 0)
|
|
gwthread_create((gwthread_func_t *)fetchmms_proxy, hx);
|
|
else
|
|
gwthread_create((gwthread_func_t *)sendmms_proxy, hx);
|
|
|
|
} else {
|
|
octstr_destroy(h.ip);
|
|
octstr_destroy(h.url);
|
|
if (h.ua) octstr_destroy(h.ua);
|
|
if (h.base_client_addr)
|
|
octstr_destroy(h.base_client_addr);
|
|
octstr_destroy(h.client_addr);
|
|
octstr_destroy(h.body);
|
|
http_destroy_headers(h.headers);
|
|
http_destroy_headers(h.cgivars);
|
|
|
|
http_close_client(h.client);
|
|
}
|
|
|
|
debug("proxy", 0, "Shutdown requested");
|
|
http_close_all_ports();
|
|
debug("proxy", 0, "Port closed");
|
|
sleep(2); /* Give them time to shut down. */
|
|
mms_stop_profile_engine();
|
|
sleep(2); /* Give them time to shut down. */
|
|
return 0;
|
|
}
|
|
|
|
|
|
void fetchmms_proxy(MmsHTTPClientInfo *h)
|
|
{
|
|
Octstr *qf = NULL, *token = NULL, *s = NULL, *transid = NULL;
|
|
MmsEnvelope *e = NULL;
|
|
MmsMsg *m = NULL, *mr = NULL;
|
|
List *rh;
|
|
|
|
debug("proxy.fetchinterface", 0, " ---> Entered fetch interface <---");
|
|
|
|
rh = http_create_empty_headers();
|
|
http_header_add(rh, "Pragma", "no-cache");
|
|
http_header_add(rh, "Cache-Control", "no-cache");
|
|
|
|
if (mms_decodefetchurl(h->url, &qf, &token) != 0) {
|
|
error(0, "MMS Fetch interface: failed to decode request url (%s) from %s!",
|
|
octstr_get_cstr(h->url),
|
|
octstr_get_cstr(h->ip));
|
|
goto failed;
|
|
}
|
|
e = mms_queue_readenvelope(octstr_get_cstr(qf),
|
|
octstr_get_cstr(settings->mm1_queuedir), 1);
|
|
|
|
if (!e ||
|
|
(m = mms_queue_getdata(e)) == NULL) {
|
|
error(0, "MMS Fetch interface: failed to find envelope/data %s for request url (%s) from %s (e=%s)!",
|
|
octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip),
|
|
(e)? "found" : "not found");
|
|
|
|
mr = mms_retrieveconf(NULL, NULL, "Error-permanent-message-not-found", "Message not found",
|
|
settings->system_user);
|
|
s = mms_tobinary(mr);
|
|
goto failed;
|
|
}
|
|
|
|
/* Adapt content. */
|
|
transid = mms_maketransid(e->qf.name, settings->host_alias);
|
|
if (h->prof) {
|
|
MmsMsg *outmsg = NULL;
|
|
int x = mms_transform_msg(m, h->prof, &outmsg);
|
|
|
|
if (x == -1) { /* Temporary failure, we need to fetch profile. */
|
|
mr = mms_retrieveconf(NULL, transid, "Error-transient-failure", "Mobile MMS Settings not found",
|
|
settings->system_user);
|
|
s = mms_tobinary(mr);
|
|
goto failed;
|
|
} else if (x < 0) { /* Doesn't support MMS */
|
|
mr = mms_retrieveconf(NULL, transid, "Error-permanent-content-unsupported", "No MMS Support",
|
|
settings->system_user);
|
|
s = mms_tobinary(mr);
|
|
goto failed;
|
|
} else if (x == 0) {
|
|
if (outmsg == NULL) { /* Too large so truncated. */
|
|
Octstr *xx = octstr_format(octstr_get_cstr(settings->mms_toolarge), e->from);
|
|
|
|
mr = mms_retrieveconf(NULL, transid,
|
|
#if 0
|
|
"Error-permanent-content-unsupported",
|
|
#else
|
|
"Ok",
|
|
#endif
|
|
octstr_get_cstr(xx),
|
|
settings->system_user);
|
|
octstr_destroy(xx);
|
|
|
|
s = mms_tobinary(mr);
|
|
goto failed;
|
|
} else {
|
|
mms_destroy(m);
|
|
m = outmsg;
|
|
}
|
|
}
|
|
}
|
|
|
|
mr = mms_retrieveconf(m, transid, "Error-permanent-message-not-found", NULL, e->from);
|
|
s = mms_tobinary(mr);
|
|
|
|
if ((token == NULL && e->token != NULL) ||
|
|
(e->token == NULL && token != NULL) ||
|
|
(octstr_compare(e->token, token) != 0)) {
|
|
error(0, "MMS Fetch interface: token mismatch, did client mod the fetch url?? "
|
|
" env=%s for request url (%s) from %s!",
|
|
octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip));
|
|
goto failed;
|
|
}
|
|
|
|
|
|
if (!m) {
|
|
error(0, "MMS Fetch interface: Failed to get message for request url (%s) from %s!",
|
|
octstr_get_cstr(h->url), octstr_get_cstr(h->ip));
|
|
goto failed;
|
|
}
|
|
|
|
if (!s) {
|
|
error(0, "MMS Fetch interface: Failed to convert message to binary for "
|
|
"request url (%s) from %s!",
|
|
octstr_get_cstr(h->url), octstr_get_cstr(h->ip));
|
|
goto failed;
|
|
}
|
|
|
|
|
|
|
|
e->lastaccess = time(NULL); /* No more notifications requests. */
|
|
e->sendt = e->expiryt + 3600*24*30*12;
|
|
mms_queue_update(e);
|
|
|
|
|
|
http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message");
|
|
http_send_reply(h->client, HTTP_OK, rh, s);
|
|
|
|
#if 1
|
|
debug("proxy.fetchinterface", 0,
|
|
" $$$$$$ fetch message replying with [type=%s,content_len=%ld]: ",
|
|
mr ? mms_message_type_to_cstr(mms_messagetype(mr)) : (unsigned char *)"none",
|
|
s ? octstr_len(s) : 0);
|
|
if (mr)
|
|
mms_msgdump(mr,1);
|
|
#endif
|
|
|
|
/* Send to access log with success. */
|
|
mms_log2("Fetched", e ? e->from : NULL, h->client_addr,
|
|
e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", h->ua);
|
|
|
|
goto free_stuff; /* Skip to end. */
|
|
|
|
failed:
|
|
#if 1
|
|
debug("proxy.fetchinterface", 0,
|
|
" $$$$$$ fetch message [fail] replying with [type=%s,content_len=%ld]: ",
|
|
mr ? mms_message_type_to_cstr(mms_messagetype(mr)) : (unsigned char *)"none",
|
|
s ? octstr_len(s) : 0);
|
|
if (mr)
|
|
mms_msgdump(mr,1);
|
|
#endif
|
|
|
|
/* Send to access log on failure?? */
|
|
mms_log2("Failed Fetch", e ? e->from : NULL, h->client_addr,
|
|
e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", h->ua);
|
|
|
|
if (!s) {
|
|
http_header_add(rh, "Content-Type", "text/plain");
|
|
http_send_reply(h->client, HTTP_NOT_FOUND, rh, octstr_imm("Not found"));
|
|
} else {
|
|
http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message");
|
|
http_send_reply(h->client, HTTP_OK, rh, s);
|
|
}
|
|
|
|
free_stuff:
|
|
|
|
http_destroy_headers(rh);
|
|
if (e) mms_queue_free_env(e);
|
|
|
|
if (s) octstr_destroy(s);
|
|
if (m) mms_destroy(m);
|
|
if (mr) mms_destroy(mr);
|
|
|
|
if (qf) octstr_destroy(qf);
|
|
if (token) octstr_destroy(token);
|
|
if (transid) octstr_destroy(transid);
|
|
|
|
octstr_destroy(h->ip);
|
|
octstr_destroy(h->url);
|
|
if (h->ua) octstr_destroy(h->ua);
|
|
if (h->body) octstr_destroy(h->body);
|
|
|
|
if (h->base_client_addr)
|
|
octstr_destroy(h->base_client_addr);
|
|
octstr_destroy(h->client_addr);
|
|
|
|
http_destroy_cgiargs(h->cgivars);
|
|
http_destroy_headers(h->headers);
|
|
|
|
gw_free(h);
|
|
|
|
}
|
|
|
|
/* Make list of recipients and also sender. */
|
|
static void collect_senddata(List *mh, List **xto,
|
|
Octstr **from, Octstr **subject,
|
|
Octstr **otransid, time_t *expiryt, time_t *deliveryt)
|
|
{
|
|
|
|
Octstr *s;
|
|
List *l = http_header_find_all(mh, "To");
|
|
if (l) {
|
|
int i, n;
|
|
for (i = 0, n = list_len(l); i<n; i++) {
|
|
Octstr *name, *value;
|
|
http_header_get(l, i, &name, &value);
|
|
list_append(*xto, value);
|
|
octstr_destroy(name);
|
|
|
|
}
|
|
http_destroy_headers(l);
|
|
}
|
|
|
|
l = http_header_find_all(mh, "Cc");
|
|
if (l) {
|
|
int i, n;
|
|
for (i = 0, n = list_len(l); i<n; i++) {
|
|
Octstr *name, *value;
|
|
http_header_get(l, i, &name, &value);
|
|
list_append(*xto, value);
|
|
octstr_destroy(name);
|
|
|
|
}
|
|
http_destroy_headers(l);
|
|
}
|
|
|
|
|
|
l = http_header_find_all(mh, "Bcc");
|
|
if (l) {
|
|
int i, n;
|
|
|
|
for (i = 0, n = list_len(l); i<n; i++) {
|
|
Octstr *name, *value;
|
|
http_header_get(l, i, &name, &value);
|
|
list_append(*xto, value);
|
|
octstr_destroy(name);
|
|
|
|
}
|
|
http_destroy_headers(l);
|
|
}
|
|
|
|
|
|
*from = http_header_value(mh, octstr_imm("From"));
|
|
|
|
|
|
/* Find expiry and delivery times */
|
|
if (expiryt) {
|
|
s = http_header_value(mh, octstr_imm("X-Mms-Expiry"));
|
|
if (s) {
|
|
*expiryt = date_parse_http(s);
|
|
octstr_destroy(s);
|
|
} else
|
|
*expiryt = time(NULL) + settings->default_msgexpiry;
|
|
}
|
|
|
|
if (deliveryt) {
|
|
s = http_header_value(mh, octstr_imm("X-Mms-Delivery-Time"));
|
|
if (s) {
|
|
*deliveryt = date_parse_http(s);
|
|
octstr_destroy(s);
|
|
} else
|
|
*deliveryt = 0;
|
|
}
|
|
if (subject)
|
|
*subject = http_header_value(mh, octstr_imm("Subject"));
|
|
|
|
if (otransid)
|
|
*otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID"));
|
|
|
|
}
|
|
|
|
static void sendmms_proxy(MmsHTTPClientInfo *h)
|
|
{
|
|
List *rh = http_create_empty_headers();
|
|
MmsMsg *m, *mresp = NULL;
|
|
Octstr *reply_body = NULL;
|
|
int ctype_set = 0;
|
|
int mtype = 0;
|
|
int hstatus = HTTP_OK;
|
|
char *notify_cmd = NULL;
|
|
int msize = h->body ? octstr_len(h->body) : 0;
|
|
|
|
debug("proxy.sendinterface", 0,
|
|
" --> Enterred sendmms interface, blen=%d <--- ",
|
|
msize);
|
|
|
|
http_header_add(rh, "Pragma", "no-cache");
|
|
http_header_add(rh, "Cache-Control", "no-cache");
|
|
|
|
|
|
|
|
if (!h->body) { /* A body is required. */
|
|
http_header_add(rh, "Content-Type", "text/plain");
|
|
hstatus = HTTP_FORBIDDEN;
|
|
reply_body = octstr_format("Unexpected MMS message[%s], no body?",
|
|
mms_message_type_to_cstr(mtype));
|
|
|
|
goto done;
|
|
}
|
|
|
|
m = mms_frombinary(h->body, h->client_addr);
|
|
|
|
if (!m) {
|
|
http_header_add(rh, "Content-Type", "text/plain");
|
|
ctype_set = 1;
|
|
hstatus = HTTP_BAD_REQUEST;
|
|
reply_body = octstr_format("Malformed MMS message");
|
|
debug("proxy.sendinterface", 0, " Parse error on incoming message.");
|
|
goto done;
|
|
}
|
|
|
|
debug("proxy.sendinterface", 0, " Client sent us: ");
|
|
|
|
#if 1
|
|
mms_msgdump(m,1);
|
|
/* octstr_dump(h->body, 0); */
|
|
#endif
|
|
mtype = mms_messagetype(m);
|
|
|
|
switch(mtype) {
|
|
|
|
case MMS_MSGTYPE_SEND_REQ:
|
|
{
|
|
Octstr *qf;
|
|
List *mh = mms_message_headers(m);
|
|
Octstr *from;
|
|
List *to = list_create();
|
|
Octstr *subject;
|
|
time_t expiryt, deliveryt;
|
|
|
|
Octstr *otransid, *value;
|
|
int dlr;
|
|
|
|
|
|
collect_senddata(mh, &to, &from, &subject, &otransid, &expiryt, &deliveryt);
|
|
|
|
/*Delete some headers that must be sent on. */
|
|
mms_remove_headers(m, "Bcc");
|
|
mms_remove_headers(m, "X-Mms-Delivery-Time");
|
|
mms_remove_headers(m, "X-Mms-Expiry");
|
|
mms_remove_headers(m, "X-Mms-Sender-Visibility");
|
|
|
|
|
|
value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"));
|
|
if (value &&
|
|
octstr_case_compare(value, octstr_imm("Yes")) == 0)
|
|
dlr = 1;
|
|
else
|
|
dlr = 0;
|
|
|
|
|
|
qf = mms_queue_add(from, to, NULL, subject,
|
|
NULL, NULL, deliveryt, expiryt, m, NULL, dlr,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
|
|
if (!qf)
|
|
mresp = mms_sendconf("Error-transient-failure", "None", octstr_get_cstr(otransid),0);
|
|
else {
|
|
Octstr *transid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias);
|
|
mresp = mms_sendconf("Ok", octstr_get_cstr(transid), octstr_get_cstr(otransid),0);
|
|
|
|
/* Log to access log */
|
|
mms_log("Received", from, to, msize, transid, NULL, NULL, "MM1", h->ua);
|
|
|
|
octstr_destroy(transid);
|
|
octstr_destroy(qf);
|
|
}
|
|
|
|
if (otransid)
|
|
octstr_destroy(otransid);
|
|
if (value)
|
|
octstr_destroy(value);
|
|
octstr_destroy(from);
|
|
octstr_destroy(subject);
|
|
http_destroy_headers(mh);
|
|
list_destroy(to, (list_item_destructor_t *)octstr_destroy);
|
|
|
|
notify_cmd = "sent";
|
|
reply_body = mms_tobinary(mresp);
|
|
}
|
|
break;
|
|
case MMS_MSGTYPE_FORWARD_REQ:
|
|
{
|
|
Octstr *qf = NULL, *token = NULL;
|
|
List *mh = mms_message_headers(m);
|
|
Octstr *from;
|
|
List *to = list_create();
|
|
Octstr *subject;
|
|
time_t expiryt, deliveryt;
|
|
MmsMsg *mfwd = NULL;
|
|
MmsEnvelope *e = NULL;
|
|
|
|
Octstr *otransid;
|
|
Octstr *url = http_header_value(mh, octstr_imm("X-Mms-Content-Location"));
|
|
Octstr *read_report = http_header_value(mh, octstr_imm("X-Mms-Read-Report"));
|
|
Octstr *delivery_report = http_header_value(mh,
|
|
octstr_imm("X-Mms-Delivery-Report"));
|
|
Octstr *allow_report = http_header_value(mh,
|
|
octstr_imm("X-Mms-Report-Allowed"));
|
|
int dlr;
|
|
|
|
collect_senddata(mh, &to, &from, &subject, &otransid, &expiryt, &deliveryt);
|
|
|
|
if (mms_decodefetchurl(url, &qf, &token) != 0) {
|
|
error(0, "MMS Send interface: failed to decode forward url (%s) from %s!",
|
|
octstr_get_cstr(url),
|
|
octstr_get_cstr(h->ip));
|
|
mresp = mms_sendconf("Error-permanent-message-not-found", "None",
|
|
octstr_get_cstr(otransid),1);
|
|
goto forward_done;
|
|
}
|
|
|
|
e = mms_queue_readenvelope(octstr_get_cstr(qf),
|
|
octstr_get_cstr(settings->mm1_queuedir), 1);
|
|
|
|
if (!e ||
|
|
(mfwd = mms_queue_getdata(e)) == NULL) {
|
|
error(0,
|
|
"MMS Send interface: failed to find envelope/data %s for forward url "
|
|
"(%s) from %s (e=%s)!",
|
|
octstr_get_cstr(qf), octstr_get_cstr(url), octstr_get_cstr(h->ip),
|
|
(e) ? "found" : "not found");
|
|
|
|
mresp = mms_sendconf("Error-permanent-message-not-found", "None",
|
|
octstr_get_cstr(otransid),1);
|
|
goto forward_done;
|
|
} else { /* Found it, etc. */
|
|
|
|
Octstr *transid;
|
|
Octstr *pfrom = mms_get_header_value(mfwd, octstr_imm("From"));
|
|
Octstr *pdate = mms_get_header_value(mfwd, octstr_imm("Date"));
|
|
Octstr *pdelivery_report = mms_get_header_value(mfwd,
|
|
octstr_imm("X-Mms-Delivery-Report"));
|
|
Octstr *pmsgid = mms_get_header_value(mfwd, octstr_imm("Message-ID"));
|
|
Octstr *s;
|
|
Octstr *qf2;
|
|
int n = 0;
|
|
|
|
|
|
/* Modify the message before sending on as per spec. */
|
|
mms_replace_header_value(mfwd, "From", octstr_get_cstr(from));
|
|
|
|
mms_remove_headers(mfwd, "X-Mms-Read-Report");
|
|
if (read_report)
|
|
mms_replace_header_value(mfwd, "X-Mms-Read-Report",
|
|
octstr_get_cstr(read_report));
|
|
|
|
mms_remove_headers(mfwd, "X-Mms-Delivery-Report");
|
|
if (delivery_report)
|
|
mms_replace_header_value(mfwd, "X-Mms-Delivery-Report",
|
|
octstr_get_cstr(delivery_report));
|
|
|
|
|
|
if ((s = mms_get_header_value(mfwd, octstr_imm("X-Mms-Previously-Sent-By"))) != NULL) {
|
|
sscanf(octstr_get_cstr(s), "%d", &n);
|
|
octstr_destroy(s);
|
|
}
|
|
s = octstr_format("%d %S", n+1, pfrom);
|
|
mms_replace_header_value(mfwd, "X-Mms-Previously-Sent-By", octstr_get_cstr(s));
|
|
|
|
|
|
if ((s = mms_get_header_value(mfwd,
|
|
octstr_imm("X-Mms-Previously-Sent-Date")))
|
|
!= NULL) {
|
|
sscanf(octstr_get_cstr(s), "%d", &n);
|
|
octstr_destroy(s);
|
|
}
|
|
s = octstr_format("%d %S", n+1, pdate);
|
|
mms_replace_header_value(mfwd,
|
|
"X-Mms-Previously-Sent-Date",
|
|
octstr_get_cstr(s));
|
|
octstr_destroy(pdate);
|
|
|
|
if (delivery_report &&
|
|
octstr_case_compare(delivery_report, octstr_imm("Yes")) == 0)
|
|
dlr = 1;
|
|
else
|
|
dlr = 0;
|
|
/* Message to forward is now ready, write it to queue. */
|
|
qf2 = mms_queue_add(from, to, NULL, subject,
|
|
NULL, NULL, deliveryt, expiryt, mfwd, NULL,
|
|
dlr,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
|
|
|
|
if (!qf2)
|
|
mresp = mms_sendconf("Error-transient-failure",
|
|
"None", octstr_get_cstr(otransid),1);
|
|
else {
|
|
transid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias);
|
|
mresp = mms_sendconf("Ok",
|
|
octstr_get_cstr(transid),
|
|
octstr_get_cstr(otransid),1);
|
|
|
|
/* Log to access log */
|
|
mms_log("Forwarded", h->client_addr, to, msize, transid, NULL, NULL, "MM1", h->ua);
|
|
|
|
octstr_destroy(transid);
|
|
octstr_destroy(qf2);
|
|
}
|
|
|
|
/* You have queued it, now check if the original sender asked for a delivery notify.
|
|
* if so and this forward has not refused it, then send a notify and we are done for now.
|
|
*/
|
|
|
|
if ((!allow_report ||
|
|
octstr_case_compare(allow_report, octstr_imm("Yes")) == 0) &&
|
|
(pdelivery_report && octstr_case_compare(pdelivery_report,
|
|
octstr_imm("Yes")))) {
|
|
|
|
MmsMsg *mrep = mms_deliveryreport(pmsgid, h->client_addr, time(NULL), octstr_imm("Forwarded"));
|
|
Octstr *x;
|
|
List *l = list_create();
|
|
list_append(l, pfrom);
|
|
|
|
x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, NULL, 0,
|
|
time(NULL) + settings->default_msgexpiry,
|
|
mrep, NULL,0,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
octstr_destroy(x);
|
|
|
|
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
|
|
mms_destroy(mrep);
|
|
}
|
|
octstr_destroy(pfrom);
|
|
octstr_destroy(pdelivery_report);
|
|
octstr_destroy(pmsgid);
|
|
|
|
}
|
|
|
|
forward_done:
|
|
|
|
if (mfwd)
|
|
mms_destroy(mfwd);
|
|
|
|
if (e) { /* Update the message queue and go. */
|
|
e->lastaccess = time(NULL);
|
|
if (mms_queue_update(e) != 1) /* Should be freed. */
|
|
mms_queue_free_env(e);
|
|
e = NULL;
|
|
}
|
|
|
|
if (qf)
|
|
octstr_destroy(qf);
|
|
if (token)
|
|
octstr_destroy(token);
|
|
if (from)
|
|
octstr_destroy(from);
|
|
if (subject)
|
|
octstr_destroy(subject);
|
|
if (mh)
|
|
http_destroy_headers(mh);
|
|
if (to)
|
|
list_destroy(to, (list_item_destructor_t *)octstr_destroy);
|
|
if (otransid)
|
|
octstr_destroy(otransid);
|
|
if (url)
|
|
octstr_destroy(url);
|
|
|
|
if (read_report)
|
|
octstr_destroy(read_report);
|
|
if (allow_report)
|
|
octstr_destroy(allow_report);
|
|
if (delivery_report)
|
|
octstr_destroy(delivery_report);
|
|
|
|
reply_body = mms_tobinary(mresp);
|
|
notify_cmd = "fetched";
|
|
}
|
|
break;
|
|
case MMS_MSGTYPE_NOTIFYRESP:
|
|
case MMS_MSGTYPE_ACKNOWLEDGE_IND:
|
|
{
|
|
Octstr *transid = mms_get_header_value(m, octstr_imm("X-Mms-Transaction-ID"));
|
|
Octstr *allow_report = mms_get_header_value(m, octstr_imm("X-Mms-Report-Allowed"));
|
|
|
|
Octstr *qf = mms_getqf_fromtransid(transid);
|
|
MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(qf),
|
|
octstr_get_cstr(settings->mm1_queuedir), 1);
|
|
Octstr *status;
|
|
|
|
MmsMsg *mrpt;
|
|
|
|
|
|
if (mtype == MMS_MSGTYPE_NOTIFYRESP)
|
|
status = mms_get_header_value(m, octstr_imm("X-Mms-Status"));
|
|
else /* This (acknowledge-ind) is the same as notify_resp with status=retrieved. */
|
|
status = octstr_imm("Retrieved");
|
|
|
|
if (!e) {
|
|
error(0, "MMS Send interface: Received notification type=%s "
|
|
"[url=%s, transid=%s, qf=%s] but could not find queue entry!\n",
|
|
mms_message_type_to_cstr(mtype), octstr_get_cstr(h->url),
|
|
octstr_get_cstr(transid), octstr_get_cstr(qf));
|
|
goto mdone;
|
|
}
|
|
|
|
if (octstr_str_compare(status, "Retrieved") == 0) {
|
|
MmsEnvelopeTo *t = list_get(e->to, 0);
|
|
if (t)
|
|
t->process = 0;
|
|
} else
|
|
e->lastaccess = time(NULL); /* Note now that it has been touched. */
|
|
|
|
/* If the allow report header is missing (default is Yes)
|
|
* or it is there and has said we must send report,
|
|
* and sender requested a report, then queue a report.
|
|
*/
|
|
if ((allow_report == NULL
|
|
|| octstr_case_compare(allow_report, octstr_imm("Yes")) == 0) &&
|
|
e->dlr) {
|
|
Octstr *x;
|
|
List *l = list_create();
|
|
|
|
mrpt = mms_deliveryreport(e->msgId, h->client_addr, time(NULL), status);
|
|
list_append(l, octstr_duplicate(e->from));
|
|
|
|
x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, NULL, 0,
|
|
time(NULL) + settings->default_msgexpiry, mrpt, NULL, 0,
|
|
octstr_get_cstr(settings->global_queuedir));
|
|
octstr_destroy(x);
|
|
|
|
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
|
|
mms_destroy(mrpt);
|
|
}
|
|
|
|
mdone:
|
|
|
|
/* Log to access log */
|
|
mms_log2("NotifyResp", h->client_addr, NULL, msize, transid, NULL, NULL, "MM1", h->ua);
|
|
|
|
if (e &&
|
|
mms_queue_update(e) != 1) /* Should be freed. */
|
|
mms_queue_free_env(e);
|
|
|
|
octstr_destroy(qf);
|
|
octstr_destroy(transid);
|
|
octstr_destroy(allow_report);
|
|
octstr_destroy(status);
|
|
http_header_add(rh, "Content-Type", "text/plain");
|
|
ctype_set = 1;
|
|
reply_body = octstr_imm("Received");
|
|
|
|
notify_cmd = "fetched";
|
|
}
|
|
break;
|
|
|
|
case MMS_MSGTYPE_READ_REC_IND:
|
|
{
|
|
List *mh = mms_message_headers(m);
|
|
Octstr *from;
|
|
List *to = list_create();
|
|
Octstr *x;
|
|
|
|
if (mms_convert_readrec2readorig(m) < 0)
|
|
goto mdone2;
|
|
|
|
collect_senddata(mh, &to, &from, NULL, NULL, NULL, NULL);
|
|
|
|
x = mms_queue_add(from, to, NULL, NULL, NULL,
|
|
NULL, time(NULL), time(NULL) + settings->default_msgexpiry,
|
|
m, NULL, 0, octstr_get_cstr(settings->global_queuedir));
|
|
|
|
/* Log to access log */
|
|
mms_log("ReadReport", h->client_addr, NULL, msize, NULL, NULL, NULL, "MM1", h->ua);
|
|
|
|
octstr_destroy(x);
|
|
octstr_destroy(from);
|
|
http_destroy_headers(mh);
|
|
mdone2:
|
|
|
|
list_destroy(to, (list_item_destructor_t *)octstr_destroy);
|
|
http_header_add(rh, "Content-Type", "text/plain");
|
|
ctype_set = 1;
|
|
reply_body = octstr_imm("Received");
|
|
|
|
notify_cmd = "fetched";
|
|
break;
|
|
}
|
|
default:
|
|
http_header_add(rh, "Content-Type", "text/plain");
|
|
ctype_set = 1;
|
|
hstatus = HTTP_FORBIDDEN;
|
|
reply_body = octstr_format("Unexpected MMS message type %s", mms_message_type_to_cstr(mtype));
|
|
break;
|
|
}
|
|
|
|
|
|
if (notify_cmd) /* Inform provisioning server */
|
|
notify_prov_server(octstr_get_cstr(settings->prov_notify),
|
|
h->base_client_addr ? octstr_get_cstr(h->base_client_addr) : "unknown",
|
|
notify_cmd,
|
|
octstr_get_cstr(settings->prov_notify_arg));
|
|
|
|
mms_destroy(m);
|
|
/* Send reply. */
|
|
|
|
done:
|
|
|
|
if (mresp)
|
|
mms_destroy(mresp);
|
|
if (!ctype_set)
|
|
http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message");
|
|
|
|
http_send_reply(h->client, hstatus, rh, reply_body);
|
|
http_destroy_headers(rh);
|
|
octstr_destroy(reply_body);
|
|
|
|
octstr_destroy(h->ip);
|
|
octstr_destroy(h->url);
|
|
|
|
if (h->base_client_addr)
|
|
octstr_destroy(h->base_client_addr);
|
|
octstr_destroy(h->client_addr);
|
|
|
|
if (h->ua) octstr_destroy(h->ua);
|
|
if (h->body) octstr_destroy(h->body);
|
|
http_destroy_cgiargs(h->cgivars);
|
|
http_destroy_headers(h->headers);
|
|
|
|
gw_free(h);
|
|
|
|
}
|