Kannel: Open Source WAP and SMS gateway  svn-r5262
generic.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*----------------------------------------------------------------
58  * Generic HTTP interface
59  *
60  * This 'generic' type will handle the 'send-url' directive in the
61  * group the same way the 'sms-service' for smsbox does, via
62  * URLTranslation. Response interpretation is based on the three
63  * regex value that match against the response body. The HTTP response
64  * code is not obeyed.
65  *
66  * Example config group:
67  *
68  * group = smsc
69  * smsc = http
70  * system-type = generic
71  * send-url = "http://<foobar>/<uri>?from=%P&to=%p&text=%b"
72  * status-success-regex = "ok"
73  * status-permfail-regex = "failure"
74  * status-tempfail-regex = "retry later"
75  * generic-foreign-id-regex = "<id>(.+)</id>"
76  * generic-param-from = "phoneNumber"
77  * generic-param-to = "shortCode"
78  * generic-param-text = "message"
79  * generic-message-sent = "OK"
80  * generic-status-sent = 200
81  * generic-status-error = 400
82  *
83  * Note that neither 'smsc-username' nor 'smsc-password' is required,
84  * since they are coded into the the 'send-url' value directly.
85  *
86  * Stipe Tolj <st@tolj.org>
87  *
88  * MO processing by Alejandro Guerrieri <aguerrieri at kannel dot org>
89  */
90 
91 #include "gwlib/gwlib.h"
92 #include "smscconn.h"
93 #include "smscconn_p.h"
94 #include "bb_smscconn_cb.h"
95 #include "msg.h"
96 #include "sms.h"
97 #include "dlr.h"
98 #include "urltrans.h"
99 #include "meta_data.h"
100 
101 #include "../smsc_http_p.h"
102 
103 /*
104  * This maps fields to values for MO parameters
105  */
106 struct fieldmap {
131 };
132 
134  struct fieldmap *map;
135 
136  /* The following are compiled regex for the 'generic' type for handling
137  * success, permanent failure and temporary failure. For types that use
138  * simple HTTP body parsing, these may be used also for other types,
139  * ie. for our own Kannel reply parsing. */
140  regex_t *success_regex;
141  regex_t *permfail_regex;
142  regex_t *tempfail_regex;
143 
144  /* Compiled regex for the 'generic' type to get the foreign message id
145  * from the HTTP response body */
147 };
148 
149 /*
150  * Destroys the FieldMap structure
151  */
152 static void fieldmap_destroy(struct fieldmap *fieldmap)
153 {
154  if (fieldmap == NULL)
155  return;
156  octstr_destroy(fieldmap->username);
157  octstr_destroy(fieldmap->password);
158  octstr_destroy(fieldmap->from);
159  octstr_destroy(fieldmap->to);
160  octstr_destroy(fieldmap->text);
161  octstr_destroy(fieldmap->udh);
162  octstr_destroy(fieldmap->service);
163  octstr_destroy(fieldmap->account);
164  octstr_destroy(fieldmap->binfo);
165  octstr_destroy(fieldmap->meta_data);
166  octstr_destroy(fieldmap->dlr_mask);
167  octstr_destroy(fieldmap->dlr_err);
168  octstr_destroy(fieldmap->dlr_url);
169  octstr_destroy(fieldmap->dlr_mid);
170  octstr_destroy(fieldmap->flash);
171  octstr_destroy(fieldmap->mclass);
172  octstr_destroy(fieldmap->mwi);
173  octstr_destroy(fieldmap->coding);
174  octstr_destroy(fieldmap->validity);
175  octstr_destroy(fieldmap->deferred);
176  octstr_destroy(fieldmap->foreign_id);
177  octstr_destroy(fieldmap->message_sent);
178  gw_free(fieldmap);
179 }
180 
181 
182 /*
183  * Get the FieldMap struct to map MO parameters
184  */
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 }
269 
271  List *headers, Octstr *body, List *cgivars)
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 enough parameters to validate the request */
286  user = http_cgi_variable(cgivars, octstr_get_cstr(fm->username));
287  pass = http_cgi_variable(cgivars, octstr_get_cstr(fm->password));
288  from = http_cgi_variable(cgivars, octstr_get_cstr(fm->from));
289  to = http_cgi_variable(cgivars, octstr_get_cstr(fm->to));
290  text = http_cgi_variable(cgivars, octstr_get_cstr(fm->text));
291  udh = http_cgi_variable(cgivars, octstr_get_cstr(fm->udh));
292  dlrmid = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mid));
293  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mask));
294  if (tmp_string) {
295  sscanf(octstr_get_cstr(tmp_string),"%d", &dlrmask);
296  }
297  dlrerr = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_err));
298 
299  debug("smsc.http.generic", 0, "HTTP[%s]: Received an HTTP request",
300  octstr_get_cstr(conn->id));
301 
302  if ((conndata->username != NULL && conndata->password != NULL) &&
303  (user == NULL || pass == NULL ||
304  octstr_compare(user, conndata->username) != 0 ||
305  octstr_compare(pass, conndata->password) != 0)) {
306  error(0, "HTTP[%s]: Authorization failure",
307  octstr_get_cstr(conn->id));
308  retmsg = octstr_create("Authorization failed for sendsms");
309  retstatus = fm->status_error;
310  } else if (dlrmask != DLR_UNDEFINED && dlrmid != NULL) {
311  /* we got a DLR, and we don't require additional values */
312  Msg *dlrmsg;
313 
314  dlrmsg = dlr_find(conn->id,
315  dlrmid, /* message id */
316  to, /* destination */
317  dlrmask, 0);
318 
319  if (dlrmsg != NULL) {
320  dlrmsg->sms.sms_type = report_mo;
321  dlrmsg->sms.msgdata = octstr_duplicate(text);
322  dlrmsg->sms.account = octstr_duplicate(conndata->username);
323 
324  debug("smsc.http.generic", 0, "HTTP[%s]: Received DLR for DLR-URL <%s>",
325  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmsg->sms.dlr_url));
326 
327  if (dlrerr != NULL) {
328  /* pass errorcode as is */
329  if (dlrmsg->sms.meta_data == NULL)
330  dlrmsg->sms.meta_data = octstr_create("");
331 
332  meta_data_set_value(dlrmsg->sms.meta_data, METADATA_DLR_GROUP,
334  }
335 
336  Msg *resp = msg_duplicate(dlrmsg);
337  ret = bb_smscconn_receive(conn, dlrmsg);
338  if (ret == -1) {
339  retmsg = octstr_create("Not accepted");
340  retstatus = fm->status_error;
341  } else {
342  retmsg = urltrans_fill_escape_codes(fm->message_sent, resp);
343  retstatus = fm->status_sent;
344  }
345  msg_destroy(resp);
346  } else {
347  error(0,"HTTP[%s]: Got DLR but could not find message or was not interested "
348  "in it id<%s> dst<%s>, type<%d>",
349  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmid),
350  octstr_get_cstr(to), dlrmask);
351  retmsg = octstr_create("Unknown DLR, not accepted");
352  retstatus = fm->status_error;
353  }
354  } else if (from == NULL || to == NULL || text == NULL) {
355  error(0, "HTTP[%s]: Insufficient args",
356  octstr_get_cstr(conn->id));
357  retmsg = octstr_create("Insufficient args, rejected");
358  retstatus = fm->status_error;
359  } else if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
360  error(0, "HTTP[%s]: UDH field misformed, rejected",
361  octstr_get_cstr(conn->id));
362  retmsg = octstr_create("UDH field misformed, rejected");
363  retstatus = fm->status_error;
364  } else if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
365  error(0, "HTTP[%s]: UDH field is too long, rejected",
366  octstr_get_cstr(conn->id));
367  retmsg = octstr_create("UDH field is too long, rejected");
368  retstatus = fm->status_error;
369  }
370  else {
371  /* we got a normal MO SMS */
372  Msg *msg;
373  msg = msg_create(sms);
374 
375  /* Parse the rest of the parameters */
376  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->flash));
377  if (tmp_string) {
378  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.mclass);
379  }
380  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mclass));
381  if (tmp_string) {
382  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.mclass);
383  }
384  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mwi));
385  if (tmp_string) {
386  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.mwi);
387  }
388  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->coding));
389  if (tmp_string) {
390  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.coding);
391  }
392  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->validity));
393  if (tmp_string) {
394  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.validity);
395  msg->sms.validity = time(NULL) + msg->sms.validity * 60;
396  }
397  tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->deferred));
398  if (tmp_string) {
399  sscanf(octstr_get_cstr(tmp_string),"%ld", &msg->sms.deferred);
400  msg->sms.deferred = time(NULL) + msg->sms.deferred * 60;
401  }
402  account = http_cgi_variable(cgivars, octstr_get_cstr(fm->account));
403  binfo = http_cgi_variable(cgivars, octstr_get_cstr(fm->binfo));
404  meta_data = http_cgi_variable(cgivars, octstr_get_cstr(fm->meta_data));
405 
406  debug("smsc.http.generic", 0, "HTTP[%s]: Constructing new SMS",
407  octstr_get_cstr(conn->id));
408 
409  msg->sms.msgdata = octstr_duplicate(text);
410 
411  /* re-encode content if necessary */
412  if (conndata->alt_charset &&
413  sms_charset_processing(conndata->alt_charset, msg->sms.msgdata, msg->sms.coding) == -1) {
414  error(0, "HTTP[%s]: Charset or body misformed, will leave it as it is.",
415  octstr_get_cstr(conn->id));
416  }
417 
418  msg->sms.service = octstr_duplicate(user);
419  msg->sms.sender = octstr_duplicate(from);
420  msg->sms.receiver = octstr_duplicate(to);
421  msg->sms.udhdata = octstr_duplicate(udh);
422  msg->sms.smsc_id = octstr_duplicate(conn->id);
423  msg->sms.time = time(NULL);
424  msg->sms.account = octstr_duplicate(account);
425  msg->sms.binfo = octstr_duplicate(binfo);
426  msg->sms.meta_data = octstr_duplicate(meta_data);
427  Msg *resp = msg_duplicate(msg);
428  ret = bb_smscconn_receive(conn, msg);
429  if (ret == -1) {
430  retmsg = octstr_create("Not accepted");
431  retstatus = fm->status_error;
432  } else {
433  retmsg = urltrans_fill_escape_codes(fm->message_sent, resp);
434  retstatus = fm->status_sent;
435  }
436  msg_destroy(resp);
437  }
438 
439  reply_headers = gwlist_create();
440  http_header_add(reply_headers, "Content-Type", "text/plain");
441  debug("smsc.http.generic", 0, "HTTP[%s]: Sending reply",
442  octstr_get_cstr(conn->id));
443  http_send_reply(client, retstatus, reply_headers, retmsg);
444 
445  octstr_destroy(retmsg);
446  http_destroy_headers(reply_headers);
447 }
448 
449 
450 static int generic_send_sms(SMSCConn *conn, Msg *sms)
451 {
452  ConnData *conndata = conn->data;
453  Octstr *url = NULL;
454  List *headers;
455 
456  /* We use the escape code population function from our
457  * URLTranslation module to fill in the appropriate values
458  * into the URL scheme. */
459  url = urltrans_fill_escape_codes(conndata->send_url, sms);
460 
461  headers = gwlist_create();
462  debug("smsc.http.generic", 0, "HTTP[%s]: Sending request <%s>",
463  octstr_get_cstr(conn->id), octstr_get_cstr(url));
464  http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
465  NULL, 0, sms, NULL);
466 
467  octstr_destroy(url);
468  http_destroy_headers(headers);
469 
470  return 0;
471 }
472 
473 static void generic_parse_reply(SMSCConn *conn, Msg *msg, int status,
474  List *headers, Octstr *body)
475 {
476  ConnData *conndata = conn->data;
477  struct generic_values *values = conndata->data;
478  regmatch_t pmatch[2];
479  Octstr *msgid = NULL;
480 
481  /*
482  * Our generic type checks only content on the HTTP response body.
483  * We use the pre-compiled regex to match against the states.
484  * This is the most generic criteria (at the moment).
485  */
486  if ((values->success_regex != NULL) &&
487  (gw_regex_exec(values->success_regex, body, 0, NULL, 0) == 0)) {
488  /* SMSC ACK... the message id should be in the body */
489 
490  /* add to our own DLR storage */
491  if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
492  /* directive 'generic-foreign-id-regex' is present, fetch the foreign ID */
493  if ((values->generic_foreign_id_regex != NULL)) {
494  if (gw_regex_exec(values->generic_foreign_id_regex, body, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0) == 0) {
495  if (pmatch[1].rm_so != -1 && pmatch[1].rm_eo != -1) {
496  msgid = octstr_copy(body, pmatch[1].rm_so, pmatch[1].rm_eo - pmatch[1].rm_so);
497  debug("smsc.http.generic", 0, "HTTP[%s]: Found foreign message id <%s> in body.",
498  octstr_get_cstr(conn->id), octstr_get_cstr(msgid));
499  dlr_add(conn->id, msgid, msg, 0);
500  octstr_destroy(msgid);
501  }
502  }
503  if (msgid == NULL)
504  warning(0, "HTTP[%s]: Can't get the foreign message id from the HTTP body.",
505  octstr_get_cstr(conn->id));
506  } else {
507  char id[UUID_STR_LEN + 1];
508  /* use own own UUID as msg ID in the DLR storage */
509  uuid_unparse(msg->sms.id, id);
510  msgid = octstr_create(id);
511  dlr_add(conn->id, msgid, msg, 0);
512  octstr_destroy(msgid);
513  }
514  }
515  bb_smscconn_sent(conn, msg, NULL);
516  }
517  else if ((values->permfail_regex != NULL) &&
518  (gw_regex_exec(values->permfail_regex, body, 0, NULL, 0) == 0)) {
519  error(0, "HTTP[%s]: Message not accepted.", octstr_get_cstr(conn->id));
520  bb_smscconn_send_failed(conn, msg,
522  }
523  else if ((values->tempfail_regex != NULL) &&
524  (gw_regex_exec(values->tempfail_regex, body, 0, NULL, 0) == 0)) {
525  warning(0, "HTTP[%s]: Message temporary not accepted, will retry.",
526  octstr_get_cstr(conn->id));
527  bb_smscconn_send_failed(conn, msg,
529  }
530  else {
531  error(0, "HTTP[%s]: Message was rejected. SMSC response was:",
532  octstr_get_cstr(conn->id));
533  octstr_dump(body, 0);
534  bb_smscconn_send_failed(conn, msg,
536  }
537 }
538 
539 static int generic_init(SMSCConn *conn, CfgGroup *cfg)
540 {
541  Octstr *os;
542  ConnData *conndata = conn->data;
543  struct generic_values *values;
544 
545  conndata->data = values = gw_malloc(sizeof(*values));
546  /* reset */
547  memset(conndata->data, 0, sizeof(*values));
548 
549  values->success_regex = values->permfail_regex = values->tempfail_regex = NULL;
550  values->generic_foreign_id_regex = NULL;
551 
552  values->map = generic_get_field_map(cfg);
553 
554  /* pre-compile regex expressions */
555  if ((os = cfg_get(cfg, octstr_imm("status-success-regex"))) != NULL) {
556  if ((values->success_regex = gw_regex_comp(os, REG_EXTENDED|REG_NOSUB)) == NULL)
557  error(0, "HTTP[%s]: Could not compile pattern '%s' defined for variable 'status-success-regex'",
558  octstr_get_cstr(conn->id), octstr_get_cstr(os));
559  octstr_destroy(os);
560  } else {
561  /* we need at least the criteria for a successful sent */
562  error(0, "HTTP[%s]: 'status-success-regex' required for generic http smsc",
563  octstr_get_cstr(conn->id));
564  return -1;
565  }
566  if ((os = cfg_get(cfg, octstr_imm("status-permfail-regex"))) != NULL) {
567  if ((values->permfail_regex = gw_regex_comp(os, REG_EXTENDED|REG_NOSUB)) == NULL)
568  panic(0, "Could not compile pattern '%s' defined for variable 'status-permfail-regex'", octstr_get_cstr(os));
569  octstr_destroy(os);
570  }
571  if ((os = cfg_get(cfg, octstr_imm("status-tempfail-regex"))) != NULL) {
572  if ((values->tempfail_regex = gw_regex_comp(os, REG_EXTENDED|REG_NOSUB)) == NULL)
573  panic(0, "Could not compile pattern '%s' defined for variable 'status-tempfail-regex'", octstr_get_cstr(os));
574  octstr_destroy(os);
575  }
576  if ((os = cfg_get(cfg, octstr_imm("generic-foreign-id-regex"))) != NULL) {
577  if ((values->generic_foreign_id_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
578  panic(0, "Could not compile pattern '%s' defined for variable 'generic-foreign-id-regex'", octstr_get_cstr(os));
579  else {
580  /* check quickly that at least 1 group seems to be defined in the regex */
581  if (octstr_search_char(os, '(', 0) == -1 || octstr_search_char(os, ')', 0) == -1)
582  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));
583  }
584  octstr_destroy(os);
585  }
586 
587  debug("", 0, "generic init completed");
588 
589  return 0;
590 }
591 
592 static void generic_destroy(SMSCConn *conn)
593 {
595  struct generic_values *values;
596 
597  if (conn == NULL || conn->data == NULL)
598  return;
599 
600  conndata = conn->data;
601  values = conndata->data;
602 
603  fieldmap_destroy(values->map);
604  if (values->success_regex)
605  gw_regex_destroy(values->success_regex);
606  if (values->permfail_regex)
607  gw_regex_destroy(values->permfail_regex);
608  if (values->tempfail_regex)
609  gw_regex_destroy(values->tempfail_regex);
610  if (values->generic_foreign_id_regex)
611  gw_regex_destroy(values->generic_foreign_id_regex);
612 
613  gw_free(values);
614  conndata->data = NULL;
615 
616  debug("", 0, "generic destroy completed");
617 }
618 
620  .init = generic_init,
621  .destroy = generic_destroy,
622  .send_sms = generic_send_sms,
623  .parse_reply = generic_parse_reply,
624  .receive_sms = generic_receive_sms,
625 };
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:111
static int generic_send_sms(SMSCConn *conn, Msg *sms)
Definition: generic.c:450
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
Octstr * text
Definition: generic.c:111
Octstr * alt_charset
Definition: smsc_http_p.h:104
Octstr * validity
Definition: generic.c:125
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2863
Octstr * account
Definition: generic.c:114
gw_assert(wtls_machine->packet_to_send !=NULL)
Octstr * message_sent
Definition: generic.c:128
Definition: msg.h:109
static void generic_destroy(SMSCConn *conn)
Definition: generic.c:592
static void generic_receive_sms(SMSCConn *conn, HTTPClient *client, List *headers, Octstr *body, List *cgivars)
Definition: generic.c:270
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
static void client(int port)
Definition: test_udp.c:77
#define METADATA_DLR_GROUP_ERRORCODE
Definition: meta_data.h:71
HTTPCaller * http_ref
Definition: smsc_http_p.h:86
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
#define cfg_get(grp, varname)
Definition: cfg.h:86
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
#define msg_create(type)
Definition: msg.h:136
static void generic_parse_reply(SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body)
Definition: generic.c:473
regex_t * success_regex
Definition: generic.c:140
static Cfg * cfg
Definition: opensmppbox.c:95
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
Definition: dlr.c:387
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
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1010
Octstr * dlr_mask
Definition: generic.c:117
regex_t * permfail_regex
Definition: generic.c:141
Octstr * http_cgi_variable(List *list, char *name)
Definition: http.c:2813
Octstr * flash
Definition: generic.c:121
void http_destroy_headers(List *headers)
Definition: http.c:2856
Octstr * binfo
Definition: generic.c:115
void http_start_request(HTTPCaller *caller, int method, Octstr *url, List *headers, Octstr *body, int follow, void *id, Octstr *certkeyfile)
Definition: http.c:1745
Octstr * dlr_mid
Definition: generic.c:120
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2672
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Definition: msg.h:79
Octstr * dlr_url
Definition: generic.c:119
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:478
Octstr * urltrans_fill_escape_codes(Octstr *pattern, Msg *request)
Definition: urltrans.c:323
#define METADATA_DLR_GROUP
Definition: meta_data.h:68
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
static int generic_init(SMSCConn *conn, CfgGroup *cfg)
Definition: generic.c:539
struct smsc_http_fn_callbacks smsc_http_generic_callback
Definition: generic.c:619
void msg_destroy(Msg *msg)
Definition: msg.c:132
static struct fieldmap * generic_get_field_map(CfgGroup *grp)
Definition: generic.c:185
Octstr * foreign_id
Definition: generic.c:127
void warning(int err, const char *fmt,...)
Definition: log.c:660
Octstr * mclass
Definition: generic.c:122
Octstr * service
Definition: generic.c:113
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
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
#define UUID_STR_LEN
Definition: gw_uuid.h:19
Octstr * mwi
Definition: generic.c:123
#define DLR_UNDEFINED
Definition: dlr.h:70
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
int(* init)(SMSCConn *conn, CfgGroup *cfg)
Definition: smsc_http_p.h:74
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:279
Octstr * password
Definition: smsc_http_p.h:98
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
#define panic
Definition: log.h:87
Definition: cfg.c:73
#define gwlist_create()
Definition: list.h:136
Octstr * username
Definition: smsc_http_p.h:97
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
static void fieldmap_destroy(struct fieldmap *fieldmap)
Definition: generic.c:152
Octstr * password
Definition: generic.c:108
regex_t * generic_foreign_id_regex
Definition: generic.c:146
Octstr * send_url
Definition: smsc_http_p.h:93
struct fieldmap * map
Definition: generic.c:134
regex_t * tempfail_regex
Definition: generic.c:142
long status_error
Definition: generic.c:130
static Octstr * url
Definition: test_xmlrpc.c:84
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
long status_sent
Definition: generic.c:129
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82
Definition: list.c:102
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.