Kannel: Open Source WAP and SMS gateway  svn-r5335
dlr.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  * gw/dlr.c
59  *
60  * Implementation of handling delivery reports (DLRs)
61  *
62  * Andreas Fink <andreas@fink.org>, 18.08.2001
63  * Stipe Tolj <stolj@wapme.de>, 22.03.2002
64  * Alexander Malysh <a.malysh@centrium.de> 2003
65  *
66  * Changes:
67  * 2001-12-17: andreas@fink.org:
68  * implemented use of mutex to avoid two mysql calls to run at the same time
69  * 2002-03-22: stolj@wapme.de:
70  * added more abstraction to fit for several other storage types
71  * 2002-08-04: stolj@wapme.de:
72  * added simple database library (sdb) support
73  * 2002-11-14: stolj@wapme.de:
74  * added re-routing info for DLRs to route via bearerbox to the same smsbox
75  * instance. This is required if you use state conditioned smsboxes or smppboxes
76  * via one bearerbox. Previously bearerbox was simple ignoring to which smsbox
77  * connection a msg is passed. Now we can route the messages inside bearerbox.
78  * 2009-04-29: aguerrieri at kannel dot org:
79  * added support for ms-sql and sybase via freetds.
80  */
81 
82 #include <ctype.h>
83 #include <time.h>
84 #include <errno.h>
85 #include <limits.h>
86 #include <string.h>
87 
88 #include <unistd.h>
89 
90 #include "gwlib/gwlib.h"
91 #include "sms.h"
92 #include "dlr.h"
93 #include "dlr_p.h"
94 #include "meta_data.h"
95 
96 /* Our callback functions */
97 static struct dlr_storage *handles = NULL;
98 
99 /*
100  * Function to allocate a new struct dlr_entry entry
101  * and initialize it to zero
102  */
104 {
105  struct dlr_entry *dlr;
106 
107  dlr = gw_malloc(sizeof(*dlr));
108  gw_assert(dlr != NULL);
109 
110  /* set all values to NULL */
111  memset(dlr, 0, sizeof(*dlr));
112 
113  return dlr;
114 }
115 
116 /*
117  * Duplicate dlr entry
118  */
119 struct dlr_entry *dlr_entry_duplicate(const struct dlr_entry *dlr)
120 {
121  struct dlr_entry *ret;
122 
123  if (dlr == NULL)
124  return NULL;
125 
126  ret = dlr_entry_create();
127  ret->smsc = octstr_duplicate(dlr->smsc);
128  ret->timestamp = octstr_duplicate(dlr->timestamp);
129  ret->source = octstr_duplicate(dlr->source);
131  ret->service = octstr_duplicate(dlr->service);
132  ret->url = octstr_duplicate(dlr->url);
133  ret->boxc_id = octstr_duplicate(dlr->boxc_id);
134  ret->mask = dlr->mask;
135 
136  return ret;
137 }
138 
139 /*
140  * Function to destroy the struct dlr_entry entry
141  */
142 void dlr_entry_destroy(struct dlr_entry *dlr)
143 {
144  /* sanity check */
145  if (dlr == NULL)
146  return;
147 
148 #define O_DELETE(a) { if (a) octstr_destroy(a); a = NULL; }
149 
150  O_DELETE(dlr->smsc);
151  O_DELETE(dlr->timestamp);
152  O_DELETE(dlr->source);
153  O_DELETE(dlr->destination);
154  O_DELETE(dlr->service);
155  O_DELETE(dlr->url);
156  O_DELETE(dlr->boxc_id);
157 
158 #undef O_DELETE
159 
160  dlr->mask = 0;
161  gw_free(dlr);
162 }
163 
164 /*
165  * Load all configuration directives that are common for all database
166  * types that use the 'dlr-db' group to define which attributes are
167  * used in the table
168  */
170 {
171  struct dlr_db_fields *ret = NULL;
172 
173  ret = gw_malloc(sizeof(*ret));
174  gw_assert(ret != NULL);
175  memset(ret, 0, sizeof(*ret));
176 
177  if (!(ret->table = cfg_get(grp, octstr_imm("table"))))
178  panic(0, "DLR: DB: directive 'table' is not specified!");
179  ret->ttl = 0;
180  if (cfg_get_integer(&ret->ttl, grp, octstr_imm("ttl")) == -1 || ret->ttl < 0)
181  ret->ttl = 0;
182  if (!(ret->field_smsc = cfg_get(grp, octstr_imm("field-smsc"))))
183  panic(0, "DLR: DB: directive 'field-smsc' is not specified!");
184  if (!(ret->field_ts = cfg_get(grp, octstr_imm("field-timestamp"))))
185  panic(0, "DLR: DB: directive 'field-timestamp' is not specified!");
186  if (!(ret->field_src = cfg_get(grp, octstr_imm("field-source"))))
187  panic(0, "DLR: DB: directive 'field-source' is not specified!");
188  if (!(ret->field_dst = cfg_get(grp, octstr_imm("field-destination"))))
189  panic(0, "DLR: DB: directive 'field-destination' is not specified!");
190  if (!(ret->field_serv = cfg_get(grp, octstr_imm("field-service"))))
191  panic(0, "DLR: DB: directive 'field-service' is not specified!");
192  if (!(ret->field_url = cfg_get(grp, octstr_imm("field-url"))))
193  panic(0, "DLR: DB: directive 'field-url' is not specified!");
194  if (!(ret->field_mask = cfg_get(grp, octstr_imm("field-mask"))))
195  panic(0, "DLR: DB: directive 'field-mask' is not specified!");
196  if (!(ret->field_status = cfg_get(grp, octstr_imm("field-status"))))
197  panic(0, "DLR: DB: directive 'field-status' is not specified!");
198  if (!(ret->field_boxc = cfg_get(grp, octstr_imm("field-boxc-id"))))
199  panic(0, "DLR: DB: directive 'field-boxc-id' is not specified!");
200 
201  return ret;
202 }
203 
205 {
206  /* sanity check */
207  if (fields == NULL)
208  return;
209 
210 #define O_DELETE(a) { if (a) octstr_destroy(a); a = NULL; }
211 
212  O_DELETE(fields->table);
213  O_DELETE(fields->field_smsc);
214  O_DELETE(fields->field_ts);
215  O_DELETE(fields->field_src);
216  O_DELETE(fields->field_dst);
217  O_DELETE(fields->field_serv);
218  O_DELETE(fields->field_url);
219  O_DELETE(fields->field_mask);
220  O_DELETE(fields->field_status);
221  O_DELETE(fields->field_boxc);
222 
223 #undef O_DELETE
224 
225  gw_free(fields);
226 }
227 
228 
229 /*
230  * Initialize specifically dlr storage. If defined storage is unknown
231  * then panic.
232  */
234 {
235  CfgGroup *grp;
236  Octstr *dlr_type;
237 
238  /* check which DLR storage type we are using */
239  grp = cfg_get_single_group(cfg, octstr_imm("core"));
240  if(grp == NULL)
241  panic(0, "DLR: can't find group core");
242 
243  dlr_type = cfg_get(grp, octstr_imm("dlr-storage"));
244 
245  /*
246  * assume we are using internal memory in case no directive
247  * has been specified, warn the user anyway
248  */
249  if (dlr_type == NULL) {
250  dlr_type = octstr_imm("internal");
251  warning(0, "DLR: using default 'internal' for storage type.");
252  }
253 
254  /* call the sub-init routine */
255  if (octstr_compare(dlr_type, octstr_imm("spool")) == 0) {
257  } else if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
259  } else if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
261  } else if (octstr_compare(dlr_type, octstr_imm("oracle")) == 0) {
263  } else if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
265  } else if (octstr_compare(dlr_type, octstr_imm("pgsql")) == 0) {
267  } else if (octstr_compare(dlr_type, octstr_imm("mssql")) == 0) {
269  } else if (octstr_compare(dlr_type, octstr_imm("sqlite3")) == 0) {
271  } else if (octstr_compare(dlr_type, octstr_imm("redis")) == 0) {
273  } else if (octstr_compare(dlr_type, octstr_imm("cassandra")) == 0) {
275  }
276 
277  /*
278  * add aditional types here
279  */
280 
281  if (handles == NULL) {
282  panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
283  }
284 
285  /* check needed function pointers */
286  if (handles->dlr_add == NULL || handles->dlr_get == NULL || handles->dlr_remove == NULL)
287  panic(0, "DLR: storage type '%s' don't implement needed functions", octstr_get_cstr(dlr_type));
288 
289  /* get info from storage */
290  info(0, "DLR using storage type: %s", handles->type);
291 
292  /* cleanup */
294 }
295 
296 /*
297  * Shutdown dlr storage
298  */
300 {
301  if (handles != NULL && handles->dlr_shutdown != NULL)
303 }
304 
305 /*
306  * Return count waiting delivery entries or -1 if error occurs
307  */
308 long dlr_messages(void)
309 {
310  if (handles != NULL && handles->dlr_messages != NULL)
311  return handles->dlr_messages();
312 
313  return -1;
314 }
315 
316 /*
317  * Return type of used dlr storage
318  */
319 const char* dlr_type(void)
320 {
321  if (handles != NULL && handles->type != NULL)
322  return handles->type;
323 
324  return "unknown";
325 }
326 
327 /*
328  * Add new dlr entry into dlr storage.
329  */
330 void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
331 {
332  struct dlr_entry *dlr = NULL;
333 
334  /* Add the foreign_id so all SMSC modules can use it.
335  * Obey also the original message in the split_parts list. */
336  if (msg->sms.foreign_id != NULL)
337  octstr_destroy(msg->sms.foreign_id);
338  msg->sms.foreign_id = octstr_duplicate(ts);
339  if (msg->sms.split_parts != NULL) {
340  struct split_parts *split = msg->sms.split_parts;
341  if (split->orig->sms.foreign_id != NULL)
342  octstr_destroy(split->orig->sms.foreign_id);
343  split->orig->sms.foreign_id = octstr_duplicate(ts);
344  }
345 
346  if (octstr_len(smsc) == 0) {
347  warning(0, "DLR[%s]: Can't add a dlr without smsc-id", dlr_type());
348  return;
349  }
350 
351  /* sanity check */
352  if (handles == NULL || handles->dlr_add == NULL || msg == NULL)
353  return;
354 
355  /* check if delivery receipt requested */
356  if (!DLR_IS_ENABLED(msg->sms.dlr_mask))
357  return;
358 
359  /* allocate new struct dlr_entry struct */
360  dlr = dlr_entry_create();
361  gw_assert(dlr != NULL);
362 
363  /* now copy all values, we are interested in */
364  dlr->smsc = (smsc ? octstr_duplicate(smsc) : octstr_create(""));
365  dlr->timestamp = (ts ? octstr_duplicate(ts) : octstr_create(""));
366  dlr->source = (msg->sms.sender ? octstr_duplicate(msg->sms.sender) : octstr_create(""));
367  dlr->destination = (msg->sms.receiver ? octstr_duplicate(msg->sms.receiver) : octstr_create(""));
368  dlr->service = (msg->sms.service ? octstr_duplicate(msg->sms.service) : octstr_create(""));
369  dlr->url = (msg->sms.dlr_url ? octstr_duplicate(msg->sms.dlr_url) : octstr_create(""));
370  dlr->boxc_id = (msg->sms.boxc_id ? octstr_duplicate(msg->sms.boxc_id) : octstr_create(""));
371  dlr->mask = msg->sms.dlr_mask;
372  dlr->use_dst = use_dst;
373 
374  debug("dlr.dlr", 0, "DLR[%s]: Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d, boxc=%s",
377 
378  /* call registered function */
379  handles->dlr_add(dlr);
380 }
381 
382 /*
383  * Return Msg* if dlr entry found in DB, otherwise NULL.
384  * NOTE: If typ is end status (e.g. DELIVERED) then dlr entry
385  * will be removed from DB.
386  */
387 Msg *dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
388 {
389  Msg *msg = NULL;
390  struct dlr_entry *dlr = NULL;
391  Octstr *dst_min = NULL;
392  Octstr *dlr_mask;
393 
394  if(octstr_len(smsc) == 0) {
395  warning(0, "DLR[%s]: Can't find a dlr without smsc-id", dlr_type());
396  return NULL;
397  }
398 
399  /* check if we have handler registered */
400  if (handles == NULL || handles->dlr_get == NULL)
401  return NULL;
402 
403  if (use_dst && dst) {
404  dst_min = octstr_duplicate(dst);
405  int len = octstr_len(dst);
406 
407  if (len > MIN_DST_LEN)
408  octstr_delete(dst_min, 0, len - MIN_DST_LEN);
409  }
410  debug("dlr.dlr", 0, "DLR[%s]: Looking for DLR smsc=%s, ts=%s, dst=%s, type=%d",
412 
413  dlr = handles->dlr_get(smsc, ts, dst_min);
414  if (dlr == NULL) {
415  warning(0, "DLR[%s]: DLR from SMSC<%s> for DST<%s> not found.",
417  return NULL;
418  }
419 
420 #define O_SET(x, val) if (octstr_len(val) > 0) { x = val; val = NULL; }
421 
422  if ((typ & dlr->mask) > 0) {
423  /* its an entry we are interested in */
424  msg = msg_create(sms);
425  msg->sms.sms_type = report_mo;
426  msg->sms.dlr_mask = typ;
427  O_SET(msg->sms.service, dlr->service);
428  O_SET(msg->sms.smsc_id, dlr->smsc);
429  O_SET(msg->sms.receiver, dlr->destination);
430  O_SET(msg->sms.sender, dlr->source);
431  /* if dlr_url was present, recode it here again */
432  O_SET(msg->sms.dlr_url, dlr->url);
433  /* add the foreign_id */
434  msg->sms.foreign_id = octstr_duplicate(ts);
435  /*
436  * insert original message to the data segment
437  * later in the smsc module
438  */
439  msg->sms.msgdata = NULL;
440  /*
441  * If a boxc_id is available, then instruct bearerbox to
442  * route this msg back to originating smsbox
443  */
444  O_SET(msg->sms.boxc_id, dlr->boxc_id);
445  /*
446  * We will provide the DLR request bitmask in the DLR going back
447  * to the smsbox connection for processing. This allows smsbox
448  * connection type applications to avoid temporary storing and
449  * resolving data to pull up this information.
450  */
451  dlr_mask = octstr_format("%ld", dlr->mask);
452  msg->sms.meta_data = octstr_create("");
456 
457  time(&msg->sms.time);
458  debug("dlr.dlr", 0, "DLR[%s]: created DLR message for URL <%s>",
459  dlr_type(), (msg->sms.dlr_url?octstr_get_cstr(msg->sms.dlr_url):""));
460  } else {
461  debug("dlr.dlr", 0, "DLR[%s]: Ignoring DLR message because of mask type=%d dlr->mask=%d", dlr_type(), typ, dlr->mask);
462  /* ok that was a status report but we where not interested in having it */
463  msg = NULL;
464  }
465 
466 #undef O_SET
467 
468  /* check for end status and if so remove from storage */
469  if (DLR_IS_NOT_FINAL(typ) && DLR_IS_SUCCESS_OR_FAIL(dlr->mask)) {
470  debug("dlr.dlr", 0, "DLR[%s]: DLR not destroyed, still waiting for other delivery report", dlr_type());
471  /* update dlr entry status if function defined */
472  if (handles != NULL && handles->dlr_update != NULL){
473  handles->dlr_update(smsc, ts, dst_min, typ);
474  }
475  } else {
476  if (handles != NULL && handles->dlr_remove != NULL){
477  /* it's not good for internal storage, but better for all others */
478  handles->dlr_remove(smsc, ts, dst_min);
479  } else {
480  warning(0, "DLR[%s]: Storage don't have remove operation defined", dlr_type());
481  }
482  }
483 
484  /* destroy struct dlr_entry */
485  dlr_entry_destroy(dlr);
486  octstr_destroy(dst_min);
487 
488  return msg;
489 }
490 
491 void dlr_flush(void)
492 {
493  info(0, "Flushing all %ld queued DLR messages in %s storage", dlr_messages(),
494  dlr_type());
495 
496  if (handles != NULL && handles->dlr_flush != NULL)
497  handles->dlr_flush();
498 }
499 
500 
501 Msg* create_dlr_from_msg(const Octstr *smsc, const Msg *msg, const Octstr *reply, long stat)
502 {
503  Msg *dlrmsg;
504 
505  if (msg == NULL)
506  return NULL;
507 
508  /* generate DLR */
509  debug("dlr.dlr", 0,"SMSC[%s]: creating DLR message",
510  (smsc ? octstr_get_cstr(smsc) : "UNKNOWN"));
511 
512  dlrmsg = msg_create(sms);
513  gw_assert(dlrmsg != NULL);
514 
515  dlrmsg->sms.service = octstr_duplicate(msg->sms.service);
516  dlrmsg->sms.dlr_mask = stat;
517  dlrmsg->sms.sms_type = report_mo;
518  dlrmsg->sms.smsc_id = octstr_duplicate(smsc ? smsc : msg->sms.smsc_id);
519  dlrmsg->sms.sender = octstr_duplicate(msg->sms.sender);
520  dlrmsg->sms.receiver = octstr_duplicate(msg->sms.receiver);
521  dlrmsg->sms.dlr_url = octstr_duplicate(msg->sms.dlr_url);
522  dlrmsg->sms.msgdata = octstr_duplicate(reply);
523  dlrmsg->sms.boxc_id = octstr_duplicate(msg->sms.boxc_id);
524  dlrmsg->sms.foreign_id = octstr_duplicate(msg->sms.foreign_id);
525  time(&dlrmsg->sms.time);
526  dlrmsg->sms.meta_data = octstr_duplicate(msg->sms.meta_data);
527 
528  /* add original DLR bit-mask, as we do in dlr_find() */
529  if (DLR_IS_ENABLED(msg->sms.dlr_mask)) {
530  Octstr *dlr_mask = octstr_format("%ld", msg->sms.dlr_mask);
531  if (dlrmsg->sms.meta_data == NULL)
532  dlrmsg->sms.meta_data = octstr_create("");
533  meta_data_set_value(dlrmsg->sms.meta_data, METADATA_ORIG_MSG_GROUP,
536  }
537 
538  debug("dlr.dlr", 0,"SMSC[%s]: DLR = %s",
539  (smsc ? octstr_get_cstr(smsc) : "UNKNOWN"),
540  (dlrmsg->sms.dlr_url ? octstr_get_cstr(dlrmsg->sms.dlr_url) : ""));
541 
542  return dlrmsg;
543 }
static Octstr * dlr_mask
Definition: test_ppg.c:106
#define METADATA_ORIG_MSG_GROUP_DLR_MASK
Definition: meta_data.h:74
const char * type
Definition: dlr_p.h:112
void info(int err, const char *fmt,...)
Definition: log.c:672
struct dlr_storage * dlr_init_sdb(Cfg *cfg)
Definition: dlr_sdb.c:477
Octstr * url
Definition: dlr_p.h:84
void(* dlr_update)(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
Definition: dlr_p.h:130
gw_assert(wtls_machine->packet_to_send !=NULL)
Octstr * field_boxc
Definition: dlr_p.h:160
Octstr * service
Definition: dlr_p.h:83
struct dlr_entry * dlr_entry_duplicate(const struct dlr_entry *dlr)
Definition: dlr.c:119
void dlr_db_fields_destroy(struct dlr_db_fields *fields)
Definition: dlr.c:204
Definition: msg.h:109
struct dlr_entry * dlr_entry_create(void)
Definition: dlr.c:103
Octstr * boxc_id
Definition: dlr_p.h:85
int meta_data_set_value(Octstr *data, const char *group, const Octstr *key, const Octstr *value, int replace)
Definition: meta_data.c:324
long(* dlr_messages)(void)
Definition: dlr_p.h:134
#define MIN_DST_LEN
Definition: dlr_p.h:74
Msg * create_dlr_from_msg(const Octstr *smsc, const Msg *msg, const Octstr *reply, long stat)
Definition: dlr.c:501
#define cfg_get(grp, varname)
Definition: cfg.h:86
struct dlr_storage * dlr_init_mem(Cfg *cfg)
Definition: dlr_mem.c:206
#define msg_create(type)
Definition: msg.h:136
Octstr * field_src
Definition: dlr_p.h:154
Octstr * field_url
Definition: dlr_p.h:157
static Cfg * cfg
Definition: opensmppbox.c:95
void(* dlr_add)(struct dlr_entry *entry)
Definition: dlr_p.h:117
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 DLR_IS_NOT_FINAL(dlr)
Definition: dlr.h:84
struct dlr_storage * dlr_init_oracle(Cfg *cfg)
Definition: dlr_oracle.c:428
Octstr * field_status
Definition: dlr_p.h:159
struct dlr_storage * dlr_init_pgsql(Cfg *cfg)
Definition: dlr_pgsql.c:420
static struct dlr_storage * handles
Definition: dlr.c:97
Octstr * table
Definition: dlr_p.h:150
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Definition: msg.h:79
Definition: cfg.c:164
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1527
void(* dlr_flush)(void)
Definition: dlr_p.h:138
Octstr * source
Definition: dlr_p.h:81
struct dlr_entry *(* dlr_get)(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
Definition: dlr_p.h:122
const char * dlr_type(void)
Definition: dlr.c:319
#define octstr_duplicate(ostr)
Definition: octstr.h:187
struct dlr_storage * dlr_init_sqlite3(Cfg *cfg)
Definition: dlr_sqlite3.c:421
#define METADATA_ORIG_MSG_GROUP
Definition: meta_data.h:73
void warning(int err, const char *fmt,...)
Definition: log.c:660
Octstr * timestamp
Definition: dlr_p.h:80
Octstr * field_serv
Definition: dlr_p.h:156
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
struct dlr_storage * dlr_init_spool(Cfg *cfg)
Definition: dlr_spool.c:602
#define octstr_create(cstr)
Definition: octstr.h:125
struct dlr_storage * dlr_init_redis(Cfg *cfg)
Definition: dlr_redis.c:576
struct dlr_storage * dlr_init_mysql(Cfg *cfg)
Definition: dlr_mysql.c:470
Octstr * field_smsc
Definition: dlr_p.h:152
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Octstr * destination
Definition: dlr_p.h:82
struct dlr_storage * dlr_init_mssql(Cfg *cfg)
Definition: dlr_mssql.c:394
void dlr_init(Cfg *cfg)
Definition: dlr.c:233
Definition: octstr.c:118
struct dlr_storage * dlr_init_cass(Cfg *cfg)
Definition: dlr_cass.c:427
void dlr_flush(void)
Definition: dlr.c:491
void dlr_entry_destroy(struct dlr_entry *dlr)
Definition: dlr.c:142
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:742
#define panic
Definition: log.h:87
static List * split
Definition: test_http.c:88
Definition: cfg.c:73
#define O_SET(x, val)
#define O_DELETE(a)
Definition: dlr_p.h:78
Octstr * smsc
Definition: dlr_p.h:79
int mask
Definition: dlr_p.h:86
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:639
long dlr_messages(void)
Definition: dlr.c:308
struct dlr_db_fields * dlr_db_fields_create(CfgGroup *grp)
Definition: dlr.c:169
#define DLR_IS_ENABLED(dlr)
Definition: dlr.h:81
void(* dlr_remove)(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
Definition: dlr_p.h:126
Octstr * field_ts
Definition: dlr_p.h:153
Octstr * field_dst
Definition: dlr_p.h:155
#define DLR_IS_SUCCESS_OR_FAIL(dlr)
Definition: dlr.h:85
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void dlr_shutdown()
Definition: dlr.c:299
int use_dst
Definition: dlr_p.h:87
Octstr * field_mask
Definition: dlr_p.h:158
void(* dlr_shutdown)(void)
Definition: dlr_p.h:142
long ttl
Definition: dlr_p.h:151
static void reply(HTTPClient *c, List *push_headers)
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.