#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:

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) |
| Octstr * | store_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 | |
| Octstr * | spool |
| Counter * | counter |
| List * | loaded |
|
|
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(). |
|
||||||||||||
|
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:

|
||||||||||||||||||||
|
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:

|
||||||||||||
|
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:

|
|
Definition at line 87 of file bb_store_spool.c. 00088 {
00089 /* nothing todo */
00090 return 0;
00091 }
|
|
|
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:

|
|
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:

|
|
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:

|
|
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:

|
||||||||||||
|
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:

|
|
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:

|
|
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:

|
|
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(). |
|
|
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(). |
|
|
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(). |