/* * MMS proxy gateway: Receives MMS messages from clients, dispatches to * delivery queues. Also provides interface for collecting messages. */ #include #include #include #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); idefault_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); }