63 #include <sys/types.h> 64 #include <sys/socket.h> 82 #include "SendSmsBinding.nsmap" 94 #define DEFAULT_CHARSET "UTF-8" 111 List *sender_threads;
125 static void octstr_remove_crlfs(
Octstr *ostr);
126 static void soap_send_sms(
struct soap *soap,
SMSCConn *conn,
Msg *sms);
128 static void soap_send_dlr(
struct soap *soap,
SMSCConn *conn,
Msg *sms);
139 static struct StateTable {
141 enum pxSms__DeliveryStatus state;
143 #define ENTRY(mask, state) { mask, state }, 144 ENTRY(
DLR_SUCCESS, pxSms__DeliveryStatus__DeliveredToTerminal)
145 ENTRY(
DLR_FAIL, pxSms__DeliveryStatus__DeliveryImpossible)
146 ENTRY(
DLR_BUFFERED, pxSms__DeliveryStatus__DeliveredToNetwork)
147 ENTRY(
DLR_SMSC_FAIL, pxSms__DeliveryStatus__DeliveryNotificationNotSupported)
148 ENTRY(
DLR_FAIL, pxSms__DeliveryStatus__DeliveryUncertain)
149 ENTRY(
DLR_BUFFERED, pxSms__DeliveryStatus__MessageWaiting)
153 static int state_table_entries =
sizeof(state_table) /
sizeof(state_table[0]);
178 static void httpsmsc_sender_ercisson_sdp(
void *arg)
189 soap = soap_new1(SOAP_XML_INDENT|SOAP_IO_KEEPALIVE);
192 soap_register_plugin(soap, soap_wsse);
196 if (soap_ssl_client_context(soap, SOAP_SSL_NO_AUTHENTICATION,
197 NULL, NULL, NULL, NULL, NULL)) {
201 soap_sprint_fault(soap, buf, 1024);
203 octstr_remove_crlfs(os);
205 error(0,
"SOAP[%s]: Could not assign gSOAP SSL context:",
207 error(0,
"SOAP[%s]: %s",
219 soap_wsse_add_Timestamp(soap,
"Time", 10);
222 soap_wsse_add_UsernameTokenDigest(soap,
"User",
225 soap_send_sms(soap, conn,
msg);
229 soap_wsse_delete_Security(soap);
240 static void httpsmsc_sender_gsma_oneapi(
void *arg)
251 soap = soap_new1(SOAP_XML_INDENT|SOAP_IO_KEEPALIVE);
259 if (soap_ssl_client_context(soap, SOAP_SSL_NO_AUTHENTICATION,
260 NULL, NULL, NULL, NULL, NULL)) {
264 soap_sprint_fault(soap, buf, 1024);
266 octstr_remove_crlfs(os);
268 error(0,
"SOAP[%s]: Could not assign gSOAP SSL context:",
270 error(0,
"SOAP[%s]: %s",
280 soap_send_sms(soap, conn,
msg);
301 List *headers, *cgivars;
303 ip =
url = body = NULL;
304 headers = cgivars = NULL;
314 &headers, &body, &cgivars);
318 debug(
"smsc.soap", 0,
"SOAP[%s]: Got HTTP request `%s'",
322 info(0,
"SOAP[%s]: Connection `%s' tried from denied " 329 debug(
"smsc.soap", 0,
"SOAP[%s]: Destroying client information",
337 debug(
"smsc.soap", 0,
"SOAP[%s]: httpsmsc_receiver dying",
350 static void dlr_sender(
void *arg)
361 soap = soap_new1(SOAP_XML_INDENT|SOAP_IO_KEEPALIVE);
365 if (soap_ssl_client_context(soap, SOAP_SSL_NO_AUTHENTICATION,
366 NULL, NULL, NULL, NULL, NULL)) {
370 soap_sprint_fault(soap, buf, 1024);
372 octstr_remove_crlfs(os);
374 error(0,
"SOAP[%s]: Could not assign gSOAP SSL context:",
376 error(0,
"SOAP[%s]: %s",
387 soap_send_dlr(soap, conn,
msg);
404 #define octstr_cstr(os) \ 405 (os ? octstr_get_cstr(os) : NULL) 408 (os ? octstr_create(os) : NULL) 411 static int iscrlf(
unsigned char c)
413 return c ==
'\n' || c ==
'\r';
417 static void octstr_remove_crlfs(
Octstr *ostr)
423 for (i = 0; i < end; i++) {
430 static void gw_free_wrapper(
void *data)
440 typedef struct gBuffer {
448 static gBuffer *gbuffer_create(
SMSCConn *conn,
size_t size)
452 buf = gw_malloc(
sizeof(gBuffer));
454 buf->buffer = gw_malloc(
size);
456 buf->rlen = buf->slen = 0;
462 static void gbuffer_destroy(gBuffer *buf)
467 gw_free(buf->buffer);
477 static int mysend(
struct soap *soap,
const char *s,
size_t n)
479 gBuffer *buf = (gBuffer*) soap->user;
481 if (buf->slen + n > buf->size)
484 strcpy(buf->buffer + buf->slen, s);
496 static size_t myrecv(
struct soap *soap,
char *s,
size_t n)
498 gBuffer *buf = (gBuffer*) soap->user;
500 strncpy(s, buf->buffer + buf->rlen, n);
511 static int myheader(
struct soap *soap,
const char *key,
const char *value)
521 static void soap_send_sms(
struct soap *soap,
SMSCConn *conn,
Msg *sms)
524 struct pxSmsSend__sendSmsResponse resp;
529 const char *receiv[1];
532 struct pxSmsSend__sendSms req;
533 struct pxCommon__ChargingInformation charge;
534 struct pxCommon__SimpleReference dlr;
542 req.__sizeaddresses = 1;
545 req.addresses = (
char**)receiv;
546 req.senderName = octstr_cstr(sms->sms.sender);
549 req.receiptRequest = NULL;
560 if (sms->sms.binfo) {
564 error(0,
"SOAP[%s]: Billing identifier <%s> has wrong format!",
571 req.charging = &charge;
584 dlr.interfaceName = NULL;
585 req.receiptRequest = &dlr;
589 ret = soap_call___px1__sendSms(
598 soap_sprint_fault(soap, buf, 1024);
600 octstr_remove_crlfs(os);
602 error(0,
"SOAP[%s]: Sending HTTP request failed:",
604 error(0,
"SOAP[%s]: %s",
729 buf = gbuffer_create(conn, 32000);
734 soap->fsend = mysend;
735 soap->frecv = myrecv;
736 soap->fposthdr = myheader;
747 gbuffer_destroy(buf);
757 http_header_add(reply_headers,
"Content-Type",
"text/xml;charset=\"utf-8\"");
758 debug(
"smsc.soap", 0,
"SOAP[%s]: Sending HTTP response",
768 static void soap_send_sms_cb(
SMSCConn *conn,
Msg *sms)
777 static void soap_send_dlr(
struct soap *soap,
SMSCConn *conn,
Msg *sms)
780 struct pxSmsNotification__notifySmsDeliveryReceiptResponse resp;
787 struct pxSmsNotification__notifySmsDeliveryReceipt req;
788 struct pxSms__DeliveryInformation deliveryStatus;
799 deliveryStatus.deliveryStatus = pxSms__DeliveryStatus__DeliveredToTerminal;
800 req.deliveryStatus = &deliveryStatus;
805 ret = soap_call___px2__notifySmsDeliveryReceipt(
813 soap_sprint_fault(soap, buf, 1024);
815 octstr_remove_crlfs(os);
817 error(0,
"SOAP[%s]: Sending DLR HTTP request failed:",
819 error(0,
"SOAP[%s]: %s",
826 debug(
"smsc.soap",0,
"SOAP[%s] Received DLR HTTP response.",
879 error(0,
"Failed to convert msgdata from charset <%s> to <%s>, will send as is.",
907 debug(
"httpsmsc_shutdown", 0,
"SOAP[%s]: Shutting down",
947 error(0,
"SOAP[%s]: 'port' invalid in 'smsc = parlayx' group.",
953 error(0,
"SOAP[%s]: 'system-type' missing in 'smsc = parlayx' group.",
969 info(0,
"SOAP[%s]: Using %ld sender threads.",
974 panic(0,
"SOAP[%s]: Sending not allowed. No 'send-url' specified.",
978 warning(0,
"SOAP[%s]: DLR requesting not allowed. No 'dlr-url' specified.",
982 error(0,
"SOAP[%s]: 'username' and 'password' required for smsc",
988 conndata->httpsmsc_sender = httpsmsc_sender_ercisson_sdp;
991 conndata->httpsmsc_sender = httpsmsc_sender_gsma_oneapi;
997 error(0,
"SOAP[%s]: system-type '%s' unknown in 'smsc = parlayx' group.",
1011 conndata->receive_sms = soap_receive_sms;
1012 conndata->send_sms = soap_send_sms_cb;
1013 conndata->parse_reply = soap_parse_reply;
1053 for (i = 0; i <
conndata->senders; i++) {
1054 long *
id = gw_malloc(
sizeof(
long));
1068 error(0,
"SOAP[%s]: Failed to create smsc connection",
1090 int __px1__sendSms (
1094 struct pxSmsSend__sendSms *req,
1096 struct pxSmsSend__sendSmsResponse *resp)
1099 resp->result =
"100";
1110 int __px2__notifySmsDeliveryReceipt (
1114 struct pxSmsNotification__notifySmsDeliveryReceipt *req,
1116 struct pxSmsNotification__notifySmsDeliveryReceiptResponse *resp)
1118 gBuffer *buf = soap->user;
1121 Octstr *id, *destination;
1122 int sm_status, state, i;
1128 id = octstr(req->correlator);
1129 if (req->deliveryStatus) {
1130 destination = octstr(req->deliveryStatus->address);
1136 sm_status = req->deliveryStatus->deliveryStatus;
1141 for (i = 0; sm_status != -1 && i < state_table_entries; ++i) {
1142 if (sm_status == state_table[i].state) {
1143 state = state_table[i].dlr_mask;
1154 if (dlrmsg != NULL) {
1167 error(0,
"SOAP[%s]: got DLR but could not find message or was not interested " 1168 "in it id<%s> dst<%s>, type<%d>",
1180 int __px2__notifySmsReception (
1184 struct pxSmsNotification__notifySmsReception *req,
1186 struct pxSmsNotification__notifySmsReceptionResponse *resp)
1188 gBuffer *buf = soap->user;
1194 msg->sms.sms_type =
mo;
1195 msg->sms.sender = octstr(req->message->senderAddress);
1196 msg->sms.receiver = octstr(req->message->smsServiceActivationNumber);
1197 msg->sms.msgdata = octstr(req->message->message);
1198 msg->sms.foreign_id = octstr(req->correlator);
1200 msg->sms.time = time(NULL);
1218 int __px1__sendSmsLogo(
1221 struct pxSmsSend__sendSmsLogo* pxSmsSend__sendSmsLogo,
1223 struct pxSmsSend__sendSmsLogoResponse* pxSmsSend__sendSmsLogoResponse
1229 int __px1__sendSmsRingtone(
1232 struct pxSmsSend__sendSmsRingtone* pxSmsSend__sendSmsRingtone,
1234 struct pxSmsSend__sendSmsRingtoneResponse* pxSmsSend__sendSmsRingtoneResponse
1240 int __px1__getSmsDeliveryStatus(
1243 struct pxSmsSend__getSmsDeliveryStatus* pxSmsSend__getSmsDeliveryStatus,
1245 struct pxSmsSend__getSmsDeliveryStatusResponse* pxSmsSend__getSmsDeliveryStatusResponse
1251 int __px3__getReceivedSms(
1254 struct pxSmsReceive__getReceivedSms* pxSmsReceive__getReceivedSms,
1256 struct pxSmsReceive__getReceivedSmsResponse* pxSmsReceive__getReceivedSmsResponse
void error(int err, const char *fmt,...)
void info(int err, const char *fmt,...)
Msg * msg_duplicate(Msg *msg)
static void httpsmsc_receiver(void *arg)
void octstr_append_data(Octstr *ostr, const char *data, long len)
static void conndata_destroy(ConnData *conndata)
static int iscrlf(unsigned char c)
void http_header_add(List *headers, char *name, char *contents)
void http_caller_signal_shutdown(HTTPCaller *caller)
void http_close_client(HTTPClient *client)
void bb_smscconn_killed(void)
void gwlist_produce(List *list, void *item)
void gwthread_join(long thread)
long gwlist_len(List *list)
static void client(int port)
void * gwlist_get(List *list, long pos)
void * gw_prioqueue_consume(gw_prioqueue_t *queue)
#define cfg_get(grp, varname)
void uuid_unparse(const uuid_t uu, char *out)
#define gw_prioqueue_produce(queue, item)
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
#define octstr_get_cstr(ostr)
#define octstr_copy(ostr, from, len)
int connect_denied(Octstr *allow_ip, Octstr *ip)
void log_thread_to(int idx)
smscconn_killed_t why_killed
void http_destroy_headers(List *headers)
int uuid_parse(const char *in, uuid_t uu)
void http_destroy_cgiargs(List *args)
void msg_destroy_item(void *msg)
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Octstr * octstr_imm(const char *cstr)
int sms_priority_compare(const void *a, const void *b)
HTTPClient * http_accept_request(int port, Octstr **client_ip, Octstr **url, List **headers, Octstr **body, List **cgivars)
void http_close_port(int port)
void gwlist_remove_producer(List *list)
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
int uuid_is_null(const uuid_t uu)
#define octstr_duplicate(ostr)
#define octstr_dump(ostr, level,...)
void msg_destroy(Msg *msg)
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
void warning(int err, const char *fmt,...)
Octstr * octstr_format(const char *fmt,...)
void octstr_destroy(Octstr *ostr)
#define gwthread_create(func, arg)
#define octstr_create(cstr)
void octstr_destroy_item(void *os)
gw_prioqueue_t * gw_prioqueue_create(int(*cmp)(const void *, const void *))
void gwthread_sleep(double seconds)
static int httpsmsc_shutdown(SMSCConn *conn, int finish_sending)
int http_open_port_if(int port, int ssl, Octstr *interface)
long octstr_len(const Octstr *ostr)
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
void gw_prioqueue_destroy(gw_prioqueue_t *queue, void(*item_destroy)(void *))
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
void * gwlist_consume(List *list)
static long httpsmsc_queued(SMSCConn *conn)
int(* shutdown)(SMSCConn *conn, int finish_sending)
void gw_prioqueue_remove_producer(gw_prioqueue_t *queue)
void debug(const char *place, int err, const char *fmt,...)
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
HTTPCaller * http_caller_create(void)
long(* queued)(SMSCConn *conn)
int(* send_msg)(SMSCConn *conn, Msg *msg)
static int httpsmsc_send(SMSCConn *conn, Msg *msg)
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
void http_caller_destroy(HTTPCaller *caller)
void gwlist_add_producer(List *list)
static int response(List *push_headers, Octstr **username, Octstr **password)
static void httpsmsc_sender(void *arg)
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
int octstr_get_char(const Octstr *ostr, long pos)
void octstr_set_char(Octstr *ostr, long pos, int ch)
#define DLR_IS_ENABLED_DEVICE(dlr)
List * octstr_split(const Octstr *os, const Octstr *sep)
static XMLRPCDocument * msg
void gw_prioqueue_add_producer(gw_prioqueue_t *queue)
void uuid_clear(uuid_t uu)
int charset_convert(Octstr *string, char *charset_from, char *charset_to)
void octstr_delete_matching(Octstr *haystack, Octstr *needle)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)