Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
dlr_spool.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 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_spool.c
59  *
60  * Implementation of handling delivery reports (DLRs) in a spool directory.
61  * This ensures we have disk persistence of the temporary DLR data, but also
62  * doesn't force users to use third party RDMS systems for the storage.
63  *
64  * Stipe Tolj <stolj at kannel dot org>
65  */
66 
67 #include <unistd.h>
68 #include <sys/types.h>
69 #include <sys/stat.h>
70 #include <fcntl.h>
71 #include <dirent.h>
72 #include <errno.h>
73 
74 #include "gwlib/gwlib.h"
75 #include "dlr_p.h"
76 #include "sms.h"
77 #include "bb_store.h"
78 
79 #ifdef HAVE_NFTW
80 #include <ftw.h>
81 #endif
82 
83 /* some standard constant for the hash functions */
84 #define MD5_DIGEST_LEN 32
85 #define SHA1_DIGEST_LEN 40
86 #ifdef HAVE_LIBSSL
87 # define OUR_DIGEST_LEN SHA1_DIGEST_LEN
88 #else
89 # define OUR_DIGEST_LEN MD5_DIGEST_LEN
90 #endif
91 
92 /* how much sub-directories will we allow? */
93 #define MAX_DIRS 100
94 
95 /*
96  * Define this macro in order to get verified counter
97  * values while start-up. This will decrease start-up performance,
98  * especially for large scale DLR spools
99  */
100 /*
101 #define VERIFIED 1
102 */
103 
104 /*
105  * Our DLR spool location.
106  */
107 static Octstr *spool_dir = NULL;
108 
109 /*
110  * Internal counter keeping track of how many items we have.
111  */
112 static Counter *counter;
113 
114 
115 /********************************************************************
116  * Hashing functions.
117  */
118 
119 /*
120  * Calculates a SHA1 hash digest, if openssl library was available
121  * on the system, or a less secure MD5 hash digest.
122  */
124 {
125 #ifdef HAVE_LIBSSL
126  /* use openssl's SHA1 */
127  EVP_MD_CTX mdctx;
128  const EVP_MD *md;
129  unsigned char md_value[EVP_MAX_MD_SIZE];
130  unsigned int md_len;
131  Octstr *ret;
132 
133  md = EVP_get_digestbyname("sha1");
134 
135  EVP_MD_CTX_init(&mdctx);
136  EVP_DigestInit_ex(&mdctx, md, NULL);
137  EVP_DigestUpdate(&mdctx, octstr_get_cstr(os), octstr_len(os));
138  EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
139  EVP_MD_CTX_cleanup(&mdctx);
140 
141  ret = octstr_create_from_data((char*) md_value, md_len);
142  octstr_binary_to_hex(ret, 0);
143  return ret;
144 #else
145  /* fallback to our own MD5 if we don't have openssl available */
146  return md5digest(os);
147 #endif
148 }
149 
150 
151 /********************************************************************
152  * Disk IO operations.
153  */
154 
155 /*
156  * This callback function for use with for_each_file() will really
157  * try to load the DLR message file from the DLR spool and try to
158  * unpack it. This ensures we get a real accurate counter value at
159  * startup time.
160  */
161 #ifdef VERIFIED
162 #ifdef HAVE_NFTW
163 static int verified_file(const char *filename, const struct stat *sb, int tflag, struct FTW *ftwbuf)
164 {
165  Octstr *os;
166  Msg *msg;
167 
168  /* we need to check here if we have a regular file. */
169  if (tflag != FTW_F)
170  return 0;
171 #else
172 static int verified_file(const char *filename, const struct stat *sb, int tflag, void *ftwbuf)
173 {
174  Octstr *os;
175  Msg *msg;
176 #endif
177 
178  if ((os = octstr_read_file(filename)) == NULL) {
179  return -1;
180  }
181 
182  if ((msg = store_msg_unpack(os)) == NULL) {
183  error(0, "Could not unpack DLR message `%s'", filename);
184  octstr_destroy(os);
185  return -1;
186  }
187 
188  /* we could load and unpack, so this is verified */
189  counter_increase(counter);
190  octstr_destroy(os);
191  msg_destroy(msg);
192 
193  return 0;
194 }
195 #endif
196 
197 
198 /*
199  * This callback function for use with for_each_file() will be more
200  * optimistic and simply account and file occurrences, without trying
201  * to load and unpack the DLR message. This is less accurate, but
202  * faster for very large DLR spools.
203  */
204 #ifdef HAVE_NFTW
205 static int non_verified_file(const char *filename, const struct stat *sb, int tflag, struct FTW *ftwbuf)
206 {
207  /* we need to check here if we have a regular file. */
208  if (tflag != FTW_F)
209  return 0;
210 #else
211 static int non_verified_file(const char *filename, const struct stat *sb, int tflag, void *ftwbuf)
212 {
213 #endif
214 
215  counter_increase(counter);
216 
217  return 0;
218 }
219 
220 /*
221  * This callback function for use with for_each_file() will unlink
222  * the file, and hence removing all regular files within the DLR spool.
223  */
224 #ifdef HAVE_NFTW
225 static int unlink_file(const char *filename, const struct stat *sb, int tflag, struct FTW *ftwbuf)
226 {
227  /* we need to check here if we have a regular file. */
228  if (tflag != FTW_F)
229  return 0;
230 #else
231 static int unlink_file(const char *filename, const struct stat *sb, int tflag, void *ftwbuf)
232 {
233 #endif
234 
235  /* remove the file from the file system */
236  if (unlink(filename) == -1) {
237  error(errno, "Could not unlink file `%s'.", filename);
238  }
239 
240  return 0;
241 }
242 
243 
244 /*
245  * The function traverses a directory structure and calls a callback
246  * function for each regular file within that directory structure.
247  */
248 #ifdef HAVE_NFTW
249 static int for_each_file(const Octstr *dir_s, int ignore_err,
250  int(*cb)(const char *, const struct stat *, int, struct FTW *))
251 {
252  int ret;
253 
254  ret = nftw(octstr_get_cstr(dir_s), cb, 20, FTW_PHYS);
255 
256  return ret;
257 }
258 #else
259 static int for_each_file(const Octstr *dir_s, int ignore_err,
260  int(*cb)(const char *, const struct stat *, int, void *))
261 {
262  DIR *dir;
263  struct dirent *ent;
264  int ret = 0;
265 #ifndef _DIRENT_HAVE_D_TYPE
266  struct stat stat;
267 #endif
268 
269  if ((dir = opendir(octstr_get_cstr(dir_s))) == NULL) {
270  error(errno, "Could not open directory `%s'", octstr_get_cstr(dir_s));
271  return -1;
272  }
273  while ((ent = readdir(dir)) != NULL) {
274  Octstr *filename;
275  if (!(strcmp((char*)ent->d_name, "." ) != 0 && strcmp((char*)ent->d_name, ".." ) != 0))
276  continue;
277  filename = octstr_format("%S/%s", dir_s, ent->d_name);
278 #ifdef _DIRENT_HAVE_D_TYPE
279  if (ent->d_type == DT_DIR && for_each_file(filename, ignore_err, cb) == -1) {
280  ret = -1;
281  } else if (ent->d_type == DT_REG && cb != NULL) {
282  cb(octstr_get_cstr(filename), NULL, 0, NULL);
283  }
284 #else
285  if (lstat(octstr_get_cstr(filename), &stat) == -1) {
286  if (!ignore_err)
287  error(errno, "Could not get stat for `%s'", octstr_get_cstr(filename));
288  ret = -1;
289  } else if (S_ISDIR(stat.st_mode) && for_each_file(filename, ignore_err, cb) == -1) {
290  ret = -1;
291  } else if (S_ISREG(stat.st_mode) && cb != NULL)
292  cb(octstr_get_cstr(filename), &stat, 0, NULL);
293 #endif
294  octstr_destroy(filename);
295  if (ret == -1 && ignore_err)
296  ret = 0;
297  else if (ret == -1)
298  break;
299  }
300  closedir(dir);
301 
302  return ret;
303 }
304 #endif
305 
306 
307 static Octstr *get_msg_filename(const Octstr *dir_s, const Octstr *hash, const Octstr *dst)
308 {
309  Octstr *ret;
310  DIR *dir;
311  struct dirent *ent;
312 
313  if ((dir = opendir(octstr_get_cstr(dir_s))) == NULL) {
314  error(errno, "Could not open directory `%s'", octstr_get_cstr(dir_s));
315  return NULL;
316  }
317 
318  while ((ent = readdir(dir)) != NULL) {
319  Octstr *fname = octstr_create((char*)ent->d_name);
320 
321  if (octstr_ncompare(fname, hash, OUR_DIGEST_LEN) == 0) {
322  Octstr *addr;
323  long addr_len, pos;
324 
325  /* this is a candidate */
326  if (dst == NULL)
327  goto found;
328 
329  /* check for the destination address suffix part */
330  if ((addr_len = (octstr_len(fname) - OUR_DIGEST_LEN)) < 0 ||
331  (pos = (addr_len - octstr_len(dst))) < 0) {
332  octstr_destroy(fname);
333  continue;
334  }
335  addr = octstr_copy(fname, OUR_DIGEST_LEN, addr_len);
336 
337  /* if not found, then bail out*/
338  if (octstr_search(addr, dst, pos) == -1) {
339  octstr_destroy(addr);
340  octstr_destroy(fname);
341  continue;
342  }
343  octstr_destroy(addr);
344 found:
345  /* found it */
346  closedir(dir);
347  ret = octstr_format("%S/%S", dir_s, fname);
348  octstr_destroy(fname);
349  return ret;
350  }
351  octstr_destroy(fname);
352  }
353  closedir(dir);
354 
355  return NULL;
356 }
357 
358 static Octstr *get_msg_surrogate(const Octstr *dir_s, const Octstr *hash,
359  const Octstr *dst, Octstr **filename)
360 {
361  /* get our msg filename */
362  if ((*filename = get_msg_filename(dir_s, hash, dst)) == NULL)
363  return NULL;
364 
365  return octstr_read_file(octstr_get_cstr(*filename));
366 }
367 
368 
369 /********************************************************************
370  * Implementation of the DLR handle functions.
371  */
372 
373 /*
374  * Adds a struct dlr_entry to the spool directory.
375  */
376 static void dlr_spool_add(struct dlr_entry *dlr)
377 {
378  Msg *msg;
379  Octstr *os, *hash, *dir, *filename;
380  int fd;
381  size_t wrc;
382 
383 #define MAP(to, from) \
384  to = from; \
385  from = NULL;
386 
387  /* create a common message structure to contain our values */
388  msg = msg_create(sms);
389  msg->sms.sms_type = report_mt;
390  MAP(msg->sms.smsc_id, dlr->smsc);
391  MAP(msg->sms.foreign_id, dlr->timestamp);
392  MAP(msg->sms.sender, dlr->source);
393  MAP(msg->sms.receiver, dlr->destination);
394  MAP(msg->sms.service, dlr->service);
395  MAP(msg->sms.dlr_url, dlr->url);
396  MAP(msg->sms.boxc_id, dlr->boxc_id);
397  msg->sms.dlr_mask = dlr->mask;
398 
399  /* we got all values, destroy the structure now */
400  dlr_entry_destroy(dlr);
401 
402  /* create hash value */
403  os = octstr_duplicate(msg->sms.smsc_id);
404  octstr_append(os, msg->sms.foreign_id);
405  hash = our_hash_func(os);
406  octstr_destroy(os);
407 
408  /* target directory */
409  dir = octstr_format("%S/%ld", spool_dir, octstr_hash_key(hash) % MAX_DIRS);
410  if (mkdir(octstr_get_cstr(dir), S_IRUSR|S_IWUSR|S_IXUSR) == -1 && errno != EEXIST) {
411  error(errno, "Could not create directory `%s'.", octstr_get_cstr(dir));
412  octstr_destroy(dir);
413  octstr_destroy(hash);
414  return;
415  }
416 
417  /*
418  * Now also add the hex value of the destination.
419  * This will be the part we look later into while
420  * DLR resolving.
421  */
422  os = octstr_duplicate(msg->sms.receiver);
423  octstr_binary_to_hex(os, 0);
424  octstr_append(hash, os);
425  octstr_destroy(os);
426 
427  /* target file */
428  filename = octstr_format("%S/%S", dir, hash);
429  octstr_destroy(dir);
430  octstr_destroy(hash);
431  if ((fd = open(octstr_get_cstr(filename), O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR)) == -1) {
432  error(errno, "Could not open file `%s'.", octstr_get_cstr(filename));
433  octstr_destroy(filename);
434  return;
435  }
436 
437  /* pack and write content to file */
438  os = store_msg_pack(msg);
439  msg_destroy(msg);
440  for (wrc = 0; wrc < octstr_len(os); ) {
441  size_t rc = write(fd, octstr_get_cstr(os) + wrc, octstr_len(os) - wrc);
442  if (rc == -1) {
443  /* remove file */
444  error(errno, "Could not write DLR message to `%s'.", octstr_get_cstr(filename));
445  close(fd);
446  if (unlink(octstr_get_cstr(filename)) == -1)
447  error(errno, "Oops, Could not remove failed file `%s'.", octstr_get_cstr(filename));
448  octstr_destroy(os);
449  octstr_destroy(filename);
450  return;
451  }
452  wrc += rc;
453  }
454  close(fd);
455  counter_increase(counter);
456  octstr_destroy(filename);
457  octstr_destroy(os);
458 }
459 
460 
461 /*
462  * Find matching entry in our spool and return the dlr_entry.
463  */
464 static struct dlr_entry *dlr_spool_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
465 {
466  struct dlr_entry *ret = NULL;
467  Octstr *os, *hash, *dir, *filename = NULL;
468  Msg *msg;
469 
470  /* determine target dir and filename via hash */
471  os = octstr_duplicate(smsc);
472  octstr_append(os, ts);
473  hash = our_hash_func(os);
474  octstr_destroy(os);
475 
476  /* determine target dir */
477  dir = octstr_format("%S/%ld", spool_dir, octstr_hash_key(hash) % MAX_DIRS);
478 
479  /* get content of msg surrogate */
480  os = get_msg_surrogate(dir, hash, dst, &filename);
481  octstr_destroy(dir);
482  octstr_destroy(hash);
483 
484  /* if there was no content */
485  if (os == NULL) {
486  octstr_destroy(filename);
487  return NULL;
488  }
489 
490  /* unpack */
491  if ((msg = store_msg_unpack(os)) == NULL) {
492  octstr_destroy(os);
493  error(0, "Could not unpack DLR message `%s'", octstr_get_cstr(filename));
494  octstr_destroy(filename);
495  return ret;
496  }
497 
498  octstr_destroy(os);
499  octstr_destroy(filename);
500 
501 #define MAP(to, from) \
502  to = from; \
503  from = NULL;
504 
505  /* map values to a struct dlr_entry */
506  ret = dlr_entry_create();
507  MAP(ret->smsc, msg->sms.smsc_id);
508  MAP(ret->timestamp, msg->sms.foreign_id);
509  MAP(ret->source, msg->sms.sender);
510  MAP(ret->destination, msg->sms.receiver);
511  MAP(ret->service, msg->sms.service);
512  MAP(ret->url, msg->sms.dlr_url);
513  MAP(ret->boxc_id, msg->sms.boxc_id);
514  ret->mask = msg->sms.dlr_mask;
515 
516  msg_destroy(msg);
517 
518  return ret;
519 }
520 
521 
522 /*
523  * Remove matching entry from the spool.
524  */
525 static void dlr_spool_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
526 {
527  Octstr *os, *hash, *dir, *filename;
528 
529  /* determine target dir and filename via hash */
530  os = octstr_duplicate(smsc);
531  octstr_append(os, ts);
532  hash = our_hash_func(os);
533  octstr_destroy(os);
534 
535  /* determine target dir */
536  dir = octstr_format("%S/%ld", spool_dir, octstr_hash_key(hash) % MAX_DIRS);
537 
538  /* get msg surrogate filename */
539  filename = get_msg_filename(dir, hash, dst);
540  octstr_destroy(dir);
541  octstr_destroy(hash);
542 
543  /* if there was no filename, then we didn't find it */
544  if (filename == NULL) {
545  return;
546  }
547 
548  /* remove the file from the file system */
549  if (unlink(octstr_get_cstr(filename)) == -1) {
550  error(errno, "Could not unlink file `%s'.", octstr_get_cstr(filename));
551  octstr_destroy(filename);
552  return;
553  }
554 
555  counter_decrease(counter);
556  octstr_destroy(filename);
557 }
558 
559 
560 /*
561  * Destroy data structures of the module.
562  */
563 static void dlr_spool_shutdown()
564 {
565  counter_destroy(counter);
566  octstr_destroy(spool_dir);
567 }
568 
569 
570 /*
571  * Get count of DLR messages within the spool.
572  */
573 static long dlr_spool_messages(void)
574 {
575  return counter_value(counter);
576 }
577 
578 
579 /*
580  * Flush all DLR messages out of the spool, removing all.
581  */
582 static void dlr_spool_flush(void)
583 {
584  for_each_file(spool_dir, 1, unlink_file);
585  counter_set(counter, 0);
586 }
587 
588 
589 /********************************************************************
590  * DLR storage handle definition and init function.
591  */
592 
593 static struct dlr_storage handles = {
594  .type = "spool",
595  .dlr_add = dlr_spool_add,
596  .dlr_get = dlr_spool_get,
597  .dlr_remove = dlr_spool_remove,
598  .dlr_shutdown = dlr_spool_shutdown,
599  .dlr_messages = dlr_spool_messages,
600  .dlr_flush = dlr_spool_flush
601 };
602 
603 
604 /*
605  * Initialize dlr_waiting_list and return out storage handles.
606  */
608 {
609  CfgGroup *grp;
610 
611  if (!(grp = cfg_get_single_group(cfg, octstr_imm("core"))))
612  panic(0, "DLR: spool: group 'core' is not specified!");
613 
614  if (!(spool_dir = cfg_get(grp, octstr_imm("dlr-spool"))))
615  panic(0, "DLR: spool: directive 'dlr-spool' is not specified!");
616 
617 #ifdef HAVE_LIBSSL
618  OpenSSL_add_all_digests();
619 #endif
620 
621  counter = counter_create();
622 
623  /* we need to traverse the DLR spool to determine how
624  * many entries we have. */
625 #ifdef VERIFIED
626  for_each_file(spool_dir, 1, verified_file);
627 #else
628  for_each_file(spool_dir, 1, non_verified_file);
629 #endif
630 
631  return &handles;
632 }
void error(int err, const char *fmt,...)
Definition: log.c:612
const char * type
Definition: dlr_p.h:112
Octstr * url
Definition: dlr_p.h:84
static Octstr * spool_dir
Definition: dlr_spool.c:107
void counter_destroy(Counter *counter)
Definition: counter.c:110
Octstr * service
Definition: dlr_p.h:83
static Octstr * our_hash_func(Octstr *os)
Definition: dlr_spool.c:123
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
struct dlr_entry * dlr_entry_create(void)
Definition: dlr.c:103
Octstr * boxc_id
Definition: dlr_p.h:85
static Counter * counter
Definition: dlr_spool.c:112
long octstr_search(const Octstr *haystack, const Octstr *needle, long pos)
Definition: octstr.c:1068
#define cfg_get(grp, varname)
Definition: cfg.h:86
unsigned long counter_set(Counter *counter, unsigned long n)
Definition: counter.c:167
#define msg_create(type)
Definition: msg.h:136
unsigned long counter_decrease(Counter *counter)
Definition: counter.c:155
Msg *(* store_msg_unpack)(Octstr *os)
Definition: bb_store.c:78
static void dlr_spool_shutdown()
Definition: dlr_spool.c:563
Definition: msg.h:110
static int for_each_file(const Octstr *dir_s, int ignore_err, int(*cb)(const char *, const struct stat *, int, void *))
Definition: dlr_spool.c:259
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
void octstr_binary_to_hex(Octstr *ostr, int uppercase)
Definition: octstr.c:463
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
static struct pid_list * found
static struct dlr_storage handles
Definition: dlr_spool.c:593
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Definition: msg.h:79
Definition: cfg.c:164
Counter * counter_create(void)
Definition: counter.c:94
static Octstr * get_msg_surrogate(const Octstr *dir_s, const Octstr *hash, const Octstr *dst, Octstr **filename)
Definition: dlr_spool.c:358
static void dlr_spool_flush(void)
Definition: dlr_spool.c:582
Octstr * source
Definition: dlr_p.h:81
int octstr_ncompare(const Octstr *ostr1, const Octstr *ostr2, long n)
Definition: octstr.c:950
#define octstr_duplicate(ostr)
Definition: octstr.h:187
static long dlr_spool_messages(void)
Definition: dlr_spool.c:573
static void dlr_spool_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
Definition: dlr_spool.c:525
void msg_destroy(Msg *msg)
Definition: msg.c:132
#define MAX_DIRS
Definition: dlr_spool.c:93
Octstr * timestamp
Definition: dlr_p.h:80
unsigned long octstr_hash_key(Octstr *ostr)
Definition: octstr.c:2521
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
char filename[FILENAME_MAX+1]
Definition: log.c:135
#define octstr_create(cstr)
Definition: octstr.h:125
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
Octstr *(* store_msg_pack)(Msg *msg)
Definition: bb_store.c:77
struct dlr_storage * dlr_init_spool(Cfg *cfg)
Definition: dlr_spool.c:607
Octstr * octstr_read_file(const char *filename)
Definition: octstr.c:1546
static Cfg * cfg
Definition: smsbox.c:115
static void dlr_spool_add(struct dlr_entry *dlr)
Definition: dlr_spool.c:376
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Octstr * destination
Definition: dlr_p.h:82
Definition: octstr.c:118
#define MAP(to, from)
void dlr_entry_destroy(struct dlr_entry *dlr)
Definition: dlr.c:142
#define panic
Definition: log.h:87
Definition: cfg.c:73
static struct dlr_entry * dlr_spool_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
Definition: dlr_spool.c:464
#define EVP_MAX_MD_SIZE
Definition: test_hmac.c:82
Definition: dlr_p.h:78
static Octstr * get_msg_filename(const Octstr *dir_s, const Octstr *hash, const Octstr *dst)
Definition: dlr_spool.c:307
Octstr * smsc
Definition: dlr_p.h:79
static int unlink_file(const char *filename, const struct stat *sb, int tflag, void *ftwbuf)
Definition: dlr_spool.c:231
int mask
Definition: dlr_p.h:86
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:636
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static int non_verified_file(const char *filename, const struct stat *sb, int tflag, void *ftwbuf)
Definition: dlr_spool.c:211
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define OUR_DIGEST_LEN
Definition: dlr_spool.c:89
Octstr * md5digest(Octstr *data)
Definition: md5.c:406
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.