static void start_push(HTTPCaller *caller, long i) { List *push_headers; Octstr *push_content; long *id; push_content = push_content_create(); push_headers = push_headers_create(octstr_len(push_content)); if (verbose) { debug("test.ppg", 0, "we have push content"); octstr_dump(push_content, 0); debug("test.ppg", 0, "and headers"); http_header_dump(push_headers); } id = gw_malloc(sizeof(long)); *id = i; make_url(&push_url); debug("test.ppg", 0, "TEST_PPG: starting to push job %ld", i); http_start_request(caller, HTTP_METHOD_POST, push_url, push_headers, push_content, 0, id, ssl_client_certkey_file); debug("test.ppg", 0, "push done"); octstr_destroy(push_content); http_destroy_headers(push_headers); }
/* Sends REQ on socket SOCKFD. Returns the number of bytes which were sent, * and -1 on error. */ int kvrequest_send(kvrequest_t *kvreq, int sockfd) { char *method = http_method_for_request_type(kvreq->type); if (!method) return -1; struct url_params params; params.path = path_for_request_type(kvreq->type); params.key = kvreq->key; params.val = kvreq->val; char *url = url_encode(¶ms); struct http_outbound *msg = http_start_request(sockfd, method, url); if (!msg) return -1; free(url); http_end_headers(msg); return http_send_and_free(msg); }
static void start_request(HTTPCaller *caller, List *reqh, long i) { Octstr *url, *content = NULL; long *id; if ((i % 1000) == 0) info(0, "Starting fetch %ld", i); id = gw_malloc(sizeof(long)); *id = i; url = octstr_create(urls[i % num_urls]); if (file) { octstr_append(url, octstr_imm("&text=")); octstr_append(url, msg_text); } /* add the extra headers that have been read from the file */ if (split != NULL) http_header_combine(reqh, split); /* * if a body content file has been specified, then * we assume this should be a POST */ if (content_file != NULL) { content = post_content_create(); method = HTTP_METHOD_POST; } /* * if this is a POST request then pass the required content as body to * the HTTP server, otherwise skip the body, the arguments will be * urlencoded in the URL itself. */ http_start_request(caller, method, url, reqh, content, follow_redirect, id, ssl_client_certkey_file); debug("", 0, "Started request %ld with url:", *id); octstr_url_decode(url); octstr_dump(url, 0); octstr_destroy(url); octstr_destroy(msg_text); octstr_destroy(content); }
static int kannel_send_sms(SMSCConn *conn, Msg *sms) { ConnData *conndata = conn->data; Octstr *url; List *headers; if (!conndata->no_sep) { url = octstr_format("%S?" "username=%E&password=%E&to=%E&text=%E", conndata->send_url, conndata->username, conndata->password, sms->sms.receiver, sms->sms.msgdata); } else { Octstr *msgdata = octstr_duplicate(sms->sms.msgdata); octstr_binary_to_hex(msgdata, HEX_NOT_UPPERCASE); url = octstr_format("%S?" "username=%E&password=%E&to=%E&text=%S", conndata->send_url, conndata->username, conndata->password, sms->sms.receiver, msgdata); octstr_destroy(msgdata); } if (octstr_len(sms->sms.udhdata)) { if (!conndata->no_sep) { octstr_format_append(url, "&udh=%E", sms->sms.udhdata); } else { Octstr *udhdata = octstr_duplicate(sms->sms.udhdata); octstr_binary_to_hex(udhdata, HEX_NOT_UPPERCASE); octstr_format_append(url, "&udh=%S", udhdata); octstr_destroy(udhdata); } } if (!conndata->no_sender) octstr_format_append(url, "&from=%E", sms->sms.sender); if (sms->sms.mclass != MC_UNDEF) octstr_format_append(url, "&mclass=%d", sms->sms.mclass); if (!conndata->no_coding && sms->sms.coding != DC_UNDEF) octstr_format_append(url, "&coding=%d", sms->sms.coding); /* Obey that smsbox's sendsms HTTP interface is still expecting * WINDOWS-1252 as default charset, while all other internal parts * use UTF-8 as internal encoding. This means, when we pass a SMS * into a next Kannel instance, we need to let the smsbox know which * charset we have in use. * XXX TODO: change smsbox interface to use UTF-8 as default * in next major release. */ if (sms->sms.coding == DC_7BIT) octstr_append_cstr(url, "&charset=UTF-8"); else if (sms->sms.coding == DC_UCS2) octstr_append_cstr(url, "&charset=UTF-16BE"); if (sms->sms.mwi != MWI_UNDEF) octstr_format_append(url, "&mwi=%d", sms->sms.mwi); if (sms->sms.account) /* prepend account with local username */ octstr_format_append(url, "&account=%E:%E", sms->sms.service, sms->sms.account); if (sms->sms.binfo) /* prepend billing info */ octstr_format_append(url, "&binfo=%S", sms->sms.binfo); if (sms->sms.smsc_id) /* proxy the smsc-id to the next instance */ octstr_format_append(url, "&smsc=%S", sms->sms.smsc_id); if (conndata->dlr_url) { char id[UUID_STR_LEN + 1]; Octstr *mid; /* create Octstr from UUID */ uuid_unparse(sms->sms.id, id); mid = octstr_create(id); octstr_format_append(url, "&dlr-url=%E", conndata->dlr_url); /* encapsulate the original DLR-URL, escape code for DLR mask * and message id */ octstr_format_append(url, "%E%E%E%E%E", octstr_imm("&dlr-url="), sms->sms.dlr_url != NULL ? sms->sms.dlr_url : octstr_imm(""), octstr_imm("&dlr-mask=%d"), octstr_imm("&dlr-mid="), mid); octstr_destroy(mid); } else if (sms->sms.dlr_url != NULL) octstr_format_append(url, "&dlr-url=%E", sms->sms.dlr_url); if (sms->sms.dlr_mask != DLR_UNDEFINED && sms->sms.dlr_mask != DLR_NOTHING) octstr_format_append(url, "&dlr-mask=%d", sms->sms.dlr_mask); if (sms->sms.validity != SMS_PARAM_UNDEFINED) octstr_format_append(url, "&validity=%ld", (sms->sms.validity - time(NULL)) / 60); if (sms->sms.deferred != SMS_PARAM_UNDEFINED) octstr_format_append(url, "&deferred=%ld", (sms->sms.deferred - time(NULL)) / 60); headers = gwlist_create(); debug("smsc.http.kannel", 0, "HTTP[%s]: Start request", octstr_get_cstr(conn->id)); http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers, NULL, 0, sms, NULL); octstr_destroy(url); http_destroy_headers(headers); return 0; }
/* MT related function */ static int brunet_send_sms(SMSCConn *conn, Msg *sms) { ConnData *conndata = conn->data; Octstr *url, *tid, *xser; List *headers; char id[UUID_STR_LEN + 1]; int dcs; /* * Construct TransactionId. * Beware that brunet needs an "clean" octstr representation, * without the dashes in the string. So remove them. */ uuid_unparse(sms->sms.id, id); tid = octstr_create(id); octstr_replace(tid, octstr_imm("-"), octstr_imm("")); /* form the basic URL */ url = octstr_format("%S?MsIsdn=%E&Originator=%E", conndata->send_url, sms->sms.receiver, sms->sms.sender); /* * We use &binfo=<foobar> from sendsms interface to encode * additional paramters. If a mandatory value is not set, * a default value is applied */ if (octstr_len(sms->sms.binfo)) { octstr_url_decode(sms->sms.binfo); octstr_format_append(url, "&%S", sms->sms.binfo); } /* CustomerId */ if (octstr_search(url, octstr_create("CustomerId="), 0) == -1) { octstr_format_append(url, "&CustomerId=%S", conndata->username); } /* TransactionId */ if (octstr_search(url, octstr_create("TransactionId="), 0) == -1) { octstr_format_append(url, "&TransactionId=%S", tid); } /* SMSCount */ if (octstr_search(url, octstr_create("SMSCount="), 0) == -1) { octstr_format_append(url, "&%s", "SMSCount=1"); } /* ActionType */ if (octstr_search(url, octstr_create("ActionType="), 0) == -1) { octstr_format_append(url, "&%s", "ActionType=A"); } /* ServiceDeliveryType */ if (octstr_search(url, octstr_create("ServiceDeliveryType="), 0) == -1) { octstr_format_append(url, "&%s", "ServiceDeliveryType=P"); } /* if coding is not set and UDH exists, assume DC_8BIT * else default to DC_7BIT */ if (sms->sms.coding == DC_UNDEF) sms->sms.coding = octstr_len(sms->sms.udhdata) > 0 ? DC_8BIT : DC_7BIT; if (sms->sms.coding == DC_8BIT) octstr_format_append(url, "&MessageType=B&Text=%H", sms->sms.msgdata); else octstr_format_append(url, "&MessageType=S&Text=%E", sms->sms.msgdata); dcs = fields_to_dcs(sms, (sms->sms.alt_dcs != SMS_PARAM_UNDEFINED ? sms->sms.alt_dcs : 0)); /* XSer processing */ xser = octstr_create(""); /* XSer DCS values */ if (dcs != 0 && dcs != 4) octstr_format_append(xser, "0201%02x", dcs & 0xff); /* add UDH header */ if (octstr_len(sms->sms.udhdata)) { octstr_format_append(xser, "01%02x%H", octstr_len(sms->sms.udhdata), sms->sms.udhdata); } if (octstr_len(xser) > 0) octstr_format_append(url, "&XSer=%S", xser); octstr_destroy(xser); headers = http_create_empty_headers(); debug("smsc.http.brunet", 0, "HTTP[%s]: Sending request <%s>", octstr_get_cstr(conn->id), octstr_get_cstr(url)); /* * Brunet requires an SSL-enabled HTTP client call, this is handled * transparently by the Kannel HTTP layer module. */ http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers, NULL, 0, sms, NULL); octstr_destroy(url); octstr_destroy(tid); http_destroy_headers(headers); return 0; }
static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg) { List *pheaders; static unsigned char ct; /* Transaction counter -- do we need it? */ Octstr *to = NULL; Octstr *pduhdr = octstr_create(""); Octstr *s = NULL; info(0, "mms2mobile.startpush: notification to %s\n", octstr_get_cstr(rcpt_to)); if (!rcpt_to) { error(0, "mobilesender: Queue entry %s has no recipient address!", e->xqfname); goto done; } else to = octstr_duplicate(rcpt_to); ct++; octstr_append_char(pduhdr, ct); /* Pushd id */ octstr_append_char(pduhdr, 0x06); /* PUSH */ #if 1 octstr_append_char(pduhdr, 1 + 1 + 1); octstr_append_char(pduhdr, 0xbe); /* content type. */ #else octstr_append_char(pduhdr, 1 + 1 + sizeof "application/vnd.wap.mms-message"); /*header length. */ octstr_append_cstr(pduhdr, "application/vnd.wap.mms-message"); octstr_append_char(pduhdr, 0x0); /* string terminator. */ #endif octstr_append_char(pduhdr, 0xaf); /* push application ID header and value follows. */ octstr_append_char(pduhdr, 0x84); /* ... */ s = mms_tobinary(msg); if (isphonenum) { Octstr *url; octstr_url_encode(to); octstr_url_encode(s); #if 0 octstr_dump(pduhdr, 0); #endif octstr_url_encode(pduhdr); url = octstr_format("%S&text=%S%S&to=%S&udh=%%06%%05%%04%%0B%%84%%23%%F0", settings->sendsms_url, pduhdr, s, to); pheaders = http_create_empty_headers(); http_header_add(pheaders, "Connection", "close"); http_header_add(pheaders, "User-Agent", MM_NAME "/" MMSC_VERSION); http_start_request(httpcaller, HTTP_METHOD_GET, url, pheaders, NULL, 0, e, NULL); http_destroy_headers(pheaders); octstr_destroy(url); } else { /* An IP Address: Send packet, forget. */ Octstr *addr = udp_create_address(to, WAPPUSH_PORT); int sock = udp_client_socket(); if (sock > 0) { MmsEnvelopeTo *xto = gwlist_get(e->to,0); octstr_append(pduhdr, s); #if 0 octstr_dump(pduhdr, 0); #endif udp_sendto(sock, pduhdr, addr); close(sock); /* ?? */ mms_log2("Notify", octstr_imm("system"), to, -1, e ? e->msgId : NULL, NULL, NULL, "MM1", NULL,NULL); e = update_env_success(e, xto); } else { e = update_env_failed(e); error(0, "push to %s:%d failed: %s", octstr_get_cstr(to), WAPPUSH_PORT, strerror(errno)); } octstr_destroy(addr); if (e) settings->qfs->mms_queue_free_env(e); } done: octstr_destroy(to); octstr_destroy(pduhdr); octstr_destroy(s); }
static int sendNotify(MmsEnvelope *e) { Octstr *to; MmsMsg *msg, *smsg = NULL; MmsEnvelopeTo *xto = gwlist_get(e->to, 0); Octstr *err = NULL; time_t tnow = time(NULL); int j, k, len; Octstr *phonenum = NULL, *rcpt_ip = NULL, *msgId, *from, *fromproxy; int mtype, msize; int res = MMS_SEND_OK, dlr; time_t expiryt; char *prov_notify_event = NULL; char *rtype = NULL; if (e->lastaccess != 0) { /* This message has been fetched at least once, no more signals. */ e->sendt = e->expiryt + 3600*24*30*12; info(0, "MM1: Message [ID: %s] fetched/touched at least once. Skipping", e->xqfname); return settings->qfs->mms_queue_update(e); } if (!xto) { error(0, "mobilesender: Queue entry %s with no recipients!", e->xqfname); return 0; } msg = settings->qfs->mms_queue_getdata(e); to = octstr_duplicate(xto->rcpt); expiryt = e->expiryt; msgId = e->msgId ? octstr_duplicate(e->msgId) : NULL; from = octstr_duplicate(e->from); fromproxy = e->fromproxy ? octstr_duplicate(e->fromproxy) : NULL; msize = e->msize; dlr = e->dlr; if (e->expiryt != 0 && /* Handle message expiry. */ e->expiryt < tnow) { err = octstr_format("MMSC error: Message expired while sending to %S!", to); res = MMS_SEND_ERROR_FATAL; prov_notify_event = "failedfetch"; rtype = "Expired"; goto done; } else if (e->attempts >= settings->maxsendattempts) { err = octstr_format("MMSC error: Failed to deliver to %S after %ld attempts!", to, e->attempts); res = MMS_SEND_ERROR_FATAL; prov_notify_event = "failedfetch"; rtype = "Expired"; goto done; } j = octstr_case_search(to, octstr_imm("/TYPE=PLMN"), 0); k = octstr_case_search(to, octstr_imm("/TYPE=IPv"), 0); len = octstr_len(to); if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len) { /* A proper number. */ phonenum = octstr_copy(to, 0, j); #if 0 normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum); #else mms_normalize_phonenum(&phonenum, octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes); #endif } else if (k > 0 && k + sizeof "/TYPE=IPv" == len) rcpt_ip = octstr_copy(to, 0, k); else { /* We only handle phone numbers here. */ err = octstr_format("Unexpected recipient %s in MT queue!", octstr_get_cstr(to)); res = MMS_SEND_ERROR_FATAL; goto done; } mtype = mms_messagetype(msg); /* For phone, getting here means the message can be delivered. So: * - Check whether the recipient is provisioned, if not, wait (script called will queue creation req) * - If the recipient can't take MMS, then send SMS. */ /* We handle two types of requests: send and delivery/read notifications. * other types of messages cannot possibly be in this queue! */ if (mtype == MMS_MSGTYPE_SEND_REQ || mtype == MMS_MSGTYPE_RETRIEVE_CONF) { Octstr *url, *transid; if (phonenum) { int send_ind = mms_ind_send(settings->prov_getstatus, phonenum); if (send_ind < 0 && settings->notify_unprovisioned) send_ind = 0; if (send_ind < 0) { /* That is, recipient is not (yet) provisioned. */ res = MMS_SEND_ERROR_TRANSIENT; err = octstr_format("%S is not provisioned for MMS reception, delivery deferred!", phonenum); /* Do not increase delivery attempts counter. */ e->lasttry = tnow; e->sendt = e->lasttry + settings->send_back_off * (1 + e->attempts); if (settings->qfs->mms_queue_update(e) == 1) e = NULL; /* Queue entry gone. */ else settings->qfs->mms_queue_free_env(e); goto done; } else if (send_ind == 0) { /* provisioned but does not support */ Octstr *s = octstr_format(octstr_get_cstr(settings->mms_notify_txt), from); if (settings->notify_unprovisioned && s && octstr_len(s) > 0) { /* Only send if the string was set. */ List *pheaders; Octstr *sto = octstr_duplicate(phonenum); octstr_url_encode(s); octstr_url_encode(sto); url = octstr_format("%S&text=%S&to=%S",settings->sendsms_url,s, sto); pheaders = http_create_empty_headers(); http_header_add(pheaders, "Connection", "close"); http_header_add(pheaders, "User-Agent", MM_NAME "/" VERSION); http_start_request(httpcaller, HTTP_METHOD_GET, url, pheaders, NULL, 0, &edummy, NULL); http_destroy_headers(pheaders); octstr_destroy(url); octstr_destroy(sto); } else if (s) octstr_destroy(s); res = MMS_SEND_OK; err = octstr_imm("No MMS Ind support, sent SMS instead"); xto->process = 0; /* No more processing. */ if (settings->qfs->mms_queue_update(e) == 1) e = NULL; else settings->qfs->mms_queue_free_env(e); goto done; } } /* To get here means we can send Ind. */ url = mms_makefetchurl(e->xqfname, e->token, MMS_LOC_MQUEUE, phonenum ? phonenum : to, settings); info(0, "Preparing to notify client to fetch message at URL: %s", octstr_get_cstr(url)); transid = mms_maketransid(e->xqfname, settings->host_alias); smsg = mms_notification(msg, e->msize, url, transid, e->expiryt ? e->expiryt : tnow + settings->default_msgexpiry, settings->optimize_notification_size); octstr_destroy(transid); octstr_destroy(url); } else if (mtype == MMS_MSGTYPE_DELIVERY_IND || mtype == MMS_MSGTYPE_READ_ORIG_IND) smsg = msg; else { error(0, "Unexpected message type %s for %s found in MT queue!", mms_message_type_to_cstr(mtype), octstr_get_cstr(to)); res = MMS_SEND_ERROR_FATAL; goto done; } if (smsg) start_push(phonenum ? phonenum : rcpt_ip, phonenum ? 1 : 0, e, smsg); /* Send the message. * Don't touch 'e' after this point! * It may be freed by receive thread. */ if (smsg != msg && smsg) mms_destroy(smsg); done: if (err != NULL && res != MMS_SEND_ERROR_TRANSIENT) { /* If there was a report request and this is a legit error * queue it. */ if (dlr) { MmsMsg *m = mms_deliveryreport(msgId, to, tnow, rtype ? octstr_imm(rtype) : octstr_imm("Indeterminate")); List *l = gwlist_create(); Octstr *res; gwlist_append(l, from); /* Add to queue, switch via proxy to be from proxy. */ res = settings->qfs->mms_queue_add(to ? to : settings->system_user, l, err, NULL, fromproxy, tnow, tnow+settings->default_msgexpiry, m, NULL, NULL, NULL, NULL, NULL, NULL, 0, octstr_get_cstr(settings->mm1_queuedir), "MM2", settings->host_alias); gwlist_destroy(l, NULL); mms_destroy(m); octstr_destroy(res); } } /* Write to log */ info(0, "%s Mobile Queue MMS Send Notify: From=%s, to=%s, msgsize=%d, reason=%s", SEND_ERROR_STR(res), octstr_get_cstr(from), octstr_get_cstr(to), msize, err ? octstr_get_cstr(err) : ""); if (res == MMS_SEND_ERROR_FATAL) { xto->process = 0; /* No more attempts to deliver, delete this. */ if (settings->qfs->mms_queue_update(e) == 1) e = NULL; /* Queue entry gone. */ else settings->qfs->mms_queue_free_env(e); } /* Else queue will be updated/freed elsewhere. */ if (prov_notify_event) notify_prov_server(octstr_get_cstr(settings->prov_notify), to ? octstr_get_cstr(to) : "unknown", prov_notify_event, rtype ? rtype : "", e ? e->msgId : NULL, NULL, NULL); if (msg) mms_destroy(msg); octstr_destroy(phonenum); octstr_destroy(rcpt_ip); octstr_destroy(to); octstr_destroy(msgId); octstr_destroy(fromproxy); octstr_destroy(from); octstr_destroy(err); return 1; }
/* * Try log in defined number of times, when got response 401 and authentica- * tion info is in headers. */ static int receive_push_reply(HTTPCaller *caller) { void *id; long *trid; int http_status, tries; List *reply_headers; Octstr *final_url, *auth_url, *reply_body, *os, *push_content, *auth_reply_body; WAPEvent *e; List *retry_headers; http_status = HTTP_UNAUTHORIZED; tries = 0; id = http_receive_result(caller, &http_status, &final_url, &reply_headers, &reply_body); if (id == NULL || http_status == -1 || final_url == NULL) { error(0, "push failed, no reason found"); goto push_failed; } while (use_headers && http_status == HTTP_UNAUTHORIZED && tries < retries) { debug("test.ppg", 0, "try number %d", tries); debug("test.ppg", 0, "authentication failure, get a challenge"); http_destroy_headers(reply_headers); push_content = push_content_create(); retry_headers = push_headers_create(octstr_len(push_content)); http_add_basic_auth(retry_headers, username, password); trid = gw_malloc(sizeof(long)); *trid = tries; http_start_request(caller, HTTP_METHOD_POST, final_url, retry_headers, push_content, 0, trid, NULL); debug("test.ppg ", 0, "TEST_PPG: doing response to %s", octstr_get_cstr(final_url)); octstr_destroy(push_content); http_destroy_headers(retry_headers); trid = http_receive_result(caller, &http_status, &auth_url, &reply_headers, &auth_reply_body); if (trid == NULL || http_status == -1 || auth_url == NULL) { error(0, "unable to send authorisation, no reason found"); goto push_failed; } debug("test.ppg", 0, "TEST_PPG: send authentication to %s, retry %ld", octstr_get_cstr(auth_url), *(long *) trid); gw_free(trid); octstr_destroy(auth_reply_body); octstr_destroy(auth_url); ++tries; } if (http_status == HTTP_NOT_FOUND) { error(0, "push failed, service not found"); goto push_failed; } if (http_status == HTTP_FORBIDDEN) { error(0, "push failed, service forbidden"); goto push_failed; } if (http_status == HTTP_UNAUTHORIZED) { if (use_headers) error(0, "tried %ld times, stopping", retries); else error(0, "push failed, authorisation failure"); goto push_failed; } debug("test.ppg", 0, "TEST_PPG: push %ld done: reply from, %s", *(long *) id, octstr_get_cstr(final_url)); gw_free(id); octstr_destroy(final_url); if (verbose) debug("test.ppg", 0, "TEST_PPG: reply headers were"); while ((os = gwlist_extract_first(reply_headers)) != NULL) { if (verbose) octstr_dump(os, 0); octstr_destroy(os); } if (verbose) { debug("test.ppg", 0, "TEST_PPG: reply body was"); octstr_dump(reply_body, 0); } e = NULL; if (pap_compile(reply_body, &e) < 0) { warning(0, "TEST_PPG: receive_push_reply: cannot compile pap message"); goto parse_error; } switch (e->type) { case Push_Response: debug("test.ppg", 0, "TEST_PPG: and type push response"); break; case Bad_Message_Response: debug("test.ppg", 0, "TEST_PPG: and type bad message response"); break; default: warning(0, "TEST_PPG: unknown event received from %s", octstr_get_cstr(final_url)); break; } octstr_destroy(reply_body); wap_event_destroy(e); http_destroy_headers(reply_headers); return 0; push_failed: gw_free(id); octstr_destroy(final_url); octstr_destroy(reply_body); http_destroy_headers(reply_headers); return -1; parse_error: octstr_destroy(reply_body); http_destroy_headers(reply_headers); wap_event_destroy(e); return -1; }