Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

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"

Include dependency graph for bb_store_spool.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  status

Defines

#define MAX_DIRS   100

Functions

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

Variables

Octstrspool
Countercounter
Listloaded


Define Documentation

#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

void dispatch const Octstr filename,
void *  data
[static]
 

Definition at line 239 of file bb_store_spool.c.

References counter, counter_increase(), error(), filename, octstr_destroy(), octstr_get_cstr, octstr_read_file(), and store_msg_unpack.

Referenced by store_spool_load().

00240 {
00241     Octstr *msg_s;
00242     Msg *msg;
00243     void(*receive_msg)(Msg*) = data;
00244 
00245     /* debug("", 0, "dispatch(%s,...) called", octstr_get_cstr(filename)); */
00246 
00247     msg_s = octstr_read_file(octstr_get_cstr(filename));
00248     if (msg_s == NULL)
00249         return;
00250     msg = store_msg_unpack(msg_s);
00251     octstr_destroy(msg_s);
00252     if (msg != NULL) {
00253         receive_msg(msg);
00254         counter_increase(counter);
00255     } else {
00256         error(0, "Could not unpack message `%s'", octstr_get_cstr(filename));
00257     }
00258 }

Here is the call graph for this function:

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 data, error(), filename, Octstr, octstr_destroy(), octstr_format(), and octstr_get_cstr.

Referenced by store_spool_load(), and store_spool_status().

00101 {
00102     DIR *dir;
00103     struct dirent *ent;
00104     struct stat stat;
00105     int ret = 0;
00106 
00107     if ((dir = opendir(octstr_get_cstr(dir_s))) == NULL) {
00108         error(errno, "Could not open directory `%s'", octstr_get_cstr(dir_s));
00109         return -1;
00110     }
00111     while((ent = readdir(dir)) != NULL) {
00112         Octstr *filename;
00113         if (*(ent->d_name) == '.') /* skip hidden files */
00114             continue;
00115         filename = octstr_format("%S/%s", dir_s, ent->d_name);
00116         if (lstat(octstr_get_cstr(filename), &stat) == -1) {
00117             if (!ignore_err)
00118                 error(errno, "Could not get stat for `%s'", octstr_get_cstr(filename));
00119             ret = -1;
00120         } else if (S_ISDIR(stat.st_mode) && for_each_file(filename, ignore_err, cb, data) == -1) {
00121             ret = -1;
00122         } else if (S_ISREG(stat.st_mode) && cb != NULL)
00123             cb(filename, data);
00124         octstr_destroy(filename);
00125         if (ret == -1 && ignore_err)
00126             ret = 0;
00127         else if (ret == -1)
00128             break;
00129     }
00130     closedir(dir);
00131 
00132     return ret;
00133 }

Here is the call graph for this function:

void status_cb const Octstr filename,
void *  d
[static]
 

Definition at line 142 of file bb_store_spool.c.

References data, DC_8BIT, DC_UCS2, DC_UNDEF, filename, status::format, gw_gmtime(), gw_localtime(), mo, msg_destroy(), mt_push, mt_reply, octstr_binary_to_hex(), octstr_destroy(), octstr_format_append(), octstr_get_cstr, octstr_read_file(), report_mo, report_mt, status::status, store_msg_unpack, UUID_STR_LEN, and uuid_unparse().

Referenced by store_spool_status().

00143 {
00144     struct status *data = d;
00145     struct tm tm;
00146     char id[UUID_STR_LEN + 1];
00147     Octstr *msg_s;
00148     Msg *msg;
00149 
00150     msg_s = octstr_read_file(octstr_get_cstr(filename));
00151     msg = store_msg_unpack(msg_s);
00152     octstr_destroy(msg_s);
00153     if (msg == NULL)
00154         return;
00155 
00156     /* transform the time value */
00157 #if LOG_TIMESTAMP_LOCALTIME
00158     tm = gw_localtime(msg->sms.time);
00159 #else
00160     tm = gw_gmtime(msg->sms.time);
00161 #endif
00162     if (msg->sms.udhdata)
00163         octstr_binary_to_hex(msg->sms.udhdata, 1);
00164     if (msg->sms.msgdata &&
00165         (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2 ||
00166         (msg->sms.coding == DC_UNDEF && msg->sms.udhdata)))
00167         octstr_binary_to_hex(msg->sms.msgdata, 1);
00168 
00169     uuid_unparse(msg->sms.id, id);
00170 
00171     octstr_format_append(data->status, data->format,
00172         id,
00173         (msg->sms.sms_type == mo ? "MO" :
00174         msg->sms.sms_type == mt_push ? "MT-PUSH" :
00175         msg->sms.sms_type == mt_reply ? "MT-REPLY" :
00176         msg->sms.sms_type == report_mo ? "DLR-MO" :
00177         msg->sms.sms_type == report_mt ? "DLR-MT" : ""),
00178         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
00179         tm.tm_hour, tm.tm_min, tm.tm_sec,
00180         (msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : ""),
00181         (msg->sms.receiver ? octstr_get_cstr(msg->sms.receiver) : ""),
00182         (msg->sms.smsc_id ? octstr_get_cstr(msg->sms.smsc_id) : ""),
00183         (msg->sms.boxc_id ? octstr_get_cstr(msg->sms.boxc_id) : ""),
00184         (msg->sms.udhdata ? octstr_get_cstr(msg->sms.udhdata) : ""),
00185         (msg->sms.msgdata ? octstr_get_cstr(msg->sms.msgdata) : ""));
00186 
00187     msg_destroy(msg);
00188 }

Here is the call graph for this function:

int store_spool_dump  )  [static]
 

Definition at line 87 of file bb_store_spool.c.

00088 {
00089     /* nothing todo */
00090     return 0;
00091 }

int store_spool_init const Octstr fname  ) 
 

Init functions for different store types.

Definition at line 402 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_load, store_messages, store_save, store_save_ack, store_shutdown, and store_status.

Referenced by store_init().

00403 {
00404     DIR *dir;
00405 
00406     store_messages = store_spool_messages;
00407     store_save = store_spool_save;
00408     store_save_ack = store_spool_save_ack;
00409     store_load = store_spool_load;
00410     store_dump = store_spool_dump;
00411     store_shutdown = store_spool_shutdown;
00412     store_status = store_spool_status;
00413 
00414     if (store_dir == NULL)
00415         return 0;
00416 
00417     /* check if we can open directory */
00418     if ((dir = opendir(octstr_get_cstr(store_dir))) == NULL) {
00419         error(errno, "Could not open directory `%s'", octstr_get_cstr(store_dir));
00420         return -1;
00421     }
00422     closedir(dir);
00423 
00424     loaded = gwlist_create();
00425     gwlist_add_producer(loaded);
00426     spool = octstr_duplicate(store_dir);
00427     counter = counter_create();
00428 
00429     return 0;
00430 }

Here is the call graph for this function:

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

Definition at line 261 of file bb_store_spool.c.

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

00262 {
00263     int rc;
00264 
00265     /* check if we are active */
00266     if (spool == NULL)
00267         return 0;
00268         
00269     /* sanity check */
00270     if (receive_msg == NULL)
00271         return -1;
00272 
00273     rc = for_each_file(spool, 0, dispatch, receive_msg);
00274 
00275     info(0, "Loaded %ld messages from store.", counter_value(counter));
00276 
00277     /* allow using of storage */
00278     gwlist_remove_producer(loaded);
00279 
00280     return rc;
00281 }

Here is the call graph for this function:

long store_spool_messages  )  [static]
 

Definition at line 94 of file bb_store_spool.c.

References counter, and counter_value().

00095 {
00096     return counter ? counter_value(counter) : -1;
00097 }

Here is the call graph for this function:

int store_spool_save Msg msg  )  [static]
 

Definition at line 284 of file bb_store_spool.c.

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

Referenced by store_spool_save_ack().

00285 {
00286     char id[UUID_STR_LEN + 1];
00287     Octstr *id_s;
00288 
00289     /* always set msg id and timestamp */
00290     if (msg_type(msg) == sms && uuid_is_null(msg->sms.id))
00291         uuid_generate(msg->sms.id);
00292 
00293     if (msg_type(msg) == sms && msg->sms.time == MSG_PARAM_UNDEFINED)
00294         time(&msg->sms.time);
00295 
00296     if (spool == NULL)
00297         return 0;
00298 
00299     /* blocke here if store still not loaded */
00300     gwlist_consume(loaded);
00301 
00302     switch(msg_type(msg)) {
00303         case sms:
00304         {
00305             Octstr *os = store_msg_pack(msg);
00306             Octstr *filename, *dir;
00307             int fd;
00308             size_t wrc;
00309 
00310             if (os == NULL) {
00311                 error(0, "Could not pack message.");
00312                 return -1;
00313             }
00314             uuid_unparse(msg->sms.id, id);
00315             id_s = octstr_create(id);
00316             dir = octstr_format("%S/%ld", spool, octstr_hash_key(id_s) % MAX_DIRS);
00317             octstr_destroy(id_s);
00318             if (mkdir(octstr_get_cstr(dir), S_IRUSR|S_IWUSR|S_IXUSR) == -1 && errno != EEXIST) {
00319                 error(errno, "Could not create directory `%s'.", octstr_get_cstr(dir));
00320                 octstr_destroy(dir);
00321                 octstr_destroy(os);
00322                 return -1;
00323             }
00324             filename = octstr_format("%S/%s", dir, id);
00325             octstr_destroy(dir);
00326             if ((fd = open(octstr_get_cstr(filename), O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR)) == -1) {
00327                 error(errno, "Could not open file `%s'.", octstr_get_cstr(filename));
00328                 octstr_destroy(filename);
00329                 octstr_destroy(os);
00330                 return -1;
00331             }
00332             for (wrc = 0; wrc < octstr_len(os); ) {
00333                 size_t rc = write(fd, octstr_get_cstr(os) + wrc, octstr_len(os) - wrc);
00334                 if (rc == -1) {
00335                     /* remove file */
00336                     error(errno, "Could not write message to `%s'.", octstr_get_cstr(filename));
00337                     close(fd);
00338                     if (unlink(octstr_get_cstr(filename)) == -1)
00339                         error(errno, "Oops, Could not remove failed file `%s'.", octstr_get_cstr(filename));
00340                     octstr_destroy(os);
00341                     octstr_destroy(filename);
00342                     return -1;
00343                 }
00344                 wrc += rc;
00345             }
00346             close(fd);
00347             counter_increase(counter);
00348             octstr_destroy(filename);
00349             octstr_destroy(os);
00350             break;
00351         }
00352         case ack:
00353         {
00354             Octstr *filename;
00355             uuid_unparse(msg->ack.id, id);
00356             id_s = octstr_create(id);
00357             filename = octstr_format("%S/%ld/%s", spool, octstr_hash_key(id_s) % MAX_DIRS, id);
00358             octstr_destroy(id_s);
00359             if (unlink(octstr_get_cstr(filename)) == -1) {
00360                 error(errno, "Could not unlink file `%s'.", octstr_get_cstr(filename));
00361                 octstr_destroy(filename);
00362                 return -1;
00363             }
00364             counter_decrease(counter);
00365             octstr_destroy(filename);
00366             break;
00367         }
00368         default:
00369             return -1;
00370     }
00371 
00372     return 0;
00373 }

Here is the call graph for this function:

int store_spool_save_ack Msg msg,
ack_status_t  status
[static]
 

Definition at line 376 of file bb_store_spool.c.

References ack, msg_create, msg_destroy(), store_spool_save(), and uuid_copy().

00377 {
00378     int ret;
00379     Msg *nack = msg_create(ack);
00380 
00381     nack->ack.nack = status;
00382     uuid_copy(nack->ack.id, msg->sms.id);
00383     nack->ack.time = msg->sms.time;
00384     ret = store_spool_save(nack);
00385     msg_destroy(nack);
00386 
00387     return ret;
00388 }

Here is the call graph for this function:

void store_spool_shutdown  )  [static]
 

Definition at line 391 of file bb_store_spool.c.

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

00392 {
00393     if (spool == NULL)
00394         return;
00395         
00396     counter_destroy(counter);
00397     octstr_destroy(spool);
00398     gwlist_destroy(loaded, NULL);
00399 }

Here is the call graph for this function:

Octstr* store_spool_status int  status_type  )  [static]
 

Definition at line 191 of file bb_store_spool.c.

References data, for_each_file(), status::format, octstr_append_cstr(), octstr_create, spool, status::status, and status_cb().

00192 {
00193     Octstr *ret = octstr_create("");
00194     const char *format;
00195     struct status data;
00196 
00197     /* check if we are active */
00198     if (spool == NULL)
00199         return ret;
00200 
00201     /* set the type based header */
00202     if (status_type == BBSTATUS_HTML) {
00203         octstr_append_cstr(ret, "<table border=1>\n"
00204             "<tr><td>SMS ID</td><td>Type</td><td>Time</td><td>Sender</td><td>Receiver</td>"
00205             "<td>SMSC ID</td><td>BOX ID</td><td>UDH</td><td>Message</td>"
00206             "</tr>\n");
00207 
00208         format = "<tr><td>%s</td><td>%s</td>"
00209                 "<td>%04d-%02d-%02d %02d:%02d:%02d</td>"
00210                 "<td>%s</td><td>%s</td><td>%s</td>"
00211                 "<td>%s</td><td>%s</td><td>%s</td></tr>\n";
00212     } else if (status_type == BBSTATUS_XML) {
00213         format = "<message>\n\t<id>%s</id>\n\t<type>%s</type>\n\t"
00214                 "<time>%04d-%02d-%02d %02d:%02d:%02d</time>\n\t"
00215                 "<sender>%s</sender>\n\t"
00216                 "<receiver>%s</receiver>\n\t<smsc-id>%s</smsc-id>\n\t"
00217                 "<box-id>%s</box-id>\n\t"
00218                 "<udh-data>%s</udh-data>\n\t<msg-data>%s</msg-data>\n\t"
00219                 "</message>\n";
00220     } else {
00221         octstr_append_cstr(ret, "[SMS ID] [Type] [Time] [Sender] [Receiver] [SMSC ID] [BOX ID] [UDH] [Message]\n");
00222         format = "[%s] [%s] [%04d-%02d-%02d %02d:%02d:%02d] [%s] [%s] [%s] [%s] [%s] [%s]\n";
00223     }
00224 
00225     data.format = format;
00226     data.status = ret;
00227     /* ignore error because files may disappear */
00228     for_each_file(spool, 1, status_cb, &data);
00229 
00230     /* set the type based footer */
00231     if (status_type == BBSTATUS_HTML) {
00232         octstr_append_cstr(ret,"</table>");
00233     }
00234 
00235     return ret;
00236 }

Here is the call graph for this function:


Variable Documentation

Counter* counter [static]
 

Definition at line 83 of file bb_store_spool.c.

Referenced by dispatch(), store_spool_init(), store_spool_load(), store_spool_messages(), store_spool_save(), and store_spool_shutdown().

List* loaded [static]
 

Definition at line 84 of file bb_store_spool.c.

Referenced by store_spool_init(), store_spool_load(), store_spool_save(), and store_spool_shutdown().

Octstr* spool [static]
 

Definition at line 82 of file bb_store_spool.c.

Referenced by store_spool_init(), store_spool_load(), store_spool_save(), store_spool_shutdown(), and store_spool_status().

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