Kannel: Open Source WAP and SMS gateway  svn-r5335
generic.c File Reference
#include "gwlib/gwlib.h"
#include "smscconn.h"
#include "smscconn_p.h"
#include "bb_smscconn_cb.h"
#include "msg.h"
#include "sms.h"
#include "dlr.h"
#include "urltrans.h"
#include "meta_data.h"
#include "../smsc_http_p.h"

Go to the source code of this file.

Data Structures

struct  fieldmap
 
struct  generic_values
 

Functions

static void fieldmap_destroy (struct fieldmap *fieldmap)
 
static struct fieldmapgeneric_get_field_map (CfgGroup *grp)
 
static void generic_receive_sms (SMSCConn *conn, HTTPClient *client, List *headers, Octstr *body, List *cgivars)
 
static void convert_charset (Msg *msg, Octstr *charset, Octstr **content_type)
 
static int generic_send_sms (SMSCConn *conn, Msg *sms)
 
static void generic_parse_reply (SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body)
 
static int generic_init (SMSCConn *conn, CfgGroup *cfg)
 
static void generic_destroy (SMSCConn *conn)
 

Variables

struct smsc_http_fn_callbacks smsc_http_generic_callback
 

Function Documentation

◆ convert_charset()

static void convert_charset ( Msg msg,
Octstr charset,
Octstr **  content_type 
)
static

Definition at line 466 of file generic.c.

References charset, charset_convert(), content_type, DC_7BIT, DC_8BIT, DC_UCS2, error(), msg, octstr_format(), and octstr_get_cstr.

Referenced by generic_send_sms().

467 {
468  switch (msg->sms.coding) {
469  case DC_7BIT:
470  default:
471  if (charset_convert(msg->sms.msgdata, "UTF-8", octstr_get_cstr(charset)) == 0) {
472  *content_type = octstr_format("application/x-www-form-urlencoded; charset=\"%s\"",
474  } else {
475  error(0, "Failed to convert msgdata from UTF-8 to %s, will leave as is",
477  *content_type = octstr_format("application/x-www-form-urlencoded; charset=\"UTF-8\"");
478  }
479  break;
480  case DC_UCS2:
481  if (charset_convert(msg->sms.msgdata, "UTF-16BE", octstr_get_cstr(charset)) == 0) {
482  *content_type = octstr_format("application/x-www-form-urlencoded; charset=\"%s\"",
484  } else {
485  error(0, "Failed to convert msgdata from UCS-2 to %s, will leave as is",
487  *content_type = octstr_format("application/x-www-form-urlencoded; charset=\"UTF-16BE\"");
488  }
489  break;
490  case DC_8BIT:
491  *content_type = octstr_format("application/x-www-form-urlencoded");
492  break;
493  }
494 }
void error(int err, const char *fmt,...)
Definition: log.c:648
#define DC_8BIT
Definition: sms.h:111
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * charset
Definition: test_ota.c:68
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
const char * content_type
Definition: fakewap.c:249
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define DC_UCS2
Definition: sms.h:112
int charset_convert(Octstr *string, char *charset_from, char *charset_to)
Definition: charset.c:589
#define DC_7BIT
Definition: sms.h:110

◆ fieldmap_destroy()

static void fieldmap_destroy ( struct fieldmap fieldmap)
static

Definition at line 152 of file generic.c.

References fieldmap::account, fieldmap::binfo, fieldmap::coding, fieldmap::deferred, fieldmap::dlr_err, fieldmap::dlr_mask, fieldmap::dlr_mid, fieldmap::dlr_url, fieldmap::flash, fieldmap::foreign_id, fieldmap::from, fieldmap::mclass, fieldmap::message_sent, fieldmap::meta_data, fieldmap::mwi, octstr_destroy(), fieldmap::password, fieldmap::service, fieldmap::text, fieldmap::to, fieldmap::udh, fieldmap::username, and fieldmap::validity.

Referenced by generic_destroy().

153 {
154  if (fieldmap == NULL)
155  return;
178  gw_free(fieldmap);
179 }
Octstr * to
Definition: generic.c:110
Octstr * text
Definition: generic.c:111
Octstr * validity
Definition: generic.c:125
Octstr * account
Definition: generic.c:114
Octstr * message_sent
Definition: generic.c:128
Octstr * deferred
Definition: generic.c:126
Octstr * dlr_mask
Definition: generic.c:117
Octstr * flash
Definition: generic.c:121
Octstr * binfo
Definition: generic.c:115
Octstr * dlr_mid
Definition: generic.c:120
Octstr * dlr_url
Definition: generic.c:119
Octstr * foreign_id
Definition: generic.c:127
Octstr * mclass
Definition: generic.c:122
Octstr * service
Definition: generic.c:113
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
Octstr * meta_data
Definition: generic.c:116
Octstr * coding
Definition: generic.c:124
Octstr * from
Definition: generic.c:109
Octstr * udh
Definition: generic.c:112
Octstr * username
Definition: generic.c:107
Octstr * dlr_err
Definition: generic.c:118
Octstr * mwi
Definition: generic.c:123
Octstr * password
Definition: generic.c:108

◆ generic_destroy()

static void generic_destroy ( SMSCConn conn)
static

Definition at line 666 of file generic.c.

References conndata::data, smscconn::data, debug(), fieldmap_destroy(), generic_values::generic_foreign_id_regex, generic_values::map, generic_values::permfail_regex, generic_values::success_regex, and generic_values::tempfail_regex.

667 {
669  struct generic_values *values;
670 
671  if (conn == NULL || conn->data == NULL)
672  return;
673 
674  conndata = conn->data;
675  values = conndata->data;
676 
677  fieldmap_destroy(values->map);
678  if (values->success_regex)
679  gw_regex_destroy(values->success_regex);
680  if (values->permfail_regex)
681  gw_regex_destroy(values->permfail_regex);
682  if (values->tempfail_regex)
683  gw_regex_destroy(values->tempfail_regex);
684  if (values->generic_foreign_id_regex)
685  gw_regex_destroy(values->generic_foreign_id_regex);
686 
687  gw_free(values);
688  conndata->data = NULL;
689 
690  debug("", 0, "generic destroy completed");
691 }
void * data
Definition: smsc_http_p.h:114
void * data
Definition: smscconn_p.h:250
regex_t * success_regex
Definition: generic.c:140
regex_t * permfail_regex
Definition: generic.c:141
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static void fieldmap_destroy(struct fieldmap *fieldmap)
Definition: generic.c:152
regex_t * generic_foreign_id_regex
Definition: generic.c:146
struct fieldmap * map
Definition: generic.c:134
regex_t * tempfail_regex
Definition: generic.c:142

◆ generic_get_field_map()

static struct fieldmap* generic_get_field_map ( CfgGroup grp)
static

Definition at line 185 of file generic.c.

References fieldmap::account, fieldmap::binfo, cfg_get, cfg_get_integer(), fieldmap::coding, fieldmap::deferred, fieldmap::dlr_err, fieldmap::dlr_mask, fieldmap::dlr_mid, fieldmap::dlr_url, fieldmap::flash, fieldmap::foreign_id, fieldmap::from, gw_assert(), HTTP_ACCEPTED, fieldmap::mclass, fieldmap::message_sent, fieldmap::meta_data, fieldmap::mwi, octstr_create, octstr_imm(), fieldmap::password, fieldmap::service, fieldmap::status_error, fieldmap::status_sent, fieldmap::text, fieldmap::to, fieldmap::udh, fieldmap::username, and fieldmap::validity.

Referenced by generic_init().

186 {
187  struct fieldmap *fm = NULL;
188 
189  fm = gw_malloc(sizeof(*fm));
190  gw_assert(fm != NULL);
191 
192  fm->username = cfg_get(grp, octstr_imm("generic-param-username"));
193  if (fm->username == NULL)
194  fm->username = octstr_create("username");
195  fm->password = cfg_get(grp, octstr_imm("generic-param-password"));
196  if (fm->password == NULL)
197  fm->password = octstr_create("password");
198  fm->from = cfg_get(grp, octstr_imm("generic-param-from"));
199  if (fm->from == NULL)
200  fm->from = octstr_create("from");
201  fm->to = cfg_get(grp, octstr_imm("generic-param-to"));
202  if (fm->to == NULL)
203  fm->to = octstr_create("to");
204  fm->text = cfg_get(grp, octstr_imm("generic-param-text"));
205  if (fm->text == NULL)
206  fm->text = octstr_create("text");
207  fm->udh = cfg_get(grp, octstr_imm("generic-param-udh"));
208  if (fm->udh == NULL)
209  fm->udh = octstr_create("udh");
210  /* "service" preloads the "username" parameter to mimic former behaviour */
211  fm->service = cfg_get(grp, octstr_imm("generic-param-service"));
212  if (fm->service == NULL)
213  fm->service = octstr_create("username");
214  fm->account = cfg_get(grp, octstr_imm("generic-param-account"));
215  if (fm->account == NULL)
216  fm->account = octstr_create("account");
217  fm->binfo = cfg_get(grp, octstr_imm("generic-param-binfo"));
218  if (fm->binfo == NULL)
219  fm->binfo = octstr_create("binfo");
220  fm->dlr_mask = cfg_get(grp, octstr_imm("generic-param-dlr-mask"));
221  if (fm->dlr_mask == NULL)
222  fm->dlr_mask = octstr_create("dlr-mask");
223  fm->dlr_err = cfg_get(grp, octstr_imm("generic-param-dlr-err"));
224  if (fm->dlr_err == NULL)
225  fm->dlr_err = octstr_create("dlr-err");
226  fm->dlr_url = cfg_get(grp, octstr_imm("generic-param-dlr-url"));
227  if (fm->dlr_url == NULL)
228  fm->dlr_url = octstr_create("dlr-url");
229  fm->dlr_mid = cfg_get(grp, octstr_imm("generic-param-dlr-mid"));
230  if (fm->dlr_mid == NULL)
231  fm->dlr_mid = octstr_create("dlr-mid");
232  fm->flash = cfg_get(grp, octstr_imm("generic-param-flash"));
233  if (fm->flash == NULL)
234  fm->flash = octstr_create("flash");
235  fm->mclass = cfg_get(grp, octstr_imm("generic-param-mclass"));
236  if (fm->mclass == NULL)
237  fm->mclass = octstr_create("mclass");
238  fm->mwi = cfg_get(grp, octstr_imm("generic-param-mwi"));
239  if (fm->mwi == NULL)
240  fm->mwi = octstr_create("mwi");
241  fm->coding = cfg_get(grp, octstr_imm("generic-param-coding"));
242  if (fm->coding == NULL)
243  fm->coding = octstr_create("coding");
244  fm->validity = cfg_get(grp, octstr_imm("generic-param-validity"));
245  if (fm->validity == NULL)
246  fm->validity = octstr_create("validity");
247  fm->deferred = cfg_get(grp, octstr_imm("generic-param-deferred"));
248  if (fm->deferred == NULL)
249  fm->deferred = octstr_create("deferred");
250  fm->foreign_id = cfg_get(grp, octstr_imm("generic-param-foreign-id"));
251  if (fm->foreign_id == NULL)
252  fm->foreign_id = octstr_create("foreign-id");
253  fm->meta_data = cfg_get(grp, octstr_imm("generic-param-meta-data"));
254  if (fm->meta_data == NULL)
255  fm->meta_data = octstr_create("meta-data");
256  fm->message_sent = cfg_get(grp, octstr_imm("generic-message-sent"));
257  if (fm->message_sent == NULL)
258  fm->message_sent = octstr_create("Sent");
259  /* both success and error uses HTTP_ACCEPTED to mimic former behaviour */
260  if (cfg_get_integer(&fm->status_sent, grp, octstr_imm("generic-status-sent")) == -1) {
262  }
263  if (cfg_get_integer(&fm->status_error, grp, octstr_imm("generic-status-error")) == -1) {
265  }
266 
267  return fm;
268 }
Octstr * to
Definition: generic.c:110
Octstr * text
Definition: generic.c:111
Octstr * validity
Definition: generic.c:125
Octstr * account
Definition: generic.c:114
gw_assert(wtls_machine->packet_to_send !=NULL)
Octstr * message_sent
Definition: generic.c:128
Octstr * deferred
Definition: generic.c:126
#define cfg_get(grp, varname)
Definition: cfg.h:86
Octstr * dlr_mask
Definition: generic.c:117
Octstr * flash
Definition: generic.c:121
Octstr * binfo
Definition: generic.c:115
Octstr * dlr_mid
Definition: generic.c:120
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Octstr * dlr_url
Definition: generic.c:119
Octstr * foreign_id
Definition: generic.c:127
Octstr * mclass
Definition: generic.c:122
Octstr * service
Definition: generic.c:113
#define octstr_create(cstr)
Definition: octstr.h:125
Octstr * meta_data
Definition: generic.c:116
Octstr * coding
Definition: generic.c:124
Octstr * from
Definition: generic.c:109
Octstr * udh
Definition: generic.c:112
Octstr * username
Definition: generic.c:107
Octstr * dlr_err
Definition: generic.c:118
Octstr * mwi
Definition: generic.c:123
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
Octstr * password
Definition: generic.c:108
long status_error
Definition: generic.c:130
long status_sent
Definition: generic.c:129

◆ generic_init()

static int generic_init ( SMSCConn conn,
CfgGroup cfg 
)
static

Definition at line 613 of file generic.c.

References cfg, cfg_get, conndata::data, smscconn::data, debug(), error(), generic_values::generic_foreign_id_regex, generic_get_field_map(), smscconn::id, generic_values::map, octstr_destroy(), octstr_get_cstr, octstr_imm(), octstr_search_char(), panic, generic_values::permfail_regex, generic_values::success_regex, generic_values::tempfail_regex, and warning().

614 {
615  Octstr *os;
616  ConnData *conndata = conn->data;
617  struct generic_values *values;
618 
619  conndata->data = values = gw_malloc(sizeof(*values));
620  /* reset */
621  memset(conndata->data, 0, sizeof(*values));
622 
623  values->success_regex = values->permfail_regex = values->tempfail_regex = NULL;
624  values->generic_foreign_id_regex = NULL;
625 
626  values->map = generic_get_field_map(cfg);
627 
628  /* pre-compile regex expressions */
629  if ((os = cfg_get(cfg, octstr_imm("status-success-regex"))) != NULL) {
630  if ((values->success_regex = gw_regex_comp(os, REG_EXTENDED|REG_NOSUB)) == NULL)
631  error(0, "HTTP[%s]: Could not compile pattern '%s' defined for variable 'status-success-regex'",
632  octstr_get_cstr(conn->id), octstr_get_cstr(os));
633  octstr_destroy(os);
634  } else {
635  /* we need at least the criteria for a successful sent */
636  error(0, "HTTP[%s]: 'status-success-regex' required for generic http smsc",
637  octstr_get_cstr(conn->id));
638  return -1;
639  }
640  if ((os = cfg_get(cfg, octstr_imm("status-permfail-regex"))) != NULL) {
641  if ((values->permfail_regex = gw_regex_comp(os, REG_EXTENDED|REG_NOSUB)) == NULL)
642  panic(0, "Could not compile pattern '%s' defined for variable 'status-permfail-regex'", octstr_get_cstr(os));
643  octstr_destroy(os);
644  }
645  if ((os = cfg_get(cfg, octstr_imm("status-tempfail-regex"))) != NULL) {
646  if ((values->tempfail_regex = gw_regex_comp(os, REG_EXTENDED|REG_NOSUB)) == NULL)
647  panic(0, "Could not compile pattern '%s' defined for variable 'status-tempfail-regex'", octstr_get_cstr(os));
648  octstr_destroy(os);
649  }
650  if ((os = cfg_get(cfg, octstr_imm("generic-foreign-id-regex"))) != NULL) {
651  if ((values->generic_foreign_id_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
652  panic(0, "Could not compile pattern '%s' defined for variable 'generic-foreign-id-regex'", octstr_get_cstr(os));
653  else {
654  /* check quickly that at least 1 group seems to be defined in the regex */
655  if (octstr_search_char(os, '(', 0) == -1 || octstr_search_char(os, ')', 0) == -1)
656  warning(0, "HTTP[%s]: No group defined in pattern '%s' for variable 'generic-foreign-id-regex'", octstr_get_cstr(conn->id), octstr_get_cstr(os));
657  }
658  octstr_destroy(os);
659  }
660 
661  debug("", 0, "generic init completed");
662 
663  return 0;
664 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void * data
Definition: smsc_http_p.h:114
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:250
#define cfg_get(grp, varname)
Definition: cfg.h:86
regex_t * success_regex
Definition: generic.c:140
static Cfg * cfg
Definition: opensmppbox.c:95
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1012
regex_t * permfail_regex
Definition: generic.c:141
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
static struct fieldmap * generic_get_field_map(CfgGroup *grp)
Definition: generic.c:185
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define panic
Definition: log.h:87
regex_t * generic_foreign_id_regex
Definition: generic.c:146
struct fieldmap * map
Definition: generic.c:134
regex_t * tempfail_regex
Definition: generic.c:142

◆ generic_parse_reply()

static void generic_parse_reply ( SMSCConn conn,
Msg msg,
int  status,
List headers,
Octstr body 
)
static

Definition at line 547 of file generic.c.

References bb_smscconn_send_failed(), bb_smscconn_sent(), conndata::data, smscconn::data, debug(), dlr_add(), DLR_IS_ENABLED_DEVICE, error(), generic_values::generic_foreign_id_regex, smscconn::id, msg, octstr_copy, octstr_create, octstr_destroy(), octstr_dump, octstr_duplicate, octstr_get_cstr, generic_values::permfail_regex, SMSCCONN_FAILED_MALFORMED, SMSCCONN_FAILED_REJECTED, SMSCCONN_FAILED_TEMPORARILY, generic_values::success_regex, generic_values::tempfail_regex, UUID_STR_LEN, uuid_unparse(), and warning().

549 {
550  ConnData *conndata = conn->data;
551  struct generic_values *values = conndata->data;
552  regmatch_t pmatch[2];
553  Octstr *msgid = NULL;
554 
555  /*
556  * Our generic type checks only content on the HTTP response body.
557  * We use the pre-compiled regex to match against the states.
558  * This is the most generic criteria (at the moment).
559  */
560  if ((values->success_regex != NULL) &&
561  (gw_regex_exec(values->success_regex, body, 0, NULL, 0) == 0)) {
562  /* SMSC ACK... the message id should be in the body */
563 
564  /* add to our own DLR storage */
565  if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
566  /* directive 'generic-foreign-id-regex' is present, fetch the foreign ID */
567  if ((values->generic_foreign_id_regex != NULL)) {
568  if (gw_regex_exec(values->generic_foreign_id_regex, body, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0) == 0) {
569  if (pmatch[1].rm_so != -1 && pmatch[1].rm_eo != -1) {
570  msgid = octstr_copy(body, pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);
571  debug("smsc.http.generic", 0, "HTTP[%s]: Found foreign message id <%s> in body.",
572  octstr_get_cstr(conn->id), octstr_get_cstr(msgid));
573  dlr_add(conn->id, msgid, msg, 0);
574  octstr_destroy(msgid);
575  }
576  }
577  if (msgid == NULL)
578  warning(0, "HTTP[%s]: Can't get the foreign message id from the HTTP body.",
579  octstr_get_cstr(conn->id));
580  } else {
581  char id[UUID_STR_LEN + 1];
582  /* use own own UUID as msg ID in the DLR storage */
583  uuid_unparse(msg->sms.id, id);
584  msgid = octstr_create(id);
585  dlr_add(conn->id, msgid, msg, 0);
586  octstr_destroy(msgid);
587  }
588  }
589  bb_smscconn_sent(conn, msg, NULL);
590  }
591  else if ((values->permfail_regex != NULL) &&
592  (gw_regex_exec(values->permfail_regex, body, 0, NULL, 0) == 0)) {
593  error(0, "HTTP[%s]: Message not accepted.", octstr_get_cstr(conn->id));
596  }
597  else if ((values->tempfail_regex != NULL) &&
598  (gw_regex_exec(values->tempfail_regex, body, 0, NULL, 0) == 0)) {
599  warning(0, "HTTP[%s]: Message temporary not accepted, will retry.",
600  octstr_get_cstr(conn->id));
603  }
604  else {
605  error(0, "HTTP[%s]: Message was rejected. SMSC response was:",
606  octstr_get_cstr(conn->id));
607  octstr_dump(body, 0);
610  }
611 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void * data
Definition: smsc_http_p.h:114
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:250
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
regex_t * success_regex
Definition: generic.c:140
void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
Definition: dlr.c:330
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
regex_t * permfail_regex
Definition: generic.c:141
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
#define UUID_STR_LEN
Definition: gw_uuid.h:19
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:281
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:329
regex_t * generic_foreign_id_regex
Definition: generic.c:146
regex_t * tempfail_regex
Definition: generic.c:142
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86

◆ generic_receive_sms()

static void generic_receive_sms ( SMSCConn conn,
HTTPClient client,
List headers,
Octstr body,
List cgivars 
)
static

Definition at line 270 of file generic.c.

References account, fieldmap::account, conndata::alt_charset, bb_smscconn_receive(), fieldmap::binfo, charset, client(), fieldmap::coding, conndata::data, smscconn::data, debug(), fieldmap::deferred, fieldmap::dlr_err, dlr_find(), fieldmap::dlr_mask, fieldmap::dlr_mid, DLR_UNDEFINED, error(), fieldmap::flash, from, fieldmap::from, gwlist_create, http_cgi_variable(), http_destroy_headers(), http_header_add(), http_header_get_content_type(), http_send_reply(), smscconn::id, generic_values::map, MAX_SMS_OCTETS, fieldmap::mclass, fieldmap::message_sent, meta_data, fieldmap::meta_data, meta_data_set_value(), METADATA_DLR_GROUP, METADATA_DLR_GROUP_ERRORCODE, msg, msg_create, msg_destroy(), msg_duplicate(), fieldmap::mwi, octstr_case_compare(), octstr_compare(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_char(), octstr_get_cstr, octstr_imm(), octstr_len(), parse_cgivars(), conndata::password, fieldmap::password, report_mo, sms_charset_processing(), SMS_PARAM_UNDEFINED, fieldmap::status_error, fieldmap::status_sent, fieldmap::text, text, fieldmap::to, type, fieldmap::udh, urltrans_fill_escape_codes(), conndata::use_post, conndata::username, fieldmap::username, fieldmap::validity, and warning().

272 {
273  ConnData *conndata = conn->data;
274  struct generic_values *values = conndata->data;
275  struct fieldmap *fm = values->map;
276  Octstr *user, *pass, *from, *to, *text, *udh, *account, *binfo, *meta_data;
277  Octstr *dlrmid, *dlrerr;
278  Octstr *tmp_string, *retmsg;
279  int dlrmask;
280  List *reply_headers;
281  int ret, retstatus;
282 
283  dlrmask = SMS_PARAM_UNDEFINED;
284 
285  /* Parse for HTTP POST data */
286  if (conndata->use_post && octstr_len(body) > 0) {
287  Octstr *type, *charset;
288 
289  type = charset = NULL;
291  if (octstr_case_compare(type, octstr_imm("application/x-www-form-urlencoded")) == 0) {
292  parse_cgivars(cgivars, body);
293  } else {
294  warning(0, "HTTP[%s]: Received HTTP POST with wrong content-type `%s', should be `application/x-www-form-urlencoded'.",
296  }
299  }
300 
301  /* Parse enough parameters to validate the request */
302  user = http_cgi_variable(cgivars, octstr_get_cstr(fm->username));
303  pass = http_cgi_variable(cgivars, octstr_get_cstr(fm->password));
304  from = http_cgi_variable(cgivars, octstr_get_cstr(fm->from));
305  to = http_cgi_variable(cgivars, octstr_get_cstr(fm->to));
306  text = http_cgi_variable(cgivars, octstr_get_cstr(fm->text));
307  udh = http_cgi_variable(cgivars, octstr_get_cstr(fm->udh));
308  dlrmid = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mid));
309  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mask));
310  if (tmp_string) {
311  sscanf(octstr_get_cstr(tmp_string),"%d", &dlrmask);
312  }
313  dlrerr = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_err));
314 
315  debug("smsc.http.generic", 0, "HTTP[%s]: Received an HTTP request",
316  octstr_get_cstr(conn->id));
317 
318  if ((conndata->username != NULL && conndata->password != NULL) &&
319  (user == NULL || pass == NULL ||
320  octstr_compare(user, conndata->username) != 0 ||
321  octstr_compare(pass, conndata->password) != 0)) {
322  error(0, "HTTP[%s]: Authorization failure",
323  octstr_get_cstr(conn->id));
324  retmsg = octstr_create("Authorization failed for sendsms");
325  retstatus = fm->status_error;
326  } else if (dlrmask != DLR_UNDEFINED && dlrmid != NULL) {
327  /* we got a DLR, and we don't require additional values */
328  Msg *dlrmsg;
329 
330  dlrmsg = dlr_find(conn->id,
331  dlrmid, /* message id */
332  to, /* destination */
333  dlrmask, 0);
334 
335  if (dlrmsg != NULL) {
336  dlrmsg->sms.sms_type = report_mo;
337  dlrmsg->sms.msgdata = octstr_duplicate(text);
338  dlrmsg->sms.account = octstr_duplicate(conndata->username);
339 
340  debug("smsc.http.generic", 0, "HTTP[%s]: Received DLR for DLR-URL <%s>",
341  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmsg->sms.dlr_url));
342 
343  if (dlrerr != NULL) {
344  /* pass errorcode as is */
345  if (dlrmsg->sms.meta_data == NULL)
346  dlrmsg->sms.meta_data = octstr_create("");
347 
348  meta_data_set_value(dlrmsg->sms.meta_data, METADATA_DLR_GROUP,
350  }
351 
352  Msg *resp = msg_duplicate(dlrmsg);
353  ret = bb_smscconn_receive(conn, dlrmsg);
354  if (ret == -1) {
355  retmsg = octstr_create("Not accepted");
356  retstatus = fm->status_error;
357  } else {
358  retmsg = urltrans_fill_escape_codes(fm->message_sent, resp);
359  retstatus = fm->status_sent;
360  }
361  msg_destroy(resp);
362  } else {
363  error(0,"HTTP[%s]: Got DLR but could not find message or was not interested "
364  "in it id<%s> dst<%s>, type<%d>",
365  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmid),
366  octstr_get_cstr(to), dlrmask);
367  retmsg = octstr_create("Unknown DLR, not accepted");
368  retstatus = fm->status_error;
369  }
370  } else if (from == NULL || to == NULL || text == NULL) {
371  error(0, "HTTP[%s]: Insufficient args",
372  octstr_get_cstr(conn->id));
373  retmsg = octstr_create("Insufficient args, rejected");
374  retstatus = fm->status_error;
375  } else if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
376  error(0, "HTTP[%s]: UDH field misformed, rejected",
377  octstr_get_cstr(conn->id));
378  retmsg = octstr_create("UDH field misformed, rejected");
379  retstatus = fm->status_error;
380  } else if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
381  error(0, "HTTP[%s]: UDH field is too long, rejected",
382  octstr_get_cstr(conn->id));
383  retmsg = octstr_create("UDH field is too long, rejected");
384  retstatus = fm->status_error;
385  }
386  else {
387  /* we got a normal MO SMS */
388  Msg *msg;
389  msg = msg_create(sms);
390 
391  /* Parse the rest of the parameters */
392  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->flash));
393  if (tmp_string) {
394  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.mclass);
395  }
396  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mclass));
397  if (tmp_string) {
398  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.mclass);
399  }
400  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mwi));
401  if (tmp_string) {
402  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.mwi);
403  }
404  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->coding));
405  if (tmp_string) {
406  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.coding);
407  }
408  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->validity));
409  if (tmp_string) {
410  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.validity);
411  msg->sms.validity = time(NULL) + msg->sms.validity * 60;
412  }
413  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->deferred));
414  if (tmp_string) {
415  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.deferred);
416  msg->sms.deferred = time(NULL) + msg->sms.deferred * 60;
417  }
419  binfo = http_cgi_variable(cgivars, octstr_get_cstr(fm->binfo));
421 
422  debug("smsc.http.generic", 0, "HTTP[%s]: Constructing new SMS",
423  octstr_get_cstr(conn->id));
424 
425  msg->sms.msgdata = octstr_duplicate(text);
426 
427  /* re-encode content if necessary */
428  if (conndata->alt_charset &&
429  sms_charset_processing(conndata->alt_charset, msg->sms.msgdata, msg->sms.coding) == -1) {
430  error(0, "HTTP[%s]: Charset or body misformed, will leave it as it is.",
431  octstr_get_cstr(conn->id));
432  }
433 
434  msg->sms.service = octstr_duplicate(user);
435  msg->sms.sender = octstr_duplicate(from);
436  msg->sms.receiver = octstr_duplicate(to);
437  msg->sms.udhdata = octstr_duplicate(udh);
438  msg->sms.smsc_id = octstr_duplicate(conn->id);
439  msg->sms.time = time(NULL);
440  msg->sms.account = octstr_duplicate(account);
441  msg->sms.binfo = octstr_duplicate(binfo);
442  msg->sms.meta_data = octstr_duplicate(meta_data);
443  Msg *resp = msg_duplicate(msg);
444  ret = bb_smscconn_receive(conn, msg);
445  if (ret == -1) {
446  retmsg = octstr_create("Not accepted");
447  retstatus = fm->status_error;
448  } else {
449  retmsg = urltrans_fill_escape_codes(fm->message_sent, resp);
450  retstatus = fm->status_sent;
451  }
452  msg_destroy(resp);
453  }
454 
455  reply_headers = gwlist_create();
456  http_header_add(reply_headers, "Content-Type", "text/plain");
457  debug("smsc.http.generic", 0, "HTTP[%s]: Sending reply",
458  octstr_get_cstr(conn->id));
459  http_send_reply(client, retstatus, reply_headers, retmsg);
460 
461  octstr_destroy(retmsg);
462  http_destroy_headers(reply_headers);
463 }
void parse_cgivars(List *cgivars, Octstr *pairs)
Definition: http.c:2542
Octstr * to
Definition: generic.c:110
void error(int err, const char *fmt,...)
Definition: log.c:648
#define MAX_SMS_OCTETS
Definition: sms.h:129
void * data
Definition: smsc_http_p.h:114
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
Octstr * text
Definition: generic.c:111
Octstr * alt_charset
Definition: smsc_http_p.h:103
Octstr * validity
Definition: generic.c:125
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2886
Octstr * account
Definition: generic.c:114
Octstr * message_sent
Definition: generic.c:128
Definition: msg.h:109
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:250
static void client(int port)
Definition: test_udp.c:77
#define METADATA_DLR_GROUP_ERRORCODE
Definition: meta_data.h:71
int meta_data_set_value(Octstr *data, const char *group, const Octstr *key, const Octstr *value, int replace)
Definition: meta_data.c:324
Octstr * deferred
Definition: generic.c:126
int type
Definition: smsc_cimd2.c:215
void http_header_get_content_type(List *headers, Octstr **type, Octstr **charset)
Definition: http.c:3225
#define msg_create(type)
Definition: msg.h:136
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
Definition: dlr.c:387
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * dlr_mask
Definition: generic.c:117
Octstr * charset
Definition: test_ota.c:68
Octstr * http_cgi_variable(List *list, char *name)
Definition: http.c:2836
Octstr * flash
Definition: generic.c:121
void http_destroy_headers(List *headers)
Definition: http.c:2879
static Octstr * from
Definition: mtbatch.c:95
Octstr * binfo
Definition: generic.c:115
Octstr * dlr_mid
Definition: generic.c:120
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2695
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Definition: msg.h:79
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:477
char * text
Definition: smsc_cimd2.c:921
Octstr * urltrans_fill_escape_codes(Octstr *pattern, Msg *request)
Definition: urltrans.c:325
#define METADATA_DLR_GROUP
Definition: meta_data.h:68
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void msg_destroy(Msg *msg)
Definition: msg.c:132
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:903
void warning(int err, const char *fmt,...)
Definition: log.c:660
Octstr * mclass
Definition: generic.c:122
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
int sms_charset_processing(Octstr *charset, Octstr *body, int coding)
Definition: sms.c:419
#define octstr_create(cstr)
Definition: octstr.h:125
Octstr * meta_data
Definition: generic.c:116
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
Octstr * coding
Definition: generic.c:124
Octstr * from
Definition: generic.c:109
Octstr * udh
Definition: generic.c:112
Octstr * username
Definition: generic.c:107
Octstr * dlr_err
Definition: generic.c:118
Octstr * mwi
Definition: generic.c:123
#define DLR_UNDEFINED
Definition: dlr.h:70
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
Octstr * password
Definition: smsc_http_p.h:98
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define gwlist_create()
Definition: list.h:136
Octstr * username
Definition: smsc_http_p.h:97
Octstr * password
Definition: generic.c:108
struct fieldmap * map
Definition: generic.c:134
long status_error
Definition: generic.c:130
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
long status_sent
Definition: generic.c:129
Definition: list.c:102
static Octstr * account
Definition: mtbatch.c:94
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static Octstr * meta_data
Definition: mtbatch.c:101
int use_post
Definition: smsc_http_p.h:102
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871

◆ generic_send_sms()

static int generic_send_sms ( SMSCConn conn,
Msg sms 
)
static

Definition at line 497 of file generic.c.

References conndata::alt_charset, content_type, convert_charset(), smscconn::data, debug(), gwlist_create, HTTPURLParse::host, http_destroy_headers(), http_header_add(), HTTP_METHOD_GET, HTTP_METHOD_POST, conndata::http_ref, http_start_request(), http_urlparse_destroy(), smscconn::id, octstr_destroy(), octstr_format(), octstr_get_cstr, parse_url(), HTTPURLParse::path, HTTPURLParse::port, HTTPURLParse::query, HTTPURLParse::scheme, conndata::send_url, url, urltrans_fill_escape_codes(), and conndata::use_post.

498 {
499  ConnData *conndata = conn->data;
500  Octstr *url = NULL;
501  List *headers;
502  HTTPURLParse *p;
503  Octstr *content_type = NULL;
504 
505  /* Transcode payload if required. */
506  if (conndata->alt_charset) {
508  }
509  else if (conndata->use_post) {
510  /* set content-type for HTTP POST */
511  content_type = octstr_format("application/x-www-form-urlencoded");
512  }
513 
514  /* We use the escape code population function from our
515  * URLTranslation module to fill in the appropriate values
516  * into the URL scheme. */
518 
519  headers = gwlist_create();
520 
521  /* Split now in HTTP GET or HTTP POST handling. */
522  if (conndata->use_post && (p = parse_url(url)) != NULL) {
524  url = octstr_format("%s%s:%ld%s",
526  p->port, octstr_get_cstr(p->path));
527  debug("smsc.http.generic", 0, "HTTP[%s]: Sending POST request <%s>",
529  http_header_add(headers, "Content-Type", octstr_get_cstr(content_type));
531  p->query, 0, sms, NULL);
533  } else {
534  debug("smsc.http.generic", 0, "HTTP[%s]: Sending GET request <%s>",
537  NULL, 0, sms, NULL);
538  }
539 
542  http_destroy_headers(headers);
543 
544  return 0;
545 }
Octstr * alt_charset
Definition: smsc_http_p.h:103
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2886
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:250
HTTPCaller * http_ref
Definition: smsc_http_p.h:86
Octstr * query
Definition: http.h:249
static void convert_charset(Msg *msg, Octstr *charset, Octstr **content_type)
Definition: generic.c:466
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
unsigned long port
Definition: http.h:245
void http_destroy_headers(List *headers)
Definition: http.c:2879
Octstr * host
Definition: http.h:244
void http_urlparse_destroy(HTTPURLParse *p)
Definition: http.c:1332
void http_start_request(HTTPCaller *caller, int method, Octstr *url, List *headers, Octstr *body, int follow, void *id, Octstr *certkeyfile)
Definition: http.c:1760
Octstr * urltrans_fill_escape_codes(Octstr *pattern, Msg *request)
Definition: urltrans.c:325
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
const char * content_type
Definition: fakewap.c:249
Octstr * path
Definition: http.h:248
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define gwlist_create()
Definition: list.h:136
HTTPURLParse * parse_url(Octstr *url)
Definition: http.c:1377
Octstr * send_url
Definition: smsc_http_p.h:93
static Octstr * url
Definition: test_xmlrpc.c:84
Definition: list.c:102
Octstr * scheme
Definition: http.h:243
int use_post
Definition: smsc_http_p.h:102

Variable Documentation

◆ smsc_http_generic_callback

struct smsc_http_fn_callbacks smsc_http_generic_callback
Initial value:
= {
.init = generic_init,
.destroy = generic_destroy,
.send_sms = generic_send_sms,
.parse_reply = generic_parse_reply,
.receive_sms = generic_receive_sms,
}
static int generic_send_sms(SMSCConn *conn, Msg *sms)
Definition: generic.c:497
static void generic_destroy(SMSCConn *conn)
Definition: generic.c:666
static void generic_receive_sms(SMSCConn *conn, HTTPClient *client, List *headers, Octstr *body, List *cgivars)
Definition: generic.c:270
static void generic_parse_reply(SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body)
Definition: generic.c:547
static int generic_init(SMSCConn *conn, CfgGroup *cfg)
Definition: generic.c:613

Definition at line 693 of file generic.c.

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.