Kannel: Open Source WAP and SMS gateway  svn-r5335
bb_store_spool.c File Reference
#include "gw-config.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include "gwlib/gwlib.h"
#include "msg.h"
#include "sms.h"
#include "bearerbox.h"
#include "bb_store.h"

Go to the source code of this file.

Data Structures

struct  status
 

Macros

#define MAX_DIRS   100
 

Functions

static int store_spool_dump ()
 
static long store_spool_messages ()
 
static int for_each_file (const Octstr *dir_s, int ignore_err, void(*cb)(const Octstr *, void *), void *data)
 
static void status_cb (const Octstr *filename, void *d)
 
static void store_spool_for_each_message (void(*callback_fn)(Msg *msg, void *data), void *data)
 
static void dispatch (const Octstr *filename, void *data)
 
static int store_spool_load (void(*receive_msg)(Msg *))
 
static int store_spool_save (Msg *msg)
 
static int store_spool_save_ack (Msg *msg, ack_status_t status)
 
static void store_spool_shutdown ()
 
int store_spool_init (const Octstr *store_dir)
 

Variables

static Octstrspool
 
static Countercounter
 
static Listloaded
 

Macro Definition Documentation

◆ MAX_DIRS

#define MAX_DIRS   100

bb_store_spool.c - bearerbox box SMS storage/retrieval module using spool directory

Author: Alexander Malysh, 2006

Definition at line 80 of file bb_store_spool.c.

Referenced by store_spool_save().

Function Documentation

◆ dispatch()

static void dispatch ( const Octstr filename,
void *  data 
)
static

Definition at line 175 of file bb_store_spool.c.

References counter, counter_increase(), status::data, error(), filename, msg, octstr_destroy(), octstr_get_cstr, octstr_read_file(), and store_msg_unpack.

Referenced by store_spool_load().

176 {
177  Octstr *msg_s;
178  Msg *msg;
179  void(*receive_msg)(Msg*) = data;
180 
181  /* debug("", 0, "dispatch(%s,...) called", octstr_get_cstr(filename)); */
182 
184  if (msg_s == NULL)
185  return;
186  msg = store_msg_unpack(msg_s);
187  octstr_destroy(msg_s);
188  if (msg != NULL) {
189  receive_msg(msg);
191  } else {
192  error(0, "Could not unpack message `%s'", octstr_get_cstr(filename));
193  }
194 }
void error(int err, const char *fmt,...)
Definition: log.c:648
Msg *(* store_msg_unpack)(Octstr *os)
Definition: bb_store.c:78
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
Definition: msg.h:79
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
char filename[FILENAME_MAX+1]
Definition: log.c:171
void * data
Octstr * octstr_read_file(const char *filename)
Definition: octstr.c:1548
Definition: octstr.c:118
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static Counter * counter

◆ for_each_file()

static int for_each_file ( const Octstr dir_s,
int  ignore_err,
void(*)(const Octstr *, void *)  cb,
void *  data 
)
static

Definition at line 100 of file bb_store_spool.c.

References error(), filename, octstr_destroy(), octstr_format(), and octstr_get_cstr.

Referenced by store_spool_for_each_message(), and store_spool_load().

101 {
102  DIR *dir;
103  struct dirent *ent;
104  struct stat stat;
105  int ret = 0;
106 
107  if ((dir = opendir(octstr_get_cstr(dir_s))) == NULL) {
108  error(errno, "Could not open directory `%s'", octstr_get_cstr(dir_s));
109  return -1;
110  }
111  while((ent = readdir(dir)) != NULL) {
112  Octstr *filename;
113  if (*(ent->d_name) == '.') /* skip hidden files */
114  continue;
115  filename = octstr_format("%S/%s", dir_s, ent->d_name);
116  if (lstat(octstr_get_cstr(filename), &stat) == -1) {
117  if (!ignore_err)
118  error(errno, "Could not get stat for `%s'", octstr_get_cstr(filename));
119  ret = -1;
120  } else if (S_ISDIR(stat.st_mode) && for_each_file(filename, ignore_err, cb, data) == -1) {
121  ret = -1;
122  } else if (S_ISREG(stat.st_mode) && cb != NULL)
123  cb(filename, data);
125  if (ret == -1 && ignore_err)
126  ret = 0;
127  else if (ret == -1)
128  break;
129  }
130  closedir(dir);
131 
132  return ret;
133 }
void error(int err, const char *fmt,...)
Definition: log.c:648
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static int for_each_file(const Octstr *dir_s, int ignore_err, void(*cb)(const Octstr *, void *), void *data)
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
char filename[FILENAME_MAX+1]
Definition: log.c:171
Definition: octstr.c:118

◆ status_cb()

static void status_cb ( const Octstr filename,
void *  d 
)
static

Definition at line 142 of file bb_store_spool.c.

References status::data, filename, msg, msg_destroy(), octstr_destroy(), octstr_get_cstr, octstr_read_file(), and store_msg_unpack.

Referenced by store_spool_for_each_message().

143 {
144  struct status *data = d;
145  Octstr *msg_s;
146  Msg *msg;
147 
149  msg = store_msg_unpack(msg_s);
150  octstr_destroy(msg_s);
151  if (msg == NULL)
152  return;
153 
154  data->callback_fn(msg, data->data);
155 
156  msg_destroy(msg);
157 }
Msg *(* store_msg_unpack)(Octstr *os)
Definition: bb_store.c:78
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Definition: msg.h:79
void msg_destroy(Msg *msg)
Definition: msg.c:132
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
char filename[FILENAME_MAX+1]
Definition: log.c:171
void * data
Octstr * octstr_read_file(const char *filename)
Definition: octstr.c:1548
Definition: octstr.c:118
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86

◆ store_spool_dump()

static int store_spool_dump ( )
static

Definition at line 87 of file bb_store_spool.c.

Referenced by store_spool_init().

88 {
89  /* nothing todo */
90  return 0;
91 }

◆ store_spool_for_each_message()

static void store_spool_for_each_message ( void(*)(Msg *msg, void *data)  callback_fn,
void *  data 
)
static

Definition at line 160 of file bb_store_spool.c.

References status::callback_fn, status::data, for_each_file(), spool, and status_cb().

Referenced by store_spool_init().

161 {
162  struct status d;
163 
164  if (spool == NULL)
165  return;
166 
168  d.data = data;
169 
170  /* ignore error because files may disappear */
171  for_each_file(spool, 1, status_cb, &d);
172 }
static Octstr * spool
static int for_each_file(const Octstr *dir_s, int ignore_err, void(*cb)(const Octstr *, void *), void *data)
void * data
void(* callback_fn)(Msg *msg, void *data)
static void status_cb(const Octstr *filename, void *d)

◆ store_spool_init()

int store_spool_init ( const Octstr fname)

Init functions for different store types.

Definition at line 338 of file bb_store_spool.c.

References counter, counter_create(), error(), gwlist_add_producer(), gwlist_create, loaded, octstr_duplicate, octstr_get_cstr, spool, store_dump, store_for_each_message, store_load, store_messages, store_save, store_save_ack, store_shutdown, store_spool_dump(), store_spool_for_each_message(), store_spool_load(), store_spool_messages(), store_spool_save(), store_spool_save_ack(), and store_spool_shutdown().

Referenced by store_init().

339 {
340  DIR *dir;
341 
349 
350  if (store_dir == NULL)
351  return 0;
352 
353  /* check if we can open directory */
354  if ((dir = opendir(octstr_get_cstr(store_dir))) == NULL) {
355  error(errno, "Could not open directory `%s'", octstr_get_cstr(store_dir));
356  return -1;
357  }
358  closedir(dir);
359 
360  loaded = gwlist_create();
362  spool = octstr_duplicate(store_dir);
364 
365  return 0;
366 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static Octstr * spool
static void store_spool_shutdown()
int(* store_save_ack)(Msg *msg, ack_status_t status)
Definition: bb_store.c:73
long(* store_messages)(void)
Definition: bb_store.c:71
int(* store_dump)(void)
Definition: bb_store.c:75
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void(* store_for_each_message)(void(*callback_fn)(Msg *msg, void *data), void *data)
Definition: bb_store.c:79
static long store_spool_messages()
static void store_spool_for_each_message(void(*callback_fn)(Msg *msg, void *data), void *data)
Counter * counter_create(void)
Definition: counter.c:94
static int store_spool_save(Msg *msg)
static int store_spool_dump()
#define octstr_duplicate(ostr)
Definition: octstr.h:187
static List * loaded
static int store_spool_save_ack(Msg *msg, ack_status_t status)
void(* store_shutdown)(void)
Definition: bb_store.c:76
static int store_spool_load(void(*receive_msg)(Msg *))
int(* store_load)(void(*receive_msg)(Msg *))
Definition: bb_store.c:74
#define gwlist_create()
Definition: list.h:136
int(* store_save)(Msg *msg)
Definition: bb_store.c:72
void gwlist_add_producer(List *list)
Definition: list.c:383
static Counter * counter

◆ store_spool_load()

static int store_spool_load ( void(*)(Msg *)  receive_msg)
static

Definition at line 197 of file bb_store_spool.c.

References counter, counter_value(), dispatch(), for_each_file(), gwlist_remove_producer(), info(), loaded, and spool.

Referenced by store_spool_init().

198 {
199  int rc;
200 
201  /* check if we are active */
202  if (spool == NULL)
203  return 0;
204 
205  /* sanity check */
206  if (receive_msg == NULL)
207  return -1;
208 
209  rc = for_each_file(spool, 0, dispatch, receive_msg);
210 
211  info(0, "Loaded %ld messages from store.", counter_value(counter));
212 
213  /* allow using of storage */
215 
216  return rc;
217 }
void info(int err, const char *fmt,...)
Definition: log.c:672
static Octstr * spool
static void dispatch(const Octstr *filename, void *data)
static int for_each_file(const Octstr *dir_s, int ignore_err, void(*cb)(const Octstr *, void *), void *data)
void gwlist_remove_producer(List *list)
Definition: list.c:401
static List * loaded
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
static Counter * counter

◆ store_spool_messages()

static long store_spool_messages ( )
static

Definition at line 94 of file bb_store_spool.c.

References counter, and counter_value().

Referenced by store_spool_init().

95 {
96  return counter ? counter_value(counter) : -1;
97 }
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
static Counter * counter

◆ store_spool_save()

static int store_spool_save ( Msg msg)
static

Definition at line 220 of file bb_store_spool.c.

References counter, counter_decrease(), counter_increase(), error(), filename, gwlist_consume(), loaded, MAX_DIRS, msg, MSG_PARAM_UNDEFINED, octstr_create, octstr_destroy(), octstr_format(), octstr_get_cstr, octstr_hash_key(), octstr_len(), spool, store_msg_pack, uuid_generate(), uuid_is_null(), UUID_STR_LEN, and uuid_unparse().

Referenced by store_spool_init(), and store_spool_save_ack().

221 {
222  char id[UUID_STR_LEN + 1];
223  Octstr *id_s;
224 
225  /* always set msg id and timestamp */
226  if (msg_type(msg) == sms && uuid_is_null(msg->sms.id))
227  uuid_generate(msg->sms.id);
228 
229  if (msg_type(msg) == sms && msg->sms.time == MSG_PARAM_UNDEFINED)
230  time(&msg->sms.time);
231 
232  if (spool == NULL)
233  return 0;
234 
235  /* blocke here if store still not loaded */
237 
238  switch(msg_type(msg)) {
239  case sms:
240  {
241  Octstr *os = store_msg_pack(msg);
242  Octstr *filename, *dir;
243  int fd;
244  size_t wrc;
245 
246  if (os == NULL) {
247  error(0, "Could not pack message.");
248  return -1;
249  }
250  uuid_unparse(msg->sms.id, id);
251  id_s = octstr_create(id);
252  dir = octstr_format("%S/%ld", spool, octstr_hash_key(id_s) % MAX_DIRS);
253  octstr_destroy(id_s);
254  if (mkdir(octstr_get_cstr(dir), S_IRUSR|S_IWUSR|S_IXUSR) == -1 && errno != EEXIST) {
255  error(errno, "Could not create directory `%s'.", octstr_get_cstr(dir));
256  octstr_destroy(dir);
257  octstr_destroy(os);
258  return -1;
259  }
260  filename = octstr_format("%S/%s", dir, id);
261  octstr_destroy(dir);
262  if ((fd = open(octstr_get_cstr(filename), O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR)) == -1) {
263  error(errno, "Could not open file `%s'.", octstr_get_cstr(filename));
265  octstr_destroy(os);
266  return -1;
267  }
268  for (wrc = 0; wrc < octstr_len(os); ) {
269  size_t rc = write(fd, octstr_get_cstr(os) + wrc, octstr_len(os) - wrc);
270  if (rc == -1) {
271  /* remove file */
272  error(errno, "Could not write message to `%s'.", octstr_get_cstr(filename));
273  close(fd);
274  if (unlink(octstr_get_cstr(filename)) == -1)
275  error(errno, "Oops, Could not remove failed file `%s'.", octstr_get_cstr(filename));
276  octstr_destroy(os);
278  return -1;
279  }
280  wrc += rc;
281  }
282  close(fd);
285  octstr_destroy(os);
286  break;
287  }
288  case ack:
289  {
290  Octstr *filename;
291  uuid_unparse(msg->ack.id, id);
292  id_s = octstr_create(id);
293  filename = octstr_format("%S/%ld/%s", spool, octstr_hash_key(id_s) % MAX_DIRS, id);
294  octstr_destroy(id_s);
295  if (unlink(octstr_get_cstr(filename)) == -1) {
296  error(errno, "Could not unlink file `%s'.", octstr_get_cstr(filename));
298  return -1;
299  }
302  break;
303  }
304  default:
305  return -1;
306  }
307 
308  return 0;
309 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static Octstr * spool
msg_type
Definition: msg.h:73
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
void uuid_generate(uuid_t out)
Definition: gw_uuid.c:393
unsigned long counter_decrease(Counter *counter)
Definition: counter.c:155
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
#define MAX_DIRS
int uuid_is_null(const uuid_t uu)
Definition: gw_uuid.c:413
static List * loaded
unsigned long octstr_hash_key(Octstr *ostr)
Definition: octstr.c:2523
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
char filename[FILENAME_MAX+1]
Definition: log.c:171
#define octstr_create(cstr)
Definition: octstr.h:125
Octstr *(* store_msg_pack)(Msg *msg)
Definition: bb_store.c:77
#define UUID_STR_LEN
Definition: gw_uuid.h:19
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
void * gwlist_consume(List *list)
Definition: list.c:427
#define MSG_PARAM_UNDEFINED
Definition: msg.h:71
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static Counter * counter

◆ store_spool_save_ack()

static int store_spool_save_ack ( Msg msg,
ack_status_t  status 
)
static

Definition at line 312 of file bb_store_spool.c.

References msg, msg_create, msg_destroy(), status::status, store_spool_save(), and uuid_copy().

Referenced by store_spool_init().

313 {
314  int ret;
315  Msg *nack = msg_create(ack);
316 
317  nack->ack.nack = status;
318  uuid_copy(nack->ack.id, msg->sms.id);
319  nack->ack.time = msg->sms.time;
320  ret = store_spool_save(nack);
321  msg_destroy(nack);
322 
323  return ret;
324 }
#define msg_create(type)
Definition: msg.h:136
Definition: msg.h:79
static int store_spool_save(Msg *msg)
void uuid_copy(uuid_t dst, const uuid_t src)
Definition: gw_uuid.c:150
void msg_destroy(Msg *msg)
Definition: msg.c:132
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
Octstr * status
Definition: bb_store.c:108

◆ store_spool_shutdown()

static void store_spool_shutdown ( )
static

Definition at line 327 of file bb_store_spool.c.

References counter, counter_destroy(), gwlist_destroy(), loaded, octstr_destroy(), and spool.

Referenced by store_spool_init().

328 {
329  if (spool == NULL)
330  return;
331 
334  gwlist_destroy(loaded, NULL);
335 }
static Octstr * spool
void counter_destroy(Counter *counter)
Definition: counter.c:110
static List * loaded
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
static Counter * counter
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

Variable Documentation

◆ counter

◆ loaded

List* loaded
static

◆ spool

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