[PATCH] rewrite/cleanup of dlr handling
Alexander Malysh <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Organization | Centrium GmbH |
| Message-ID | <[email protected]> |
Hi all, attached "big" patch does following: 1) adds more abstraction to dlr handling 2) makes it easier to add new dlr storage types to kannel without touching a dlr-core code 3) makes dlr-core ready for coming (hopefully soon) modules API 4) makes handling/creating of dlr messages uniformly over all storage types Please look in it. Comments are very welcome... -- Best regards / Mit besten Grüßen aus Köln Dipl.-Ing. Alexander Malysh ___________________________________ Centrium GmbH Ehrenstrasse 2 50672 Köln Fon: +49 (0221) 277 49 240 Fax: +49 (0221) 277 49 109 email: a.malysh at centrium.de web: http://www.centrium.de msn: olek2002 at hotmail.com ___________________________________________ Please avoid sending me Word or PowerPoint attachments. See http://www.fsf.org/philosophy/no-word-attachments.html
dlr_cleanup.diff
(text/x-diff, 81.4 KB)
? doc/alligata/alligata.tex
? test/test_dbpool
? test/test_md5
? test/test_octstr_dump
? utils/mtbatch
Index: gw/bearerbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/bearerbox.c,v
retrieving revision 1.139
diff -a -b -u -r1.139 bearerbox.c
--- gw/bearerbox.c 26 May 2003 18:37:11 -0000 1.139
+++ gw/bearerbox.c 26 May 2003 21:30:01 -0000
@@ -735,7 +735,7 @@
(float)counter_value(incoming_sms_counter)/t,
(float)counter_value(outgoing_sms_counter)/t,
dlr_messages(),
- octstr_get_cstr(dlr_type));
+ dlr_type());
octstr_destroy(version);
ret = octstr_create(buf);
Index: gw/dlr.c
===================================================================
RCS file: /home/cvs/gateway/gw/dlr.c,v
retrieving revision 1.33
diff -a -b -u -r1.33 dlr.c
--- gw/dlr.c 27 Feb 2003 09:48:59 -0000 1.33
+++ gw/dlr.c 26 May 2003 21:30:02 -0000
@@ -5,6 +5,7 @@
*
* Andreas Fink <[email protected]>, 18.08.2001
* Stipe Tolj <[email protected]>, 22.03.2002
+ * Alexander Malysh <[email protected]> 2003
*
* Changes:
* 2001-12-17: [email protected]:
@@ -31,229 +32,147 @@
#include "gwlib/gwlib.h"
#include "sms.h"
#include "dlr.h"
+#include "dlr_p.h"
+
+/* Our callback functions */
+static struct dlr_storage *handles = NULL;
+
/*
-#define DLR_TRACE 1
-*/
-/*
- * We use memory based DLR
- * the structure of a delivery report waiting list entry
+ * Function to allocate a new struct dlr_entry entry
+ * and intialize it to zero
*/
+struct dlr_entry *dlr_entry_create()
+{
+ struct dlr_entry *dlr;
-typedef struct dlr_wle {
- Octstr *smsc;
- Octstr *timestamp;
- Octstr *source;
- Octstr *destination;
- Octstr *service;
- Octstr *url;
- int mask;
- Octstr *boxc_id;
-} dlr_wle;
-
-/*
- * This is the global list where all messages being sent out are being kept track
- * of his list is looked up once a delivery report comes in
- */
-static List *dlr_waiting_list;
-static void dlr_destroy(dlr_wle *dlr);
-static void dlr_init_mem(void);
-#ifdef DLR_MYSQL
-static void dlr_init_mysql(Cfg* cfg);
-#endif
-#ifdef DLR_SDB
-static void dlr_init_sdb(Cfg* cfg);
-#endif
-static void dlr_shutdown_mem(void);
-static void dlr_shutdown_mysql(void);
-static dlr_wle *dlr_new(void);
+ dlr = gw_malloc(sizeof(*dlr));
+ gw_assert(dlr != NULL);
+
+ /* set all values to NULL */
+ memset(dlr, 0, sizeof(*dlr));
+
+ return dlr;
+}
/*
- * At startup initialize the list, use abstraction to
- * allow to add additional dlr_init_foobar() routines here.
- *
- * Check 'dlr-storage' directive in core group to see how DLRs are
- * processed.
+ * Duplicate dlr entry
*/
-
-static void dlr_init_mem()
+struct dlr_entry *dlr_entry_duplicate(const struct dlr_entry *dlr)
{
- dlr_waiting_list = list_create();
+ struct dlr_entry *ret;
+
+ if (dlr == NULL)
+ return NULL;
+
+ ret = dlr_entry_create();
+ ret->smsc = octstr_duplicate(dlr->smsc);
+ ret->timestamp = octstr_duplicate(dlr->timestamp);
+ ret->source = octstr_duplicate(dlr->source);
+ ret->destination = octstr_duplicate(dlr->destination);
+ ret->service = octstr_duplicate(dlr->service);
+ ret->url = octstr_duplicate(dlr->url);
+ ret->boxc_id = octstr_duplicate(dlr->boxc_id);
+ ret->mask = dlr->mask;
+
+ return ret;
}
+/*
+ * Function to destroy the struct dlr_entry entry
+ */
+void dlr_entry_destroy(struct dlr_entry *dlr)
+{
+ /* sanity check */
+ if (dlr == NULL)
+ return;
+
+#define O_DELETE(a) { if (a) octstr_destroy(a); a = NULL; }
+
+ O_DELETE (dlr->smsc);
+ O_DELETE (dlr->timestamp);
+ O_DELETE (dlr->source);
+ O_DELETE (dlr->destination);
+ O_DELETE (dlr->service);
+ O_DELETE (dlr->url);
+ O_DELETE (dlr->boxc_id);
+
+#undef O_DELETE
+
+ dlr->mask = 0;
+ gw_free(dlr);
+}
/*
* Load all configuration directives that are common for all database
* types that use the 'dlr-db' group to define which attributes are
* used in the table
*/
-#ifdef DLR_DB
-static void dlr_db_init(CfgGroup *grp)
+struct dlr_db_fields *dlr_db_fields_create(CfgGroup *grp)
{
- if (!(table = cfg_get(grp, octstr_imm("table"))))
+ struct dlr_db_fields *ret = NULL;
+
+ ret = gw_malloc(sizeof(*ret));
+ gw_assert(ret != NULL);
+ memset(ret, 0, sizeof(*ret));
+
+ if (!(ret->table = cfg_get(grp, octstr_imm("table"))))
panic(0, "DLR: DB: directive 'table' is not specified!");
- if (!(field_smsc = cfg_get(grp, octstr_imm("field-smsc"))))
+ if (!(ret->field_smsc = cfg_get(grp, octstr_imm("field-smsc"))))
panic(0, "DLR: DB: directive 'field-smsc' is not specified!");
- if (!(field_ts = cfg_get(grp, octstr_imm("field-timestamp"))))
+ if (!(ret->field_ts = cfg_get(grp, octstr_imm("field-timestamp"))))
panic(0, "DLR: DB: directive 'field-timestamp' is not specified!");
- if (!(field_src = cfg_get(grp, octstr_imm("field-source"))))
+ if (!(ret->field_src = cfg_get(grp, octstr_imm("field-source"))))
panic(0, "DLR: DB: directive 'field-source' is not specified!");
- if (!(field_dst = cfg_get(grp, octstr_imm("field-destination"))))
+ if (!(ret->field_dst = cfg_get(grp, octstr_imm("field-destination"))))
panic(0, "DLR: DB: directive 'field-destination' is not specified!");
- if (!(field_serv = cfg_get(grp, octstr_imm("field-service"))))
+ if (!(ret->field_serv = cfg_get(grp, octstr_imm("field-service"))))
panic(0, "DLR: DB: directive 'field-service' is not specified!");
- if (!(field_url = cfg_get(grp, octstr_imm("field-url"))))
+ if (!(ret->field_url = cfg_get(grp, octstr_imm("field-url"))))
panic(0, "DLR: DB: directive 'field-url' is not specified!");
- if (!(field_mask = cfg_get(grp, octstr_imm("field-mask"))))
+ if (!(ret->field_mask = cfg_get(grp, octstr_imm("field-mask"))))
panic(0, "DLR: DB: directive 'field-mask' is not specified!");
- if (!(field_status = cfg_get(grp, octstr_imm("field-status"))))
+ if (!(ret->field_status = cfg_get(grp, octstr_imm("field-status"))))
panic(0, "DLR: DB: directive 'field-status' is not specified!");
- if (!(field_boxc = cfg_get(grp, octstr_imm("field-boxc-id"))))
+ if (!(ret->field_boxc = cfg_get(grp, octstr_imm("field-boxc-id"))))
panic(0, "DLR: DB: directive 'field-boxc-id' is not specified!");
-}
-#endif
-
-#ifdef DLR_MYSQL
-static void dlr_init_mysql(Cfg* cfg)
-{
- CfgGroup *grp;
- List *grplist;
- Octstr *mysql_host, *mysql_user, *mysql_pass, *mysql_db, *mysql_id;
- Octstr *p = NULL;
-
- /*
- * check for all mandatory directives that specify the field names
- * of the used MySQL table
- */
- if (!(grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))))
- panic(0, "DLR: MySQL: group 'dlr-db' is not specified!");
-
- if (!(mysql_id = cfg_get(grp, octstr_imm("id"))))
- panic(0, "DLR: MySQL: directive 'id' is not specified!");
-
- dlr_db_init(grp);
-
- /*
- * now grap the required information from the 'mysql-connection' group
- * with the mysql-id we just obtained
- *
- * we have to loop through all available MySQL connection definitions
- * and search for the one we are looking for
- */
-
- grplist = cfg_get_multi_group(cfg, octstr_imm("mysql-connection"));
- while (grplist && (grp = list_extract_first(grplist)) != NULL) {
- p = cfg_get(grp, octstr_imm("id"));
- if (p != NULL && octstr_compare(p, mysql_id) == 0) {
- goto found;
- }
- octstr_destroy(p);
- }
- panic(0, "DLR: MySQL: connection settings for id '%s' are not specified!",
- octstr_get_cstr(mysql_id));
-
-found:
- octstr_destroy(p);
- list_destroy(grplist, NULL);
-
- if (!(mysql_host = cfg_get(grp, octstr_imm("host"))))
- panic(0, "DLR: MySQL: directive 'host' is not specified!");
- if (!(mysql_user = cfg_get(grp, octstr_imm("mysql-username"))))
- panic(0, "DLR: MySQL: directive 'mysql-username' is not specified!");
- if (!(mysql_pass = cfg_get(grp, octstr_imm("mysql-password"))))
- panic(0, "DLR: MySQL: directive 'mysql-password' is not specified!");
- if (!(mysql_db = cfg_get(grp, octstr_imm("database"))))
- panic(0, "DLR: MySQL: directive 'database' is not specified!");
-
- /*
- * ok, ready to connect to MySQL
- */
- mysql_init(&mysql);
- connection = mysql_real_connect(&mysql,
- octstr_get_cstr(mysql_host), octstr_get_cstr(mysql_user),
- octstr_get_cstr(mysql_pass), octstr_get_cstr(mysql_db),
- 0, NULL, 0);
- /*
- * XXX should a failing connect throw panic?!
- */
- if (connection == NULL) {
- error(0,"DLR: MySQL: can not connect to database!");
- error(0,"MYSQL: %s", mysql_error(&mysql));
- } else {
- info(0,"Connected to mysql server at %s.", octstr_get_cstr(mysql_host));
- info(0,"MYSQL: server version %s, client version %s.",
- mysql_get_server_info(&mysql), mysql_get_client_info());
- }
-
- octstr_destroy(mysql_db);
- octstr_destroy(mysql_host);
- octstr_destroy(mysql_user);
- octstr_destroy(mysql_pass);
- octstr_destroy(mysql_id);
+ return ret;
}
-#endif /* DLR_MYSQL */
-#ifdef DLR_SDB
-static void dlr_init_sdb(Cfg* cfg)
+void dlr_db_fields_destroy(struct dlr_db_fields *fields)
{
- CfgGroup *grp;
- List *grplist;
- Octstr *sdb_url, *sdb_id;
- Octstr *p = NULL;
-
- /*
- * check for all mandatory directives that specify the field names
- * of the used table
- */
- if (!(grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))))
- panic(0, "DLR: SDB: group 'dlr-db' is not specified!");
+ /* sanity check */
+ if (fields == NULL)
+ return;
- if (!(sdb_id = cfg_get(grp, octstr_imm("id"))))
- panic(0, "DLR: SDB: directive 'id' is not specified!");
+#define O_DELETE(a) { if (a) octstr_destroy(a); a = NULL; }
- dlr_db_init(grp);
+ O_DELETE (fields->table);
+ O_DELETE (fields->field_smsc);
+ O_DELETE (fields->field_ts);
+ O_DELETE (fields->field_src);
+ O_DELETE (fields->field_dst);
+ O_DELETE (fields->field_serv);
+ O_DELETE (fields->field_url);
+ O_DELETE (fields->field_mask);
+ O_DELETE (fields->field_status);
+ O_DELETE (fields->field_boxc);
- /*
- * now grap the required information from the 'mysql-connection' group
- * with the sdb-id we just obtained
- *
- * we have to loop through all available SDB connection definitions
- * and search for the one we are looking for
- */
+#undef O_DELETE
- grplist = cfg_get_multi_group(cfg, octstr_imm("sdb-connection"));
- while (grplist && (grp = list_extract_first(grplist)) != NULL) {
- p = cfg_get(grp, octstr_imm("id"));
- if (p != NULL && octstr_compare(p, sdb_id) == 0) {
- goto found;
- }
- }
- panic(0, "DLR: SDB: connection settings for id '%s' are not specified!",
- octstr_get_cstr(sdb_id));
-
-found:
- octstr_destroy(p);
- list_destroy(grplist, NULL);
+ gw_free(fields);
+}
- if (!(sdb_url = cfg_get(grp, octstr_imm("url"))))
- panic(0, "DLR: SDB: directive 'url' is not specified!");
- /*
- * ok, ready to connect
+/*
+ * initialize specifically dlr storage. If defined storage is unknown
+ * then panic.
*/
- info(0,"Connecting to sdb resource <%s>.", octstr_get_cstr(sdb_url));
- connection = sdb_open(octstr_get_cstr(sdb_url));
- octstr_destroy(sdb_url);
-}
-#endif /* DLR_SDB */
-
void dlr_init(Cfg* cfg)
{
CfgGroup *grp;
-
- /* create the DLR mutex */
- dlr_mutex = mutex_create();
+ Octstr *dlr_type;
/* check which DLR storage type we are using */
grp = cfg_get_single_group(cfg, octstr_imm("core"));
@@ -263,7 +182,6 @@
* assume we are using internal memory in case no directive
* has been specified, warn the user anyway
*/
-
if (dlr_type == NULL) {
dlr_type = octstr_imm("internal");
warning(0, "DLR: using default 'internal' for storage type.");
@@ -271,732 +189,189 @@
/* call the sub-init routine */
if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
-#ifdef DLR_MYSQL
- dlr_init_mysql(cfg);
-#else
+ handles = dlr_init_mysql(cfg);
+ if (handles == NULL)
panic(0, "DLR: storage type defined as '%s', but no MySQL support build in!",
octstr_get_cstr(dlr_type));
-#endif
- } else
- if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
- dlr_init_mem();
- } else
- if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
-#ifdef DLR_SDB
- dlr_init_sdb(cfg);
-#else
+ } else if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
+ handles = dlr_init_sdb(cfg);
+ if (handles == NULL)
panic(0, "DLR: storage type defined as '%s', but no LibSDB support build in!",
octstr_get_cstr(dlr_type));
-#endif
+ } else if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
+ handles = dlr_init_mem(cfg);
+ }
/*
* add aditional types here
*/
- } else {
+ if (handles == NULL) {
panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
}
-}
-
-
+ /* check needed function pointers */
+ if (handles->dlr_add == NULL || handles->dlr_get || handles->dlr_remove)
+ panic(0, "DLR: storage type '%s' don't implement needed functions", octstr_get_cstr(dlr_type));
-/*
- * At stutdown destroy the list, use abstraction to
- * allow to add additional dlr_shutdown_foobar() routines here.
- *
- * Check 'dlr-storage' directive in core group to see how DLRs are
- * processed.
- */
+ /* get info from storage */
+ info(0, "DLR using storage type: %s", handles->type);
-static void dlr_shutdown_mem()
-{
- list_destroy(dlr_waiting_list, (list_item_destructor_t *)dlr_destroy);
+ /* cleanup */
+ octstr_destroy(dlr_type);
}
-static void dlr_shutdown_mysql()
-{
-#ifdef DLR_MYSQL
- mysql_close(connection);
-#endif
-}
-
-static void dlr_shutdown_sdb()
-{
-#ifdef DLR_SDB
- sdb_close(connection);
-#endif
-}
+/*
+ * Shutdown dlr storage
+ */
void dlr_shutdown()
{
- /* call the sub-init routine */
- if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
- dlr_shutdown_mysql();
- } else
- if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
- dlr_shutdown_mem();
- } else
- if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
- dlr_shutdown_sdb();
-
- /*
- * add aditional types here
- */
-
- } else {
- panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
- }
-
- /* destroy the DLR mutex */
- mutex_destroy(dlr_mutex);
+ if (handles != NULL && handles->dlr_shutdown != NULL)
+ handles->dlr_shutdown();
}
-
-
/*
- * internal function to allocate a new dlr_wle entry
- * and intialize it to zero
+ * Return count waiting delivery entries or -1 if error occurs
*/
-
-static dlr_wle *dlr_new()
+long dlr_messages(void)
{
- int i;
- dlr_wle *dlr;
+ if (handles != NULL && handles->dlr_messages != NULL)
+ return handles->dlr_messages();
- dlr = gw_malloc(sizeof(dlr_wle));
- if (dlr)
- for(i=0;i<sizeof(dlr_wle);i++)
- ((char *)dlr)[i] = 0;
- return dlr;
+ return -1;
}
-
/*
- * internal function to destroy the dlr_wle entry
+ * Return type of used dlr storage
*/
-
-static void dlr_destroy(dlr_wle *dlr)
+const char* dlr_type()
{
- O_DELETE (dlr->smsc);
- O_DELETE (dlr->timestamp);
- O_DELETE (dlr->source);
- O_DELETE (dlr->destination);
- O_DELETE (dlr->service);
- O_DELETE (dlr->url);
- O_DELETE (dlr->boxc_id);
- dlr->mask = 0;
- gw_free(dlr);
+ if (handles != NULL && handles->type != NULL)
+ return handles->type;
+
+ return "unknown";
}
/*
- * external functions
+ * Add new dlr entry into dlr storage
*/
-
-static void dlr_add_mem(char *smsc, char *ts, char *src, char *dst,
- char *service, char *url, int mask, char *boxc)
+void dlr_add(const Octstr *smsc, const Octstr *ts, const Msg *msg)
{
- dlr_wle *dlr;
-
- if (mask & 0x1F) {
- dlr = dlr_new();
+ struct dlr_entry *dlr = NULL;
- debug("dlr.dlr", 0, "Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d, boxc=%s",
- smsc, ts, src, dst, mask, boxc);
+ /* sanity check */
+ if (handles == NULL || handles->dlr_add == NULL || msg == NULL)
+ return;
+
+ /* check if delivery receipt requested */
+ if (!(msg->sms.dlr_mask & (DLR_SUCCESS|DLR_FAIL|DLR_BUFFERED|DLR_SMSC_SUCCESS|DLR_SMSC_FAIL)))
+ return;
+
+ /* allocate new struct dlr_entry struct */
+ dlr = dlr_entry_create();
+ gw_assert(dlr != NULL);
+
+ /* now copy all values, we are interested in */
+ dlr->smsc = octstr_duplicate(smsc);
+ dlr->timestamp = octstr_duplicate(ts);
+ dlr->source = octstr_duplicate(msg->sms.sender);
+ dlr->destination = octstr_duplicate(msg->sms.receiver);
+ dlr->service = octstr_duplicate(msg->sms.service);
+ dlr->url = octstr_duplicate(msg->sms.dlr_url);
+ dlr->boxc_id = octstr_duplicate(msg->sms.boxc_id);
+ dlr->mask = msg->sms.dlr_mask;
+
+ debug("dlr.dlr", 0, "DLR[%s]: Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d, boxc=%s",
+ dlr_type(), octstr_get_cstr(dlr->smsc), octstr_get_cstr(dlr->timestamp),
+ octstr_get_cstr(dlr->source), octstr_get_cstr(dlr->destination), dlr->mask, octstr_get_cstr(dlr->boxc_id));
- dlr->smsc = octstr_create(smsc);
- dlr->timestamp = octstr_create(ts);
- dlr->source = octstr_create(src);
- dlr->destination = octstr_create(dst);
- dlr->service = octstr_create(service);
- dlr->url = octstr_create(url);
- dlr->boxc_id = octstr_create(boxc);
- dlr->mask = mask;
- list_append(dlr_waiting_list,dlr);
- }
+ /* call registered function */
+ handles->dlr_add(dlr);
}
-static void dlr_add_mysql(char *smsc, char *ts, char *src, char *dst,
- char *service, char *url, int mask, char *boxc)
-{
-#ifdef DLR_MYSQL
- Octstr *sql;
- int state;
-#if defined(DLR_TRACE)
- debug("dlr.dlr", 0, "Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d",
- smsc, ts, src, dst, mask);
-#endif
-
- sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES "
- "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d');",
- octstr_get_cstr(table), octstr_get_cstr(field_smsc),
- octstr_get_cstr(field_ts),
- octstr_get_cstr(field_src), octstr_get_cstr(field_dst),
- octstr_get_cstr(field_serv), octstr_get_cstr(field_url),
- octstr_get_cstr(field_mask), octstr_get_cstr(field_boxc),
- octstr_get_cstr(field_status),
- smsc, ts, src, dst, service, url, mask, boxc, 0);
-
- mutex_lock(dlr_mutex);
-
- state = mysql_query(connection, octstr_get_cstr(sql));
- if (state != 0)
- error(0, "MYSQL: %s", mysql_error(connection));
-
-#if defined(DLR_TRACE)
- debug("dlr.dlr", 0, "sql: %s", octstr_get_cstr(sql));
-#endif
-
-octstr_destroy(sql);
- mutex_unlock(dlr_mutex);
-#endif
-}
-
-static void dlr_add_sdb(char *smsc, char *ts, char *src, char *dst,
- char *service, char *url, int mask, char *boxc)
-{
-#ifdef DLR_SDB
- Octstr *sql;
- int state;
-
- sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES "
- "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d')",
- octstr_get_cstr(table), octstr_get_cstr(field_smsc),
- octstr_get_cstr(field_ts),
- octstr_get_cstr(field_src), octstr_get_cstr(field_dst),
- octstr_get_cstr(field_serv), octstr_get_cstr(field_url),
- octstr_get_cstr(field_mask), octstr_get_cstr(field_boxc),
- octstr_get_cstr(field_status),
- smsc, ts, src, dst, service, url, mask, boxc, 0);
-
- mutex_lock(dlr_mutex);
-
- state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
- if (state == -1)
- error(0, "SDB: error in inserting DLR");
-
- octstr_destroy(sql);
- mutex_unlock(dlr_mutex);
-#endif
-}
-
-void dlr_add(char *smsc, char *ts, char *src, char *dst,
- char *keyword, char *id, int mask, char *boxc)
-{
- if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
- dlr_add_mem(smsc, ts, src, dst, keyword, id, mask, boxc);
- } else
- if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
- dlr_add_mysql(smsc, ts, src, dst, keyword, id, mask, boxc);
- } else
- if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
- dlr_add_sdb(smsc, ts, src, dst, keyword, id, mask, boxc);
-
- /*
- * add aditional types here
- */
- } else {
- panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
- }
-}
-
-
-static Msg *dlr_find_mem(char *smsc, char *ts, char *dst, int typ)
-{
- long i;
- long len;
- dlr_wle *dlr;
- Msg *msg;
- int dlr_mask;
-
- debug("dlr.dlr", 0, "Looking for DLR smsc=%s, ts=%s, dst=%s, type=%d", smsc, ts, dst, typ);
- list_lock(dlr_waiting_list);
- len = list_len(dlr_waiting_list);
- for (i=0; i < len; i++) {
- dlr = list_get(dlr_waiting_list, i);
-
- if((strcmp(octstr_get_cstr(dlr->smsc),smsc) == 0) &&
- (strcmp(octstr_get_cstr(dlr->timestamp),ts) == 0)) {
-
- dlr_mask = dlr->mask;
-
- if ((typ & dlr_mask) > 0) {
- /* its an entry we are interested in */
- msg = msg_create(sms);
- msg->sms.sms_type = report;
- msg->sms.service = octstr_duplicate(dlr->service);
- msg->sms.dlr_mask = typ;
- msg->sms.sms_type = report;
- msg->sms.smsc_id = octstr_create(smsc);
- msg->sms.sender = octstr_duplicate(dlr->destination);
- msg->sms.receiver = octstr_duplicate(dlr->source);
-
- /* if dlr_url was present, recode it here again */
- msg->sms.dlr_url = octstr_len(dlr->url) ?
- octstr_duplicate(dlr->url) : NULL;
-
- /*
- * insert orginal message to the data segment
- * later in the smsc module
- */
- msg->sms.msgdata = NULL;
-
- /*
- * If a boxc_id is available, then instruct bearerbox to
- * route this msg back to originating smsbox
+/*
+ * Return Msg* if dlr entry found in DB, otherwise NULL.
+ * NOTE: If typ is end status (e.g. DELIVERED) then dlr entry
+ will be removed from DB.
*/
- msg->sms.boxc_id = octstr_len(dlr->boxc_id) ?
- octstr_duplicate(dlr->boxc_id) : NULL;
-
- time(&msg->sms.time);
- debug("dlr.dlr", 0, "created DLR message for URL <%s>",
- octstr_get_cstr(msg->sms.dlr_url));
- } else {
- debug("dlr.dlr", 0, "ignoring DLR message because of mask");
- /* ok that was a status report but we where not interested in having it */
- msg = NULL;
- }
- if ((typ & DLR_BUFFERED) && ((dlr_mask & DLR_SUCCESS) || (dlr_mask & DLR_FAIL))) {
- info(0, "dlr not destroyed, still waiting for other delivery report");
- } else {
- list_delete(dlr_waiting_list, i, 1);
- dlr_destroy(dlr);
- }
-
- list_unlock(dlr_waiting_list);
- return msg;
- }
- }
- list_unlock(dlr_waiting_list);
- debug("dlr.dlr", 0, "DLR not found!");
- /* we couldnt find a matching entry */
- return NULL;
-}
-
-static Msg *dlr_find_mysql(char *smsc, char *ts, char *dst, int typ)
+Msg *dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ)
{
Msg *msg = NULL;
-#ifdef DLR_MYSQL
- Octstr *sql;
- int state;
- int dlr_mask;
- Octstr *dlr_service;
- Octstr *dlr_url;
- Octstr *source_addr;
- Octstr *boxc_id;
- MYSQL_RES *result;
- MYSQL_ROW row;
-
- sql = octstr_format("SELECT %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s';",
- octstr_get_cstr(field_mask), octstr_get_cstr(field_serv),
- octstr_get_cstr(field_url), octstr_get_cstr(field_src),
- octstr_get_cstr(field_boxc),
- octstr_get_cstr(table), octstr_get_cstr(field_smsc),
- smsc, octstr_get_cstr(field_ts), ts);
-
- mutex_lock(dlr_mutex);
-
- state = mysql_query(connection, octstr_get_cstr(sql));
-#if defined(DLR_TRACE)
- debug("dlr.dlr", 0, "sql: %s", octstr_get_cstr(sql));
-#endif
-
- octstr_destroy(sql);
- if (state != 0) {
- error(0, "MYSQL: %s", mysql_error(connection));
- mutex_unlock(dlr_mutex);
- return NULL;
- }
- result = mysql_store_result(connection);
- if (mysql_num_rows(result) < 1) {
- debug("dlr.mysql", 0, "no rows found");
- mysql_free_result(result);
- mutex_unlock(dlr_mutex);
- return NULL;
- }
- row = mysql_fetch_row(result);
- if (!row) {
- debug("dlr.mysql", 0, "rows found but could not load them");
- mysql_free_result(result);
- mutex_unlock(dlr_mutex);
- return NULL;
- }
+ struct dlr_entry *dlr = NULL;
- debug("dlr.mysql", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, row[3]=%s, row[4]=%s",
- row[0], row[1], row[2], (row[3] ? row[3] : "NULL"), (row[4] ? row[4] : "NULL"));
- dlr_mask = atoi(row[0]);
- dlr_service = octstr_create(row[1]);
- dlr_url = octstr_create(row[2]);
- source_addr = row[3] ? octstr_create(row[3]) : octstr_create("");
- boxc_id = row[4] ? octstr_create(row[4]) : octstr_create("");
- mysql_free_result(result);
-
- mutex_unlock(dlr_mutex);
-
- sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s';",
- octstr_get_cstr(table), octstr_get_cstr(field_status),
- typ, octstr_get_cstr(field_smsc), smsc,
- octstr_get_cstr(field_ts), ts);
-
- mutex_lock(dlr_mutex);
-
- state = mysql_query(connection, octstr_get_cstr(sql));
- octstr_destroy(sql);
- if (state != 0) {
- error(0, "MYSQL: %s", mysql_error(connection));
- mutex_unlock(dlr_mutex);
+ /* check if we have handler registered */
+ if (handles == NULL || handles->dlr_get == NULL)
return NULL;
- }
-
- mutex_unlock(dlr_mutex);
-
- if ((typ & dlr_mask)) {
- /* its an entry we are interested in */
- msg = msg_create(sms);
- msg->sms.service = octstr_duplicate(dlr_service);
- msg->sms.dlr_mask = typ;
- msg->sms.sms_type = report;
- msg->sms.smsc_id = octstr_create(smsc);
- msg->sms.sender = octstr_duplicate(source_addr);
- msg->sms.receiver = octstr_create(dst);
-
- /* if dlr_url was present, recode it here again */
- msg->sms.dlr_url = octstr_len(dlr_url) ?
- octstr_duplicate(dlr_url) : NULL;
-
- /*
- * insert orginal message to the data segment
- * later in the smsc module
- */
- msg->sms.msgdata = NULL;
-
- /*
- * If a boxc_id is available, then instruct bearerbox to
- * route this msg back to originating smsbox
- */
- msg->sms.boxc_id = octstr_len(boxc_id) ?
- octstr_duplicate(boxc_id) : NULL;
-
- time(&msg->sms.time);
- debug("dlr.dlr", 0, "created DLR message for URL <%s>",
- octstr_get_cstr(msg->sms.dlr_url));
- } else {
- debug("dlr.dlr", 0, "ignoring DLR message because of mask");
- }
-
- if ((typ & DLR_BUFFERED) && ((dlr_mask & DLR_SUCCESS) || (dlr_mask & DLR_FAIL))) {
- debug("dlr.mysql", 0, "DLR not deleted because we wait on more reports");
- } else {
- debug("dlr.mysql", 0, "removing DLR from database");
- sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1;",
- octstr_get_cstr(table), octstr_get_cstr(field_smsc),
- smsc, octstr_get_cstr(field_ts), ts);
-
- mutex_lock(dlr_mutex);
-
- state = mysql_query(connection, octstr_get_cstr(sql));
- octstr_destroy(sql);
- if (state != 0) {
- error(0, "MYSQL: %s", mysql_error(connection));
- }
-
- mutex_unlock(dlr_mutex);
- }
-
- octstr_destroy(dlr_service);
- octstr_destroy(dlr_url);
- octstr_destroy(source_addr);
- octstr_destroy(boxc_id);
-
-#endif
- return msg;
-}
-#ifdef DLR_SDB
-static int sdb_callback_add(int n, char **p, void *row)
-{
- if (!n) {
- debug("dlr.sdb", 0, "no rows found");
- return 0;
- }
-
- /* strip string into words */
- row = octstr_split(octstr_imm(p[0]), octstr_imm(" "));
- if (list_len(row) != 5) {
- debug("dlr.sdb", 0, "Row has wrong length %ld", list_len(row));
- return 0;
- }
-
- return 0;
-}
-
-static int sdb_callback_msgs(int n, char **p, void *row)
-{}
-#endif
-
-static Msg *dlr_find_sdb(char *smsc, char *ts, char *dst, int typ)
-{
- Msg *msg = NULL;
-#ifdef DLR_SDB
- Octstr *sql;
- int state;
- int dlr_mask;
- Octstr *dlr_service;
- Octstr *dlr_url;
- Octstr *source_addr;
- Octstr *boxc_id;
- List *row;
-
- sql = octstr_format("SELECT %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s'",
- octstr_get_cstr(field_mask), octstr_get_cstr(field_serv),
- octstr_get_cstr(field_url), octstr_get_cstr(field_src),
- octstr_get_cstr(field_boxc),
- octstr_get_cstr(table), octstr_get_cstr(field_smsc),
- smsc, octstr_get_cstr(field_ts), ts);
-
- mutex_lock(dlr_mutex);
-
- state = sdb_query(connection, octstr_get_cstr(sql), sdb_callback_add, row);
- octstr_destroy(sql);
- if (state == -1) {
- error(0, "SDB: error in finding DLR");
- mutex_unlock(dlr_mutex);
- return NULL;
- }
+ debug("dlr.dlr", 0, "DLR[%s]: Looking for DLR smsc=%s, ts=%s, dst=%s, type=%d",
+ dlr_type(), octstr_get_cstr(smsc), octstr_get_cstr(ts), octstr_get_cstr(dst), typ);
- debug("dlr.sdb", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, row[3]=%s row[4]=%s",
- octstr_get_cstr(list_get(row, 0)),
- octstr_get_cstr(list_get(row, 1)),
- octstr_get_cstr(list_get(row, 2)),
- octstr_get_cstr(list_get(row, 3))
- octstr_get_cstr(list_get(row, 4)));
-
- dlr_mask = atoi(octstr_get_cstr(list_get(row, 0)));
- dlr_service = octstr_duplicate(list_get(row, 1));
- dlr_url = octstr_duplicate(list_get(row, 2));
- source_addr = octstr_duplicate(list_get(row, 3));
- boxc_id = octstr_duplicate(list_get(row, 4));
- list_destroy(row, octstr_destroy_item);
-
- mutex_unlock(dlr_mutex);
-
- sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s'",
- octstr_get_cstr(table), octstr_get_cstr(field_status),
- typ, octstr_get_cstr(field_smsc), smsc,
- octstr_get_cstr(field_ts), ts);
-
- mutex_lock(dlr_mutex);
-
- state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
- octstr_destroy(sql);
- if (state == -1) {
- error(0, "SDB: error in updating DLR");
- mutex_unlock(dlr_mutex);
+ dlr = handles->dlr_get(smsc, ts, dst);
+ if (dlr == NULL) {
+ warning(0, "DLR[%s]: DLR for DST<%s> not found.",
+ dlr_type(), octstr_get_cstr(dst));
return NULL;
}
- mutex_unlock(dlr_mutex);
-
- if ((typ & dlr_mask)) {
+ if ((typ & dlr->mask) > 0) {
/* its an entry we are interested in */
msg = msg_create(sms);
- msg->sms.service = octstr_duplicate(dlr_service);
- msg->sms.dlr_mask = typ;
msg->sms.sms_type = report;
- msg->sms.smsc_id = octstr_create(smsc);
- msg->sms.sender = octstr_duplicate(source_addr);
- msg->sms.receiver = octstr_create(dst);
-
+ msg->sms.service = octstr_duplicate(dlr->service);
+ msg->sms.dlr_mask = typ;
+ msg->sms.smsc_id = octstr_duplicate(dlr->smsc);
+ msg->sms.receiver = octstr_duplicate(dlr->destination);
+ msg->sms.sender = octstr_duplicate(dlr->source);
/* if dlr_url was present, recode it here again */
- msg->sms.dlr_url = octstr_len(dlr_url) ?
- octstr_duplicate(dlr_url) : NULL;
-
+ msg->sms.dlr_url = octstr_len(dlr->url) ? octstr_duplicate(dlr->url) : NULL;
/*
* insert orginal message to the data segment
* later in the smsc module
*/
msg->sms.msgdata = NULL;
-
/*
* If a boxc_id is available, then instruct bearerbox to
* route this msg back to originating smsbox
*/
- msg->sms.boxc_id = octstr_len(boxc_id) ?
- octstr_duplicate(boxc_id) : NULL;
+ msg->sms.boxc_id = octstr_len(dlr->boxc_id) ? octstr_duplicate(dlr->boxc_id) : NULL;
time(&msg->sms.time);
- debug("dlr.dlr", 0, "created DLR message for URL <%s>",
- octstr_get_cstr(msg->sms.dlr_url));
+ debug("dlr.dlr", 0, "DLR[%s]: created DLR message for URL <%s>",
+ dlr_type(), octstr_get_cstr(msg->sms.dlr_url));
} else {
- debug("dlr.dlr", 0, "ignoring DLR message because of mask");
+ debug("dlr.dlr", 0, "DLR[%s]: Ignoring DLR message because of mask", dlr_type());
+ /* ok that was a status report but we where not interested in having it */
+ msg = NULL;
}
- if ((typ & DLR_BUFFERED) && ((dlr_mask & DLR_SUCCESS) || (dlr_mask & DLR_FAIL))) {
- debug("dlr.sdb", 0, "DLR not deleted because we wait on more reports");
+ /* check for end status and if so remove from storage */
+ if ((typ & DLR_BUFFERED) && ((dlr->mask & DLR_SUCCESS) || (dlr->mask & DLR_FAIL))) {
+ info(0, "DLR[%s]: Dlr not destroyed, still waiting for other delivery report", dlr_type());
+ /* update dlr entry status if function defined */
+ if (handles != NULL && handles->dlr_update != NULL)
+ handles->dlr_update(smsc, ts, dst, typ);
+ } else {
+ if (handles != NULL && handles->dlr_remove != NULL) {
+ /* it's not good for internal storage, but better for all others */
+ handles->dlr_remove(smsc, ts, dst);
} else {
- debug("dlr.sdb", 0, "removing DLR from database");
- sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1",
- octstr_get_cstr(table), octstr_get_cstr(field_smsc),
- smsc, octstr_get_cstr(field_ts), ts);
-
- mutex_lock(dlr_mutex);
-
- state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
- octstr_destroy(sql);
- if (state == -1) {
- error(0, "SDB: error in deleting DLR");
+ warning(0, "DLR[%s]: Storage don't have remove operation defined", dlr_type());
}
-
- mutex_unlock(dlr_mutex);
}
- octstr_destroy(dlr_service);
- octstr_destroy(dlr_url);
- octstr_destroy(source_addr);
- octstr_destroy(boxc_id);
-
-#endif
return msg;
}
-Msg *dlr_find(char *smsc, char *ts, char *dst, int typ)
-{
- Msg *msg = NULL;
-
- if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
- msg = dlr_find_mem(smsc, ts, dst, typ);
- } else
- if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
- msg = dlr_find_mysql(smsc, ts, dst, typ);
- } else
- if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
- msg = dlr_find_sdb(smsc, ts, dst, typ);
-
- /*
- * add aditional types here
- */
-
- } else {
- panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
- }
- return msg;
-}
-
-
-long dlr_messages(void)
-{
- if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
- return list_len(dlr_waiting_list);
- } else
- if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
-#ifdef DLR_MYSQL
- Octstr *sql;
- int state;
- long res;
- MYSQL_RES *result;
-
- sql = octstr_format("SELECT * FROM %s;", octstr_get_cstr(table));
- mutex_lock(dlr_mutex);
- state = mysql_query(connection, octstr_get_cstr(sql));
- octstr_destroy(sql);
- if (state != 0) {
- error(0, "MYSQL: %s", mysql_error(connection));
- mutex_unlock(dlr_mutex);
- return -1;
- }
- result = mysql_store_result(connection);
- res = mysql_num_rows(result);
- mysql_free_result(result);
- mutex_unlock(dlr_mutex);
- return res;
-#endif
- } else
- if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
-#ifdef DLR_SDB
- Octstr *sql;
- int state;
- long res;
-
- sql = octstr_format("SELECT * FROM %s", octstr_get_cstr(table));
- mutex_lock(dlr_mutex);
- state = sdb_query(connection, octstr_get_cstr(sql), sdb_callback_msgs, NULL);
- octstr_destroy(sql);
- if (state == -1) {
- error(0, "SDB: error in selecting ammount of waiting DLRs");
- mutex_unlock(dlr_mutex);
- return -1;
- }
- res = (long) state;
- mutex_unlock(dlr_mutex);
- return res;
-#endif
-
- /*
- * add aditional types here
- */
-
- } else {
- panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
- }
- return -1;
-}
-
void dlr_flush(void)
{
- long i;
- long len;
-
info(0, "Flushing all %ld queued DLR messages in %s storage", dlr_messages(),
- octstr_get_cstr(dlr_type));
+ dlr_type());
- if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
- len = list_len(dlr_waiting_list);
- for (i=0; i < len; i++)
- list_delete(dlr_waiting_list, i, 1);
-
- } else
- if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
-#ifdef DLR_MYSQL
- Octstr *sql;
- int state;
- MYSQL_RES *result;
-
- sql = octstr_format("DELETE FROM %s;", octstr_get_cstr(table));
- mutex_lock(dlr_mutex);
- state = mysql_query(connection, octstr_get_cstr(sql));
- octstr_destroy(sql);
- if (state != 0) {
- error(0, "MYSQL: %s", mysql_error(connection));
- }
- result = mysql_store_result(connection);
- mysql_free_result(result);
- mutex_unlock(dlr_mutex);
-#endif
- } else
- if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
-#ifdef DLR_SDB
- Octstr *sql;
- int state;
-
- sql = octstr_format("DELETE FROM %s", octstr_get_cstr(table));
- mutex_lock(dlr_mutex);
- state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
- octstr_destroy(sql);
- if (state == -1) {
- error(0, "SDB: error in flusing DLR table");
- }
- mutex_unlock(dlr_mutex);
-#endif
-
- /*
- * add aditional types here
- */
-
- } else {
- panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
- }
+ if (handles != NULL && handles->dlr_flush != NULL)
+ handles->dlr_flush();
}
Index: gw/dlr.h
===================================================================
RCS file: /home/cvs/gateway/gw/dlr.h,v
retrieving revision 1.12
diff -a -b -u -r1.12 dlr.h
--- gw/dlr.h 14 Nov 2002 02:29:25 -0000 1.12
+++ gw/dlr.h 26 May 2003 21:30:02 -0000
@@ -16,33 +16,6 @@
#define DLR_SMSC_SUCCESS 0x08
#define DLR_SMSC_FAIL 0x10
-#if defined(DLR_MYSQL) || defined(DLR_SDB)
-#define DLR_DB 1
-#endif
-
-Mutex *dlr_mutex;
-Octstr *dlr_type;
-
-/*
- * DB specific global things
- */
-#ifdef DLR_DB
-#ifdef DLR_MYSQL
-#include <mysql/mysql.h>
-MYSQL *connection;
-MYSQL mysql;
-#endif
-#ifdef DLR_SDB
-#include <sdb.h>
-char *connection;
-#endif
-Octstr *table;
-Octstr *field_smsc, *field_ts, *field_src, *field_dst, *field_serv;
-Octstr *field_url, *field_mask, *field_status, *field_boxc;
-#endif
-
-/* macros */
-#define O_DELETE(a) { if (a) octstr_destroy(a); a = NULL; }
/* DLR initialization routine (abstracted) */
void dlr_init(Cfg *cfg);
@@ -53,17 +26,13 @@
/*
* Add a new entry to the list
*/
-void dlr_add(char *smsc, char *ts, char *src, char *dst,
- char *keyword, char *id, int mask, char *boxc);
+void dlr_add(const Octstr *smsc, const Octstr *ts, const Msg *msg);
/*
* Find an entry in the list. If there is one a message is returned and
* the entry is removed from the list otherwhise the message returned is NULL
*/
-Msg* dlr_find(char *smsc, char *ts, char *dst, int type);
-
-void dlr_save(const char *filename);
-void dlr_load(const char *filename);
+Msg* dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int type);
/* return the number of DLR messages in the current waiting queue */
long dlr_messages(void);
@@ -74,6 +43,16 @@
*/
void dlr_flush(void);
+/*
+ * Return type of dlr storage
+ */
+const char* dlr_type();
+
+/*
+ * Yet not used functions.
+ */
+void dlr_save(const char *filename);
+void dlr_load(const char *filename);
#endif /* DLR_H */
Index: gw/dlr_mem.c
===================================================================
RCS file: gw/dlr_mem.c
diff -N gw/dlr_mem.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gw/dlr_mem.c 26 May 2003 21:30:03 -0000
@@ -0,0 +1,135 @@
+/*
+ * gw/dlr_mem.c
+ *
+ * Implementation of handling delivery reports (DLRs)
+ * in memory
+ *
+ * Andreas Fink <[email protected]>, 18.08.2001
+ * Stipe Tolj <[email protected]>, 22.03.2002
+ * Alexander Malysh <[email protected]> 2003
+ */
+
+#include "gwlib/gwlib.h"
+#include "dlr_p.h"
+
+/*
+ * This is the global list where all messages being sent out are being kept track
+ * of his list is looked up once a delivery report comes in
+ */
+static List *dlr_waiting_list;
+
+/*
+ * Destroy dlr_waiting_list.
+ */
+static void dlr_mem_shutdown()
+{
+ list_destroy(dlr_waiting_list, (list_item_destructor_t *)dlr_entry_destroy);
+}
+
+/*
+ * Get count of dlr messages waiting.
+ */
+static long dlr_mem_messages(void)
+{
+ return list_len(dlr_waiting_list);
+}
+
+static void dlr_mem_flush(void)
+{
+ long i;
+ long len;
+
+ len = list_len(dlr_waiting_list);
+ for (i=0; i < len; i++)
+ list_delete(dlr_waiting_list, i, 1);
+}
+
+/*
+ * add struct dlr_entry to list
+ */
+static void dlr_mem_add(struct dlr_entry *dlr)
+{
+ list_append(dlr_waiting_list,dlr);
+}
+
+/*
+ * Private compare function
+ * Return 0 if entry match and 1 if not.
+ */
+static int dlr_mem_entry_match(struct dlr_entry *dlr, const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ /* XXX: check destination addr too, because e.g. for UCP is not enough to check only
+ * smsc and timestamp (timestamp is even without milliseconds)
+ */
+ if(octstr_compare(dlr->smsc,smsc) == 0 && octstr_compare(dlr->timestamp,ts) == 0)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Find matching entry and return copy of it, otherwise NULL
+ */
+static struct dlr_entry *dlr_mem_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ long i;
+ long len;
+ struct dlr_entry *dlr = NULL, *ret = NULL;
+
+ list_lock(dlr_waiting_list);
+ len = list_len(dlr_waiting_list);
+ for (i=0; i < len; i++) {
+ dlr = list_get(dlr_waiting_list, i);
+
+ if (dlr_mem_entry_match(dlr, smsc, ts, dst) == 0) {
+ ret = dlr_entry_duplicate(dlr);
+ break;
+ }
+ }
+ list_unlock(dlr_waiting_list);
+
+ /* we couldnt find a matching entry */
+ return ret;
+}
+
+/*
+ * Remove matching entry
+ */
+static void dlr_mem_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ long i;
+ long len;
+ struct dlr_entry *dlr = NULL;
+
+ list_lock(dlr_waiting_list);
+ len = list_len(dlr_waiting_list);
+ for (i=0; i < len; i++) {
+ dlr = list_get(dlr_waiting_list, i);
+
+ if (dlr_mem_entry_match(dlr, smsc, ts, dst) == 0) {
+ list_delete(dlr_waiting_list, i, 1);
+ break;
+ }
+ }
+ list_unlock(dlr_waiting_list);
+}
+
+static struct dlr_storage handles = {
+ .type = "internal",
+ .dlr_add = dlr_mem_add,
+ .dlr_get = dlr_mem_get,
+ .dlr_remove = dlr_mem_remove,
+ .dlr_shutdown = dlr_mem_shutdown,
+ .dlr_messages = dlr_mem_messages,
+ .dlr_flush = dlr_mem_flush
+};
+
+/*
+ * Initialize dlr_waiting_list and return out storage handles.
+ */
+struct dlr_storage *dlr_init_mem(Cfg *cfg)
+{
+ dlr_waiting_list = list_create();
+
+ return &handles;
+}
Index: gw/dlr_mysql.c
===================================================================
RCS file: gw/dlr_mysql.c
diff -N gw/dlr_mysql.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gw/dlr_mysql.c 26 May 2003 21:30:04 -0000
@@ -0,0 +1,339 @@
+/*
+ * dlr_mysql.c
+ *
+ * Implementation of handling delivery reports (DLRs)
+ * for MySql database
+ *
+ * Andreas Fink <[email protected]>, 18.08.2001
+ * Stipe Tolj <[email protected]>, 22.03.2002
+ * Alexander Malysh <[email protected]> 2003
+*/
+
+#include "gwlib/gwlib.h"
+#include "dlr_p.h"
+
+
+#ifdef DLR_MYSQL
+#include <mysql/mysql.h>
+static MYSQL *connection;
+static MYSQL mysql;
+
+/*
+ * Database fields, which we are use.
+ */
+static struct dlr_db_fields *fields = NULL;
+
+/*
+ * Mutex to protec access to mysql.
+ */
+static Mutex *dlr_mutex = NULL;
+
+
+static void dlr_mysql_shutdown()
+{
+ mysql_close(connection);
+ dlr_db_fields_destroy(fields);
+ mutex_destroy(dlr_mutex);
+}
+
+static void dlr_mysql_add(struct dlr_entry *entry)
+{
+ Octstr *sql;
+ int state;
+
+ sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES "
+ "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d');",
+ octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
+ octstr_get_cstr(fields->field_ts),
+ octstr_get_cstr(fields->field_src), octstr_get_cstr(fields->field_dst),
+ octstr_get_cstr(fields->field_serv), octstr_get_cstr(fields->field_url),
+ octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_boxc),
+ octstr_get_cstr(fields->field_status),
+ octstr_get_cstr(entry->smsc), octstr_get_cstr(entry->timestamp), octstr_get_cstr(entry->source),
+ octstr_get_cstr(entry->destination), octstr_get_cstr(entry->service), octstr_get_cstr(entry->url),
+ entry->mask, octstr_get_cstr(entry->boxc_id), 0);
+
+#if defined(DLR_TRACE)
+ debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+
+ state = mysql_query(connection, octstr_get_cstr(sql));
+ if (state != 0)
+ error(0, "MYSQL: %s", mysql_error(connection));
+
+ mutex_unlock(dlr_mutex);
+ octstr_destroy(sql);
+ dlr_entry_destroy(entry);
+}
+
+static struct dlr_entry* dlr_mysql_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ struct dlr_entry *res = NULL;
+ Octstr *sql;
+ int state;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ sql = octstr_format("SELECT %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s';",
+ octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_serv),
+ octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->field_src),
+ octstr_get_cstr(fields->field_dst), octstr_get_cstr(fields->field_boxc),
+ octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
+ octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+
+#if defined(DLR_TRACE)
+ debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = mysql_query(connection, octstr_get_cstr(sql));
+ octstr_destroy(sql);
+ if (state != 0) {
+ error(0, "MYSQL: %s", mysql_error(connection));
+ mutex_unlock(dlr_mutex);
+ return NULL;
+ }
+ result = mysql_store_result(connection);
+ mutex_unlock(dlr_mutex);
+ if (mysql_num_rows(result) < 1) {
+ debug("dlr.mysql", 0, "no rows found");
+ mysql_free_result(result);
+ return NULL;
+ }
+ row = mysql_fetch_row(result);
+ if (!row) {
+ debug("dlr.mysql", 0, "rows found but could not load them");
+ mysql_free_result(result);
+ return NULL;
+ }
+
+ debug("dlr.mysql", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, row[3]=%s, row[4]=%s row[5]=%s",
+ row[0], row[1], row[2], (row[3] ? row[3] : "NULL"), (row[4] ? row[4] : "NULL"), (row[5] ? row[5] : "NULL"));
+
+ res = dlr_entry_create();
+ gw_assert(res != NULL);
+ res->mask = atoi(row[0]);
+ res->service = octstr_create(row[1]);
+ res->url = octstr_create(row[2]);
+ res->source = row[3] ? octstr_create(row[3]) : octstr_create("");
+ res->destination = row[4] ? octstr_create(row[4]) : octstr_create("");
+ res->boxc_id = row[5] ? octstr_create(row[5]) : octstr_create("");
+
+ mysql_free_result(result);
+
+ return res;
+}
+
+static void dlr_mysql_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ Octstr *sql;
+ int state;
+
+ debug("dlr.mysql", 0, "removing DLR from database");
+ sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1;",
+ octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
+ octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+
+#if defined(DLR_TRACE)
+ debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = mysql_query(connection, octstr_get_cstr(sql));
+ octstr_destroy(sql);
+ if (state != 0) {
+ error(0, "MYSQL: %s", mysql_error(connection));
+ }
+ mutex_unlock(dlr_mutex);
+}
+
+static void dlr_mysql_update(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
+{
+ Octstr *sql;
+ int state;
+
+ debug("dlr.mysql", 0, "updating DLR status in database");
+ sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s' LIMIT 1;",
+ octstr_get_cstr(fields->table),
+ octstr_get_cstr(fields->field_status), status,
+ octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+ octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+
+#if defined(DLR_TRACE)
+ debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = mysql_query(connection, octstr_get_cstr(sql));
+ octstr_destroy(sql);
+ if (state != 0) {
+ error(0, "MYSQL: %s", mysql_error(connection));
+ }
+ mutex_unlock(dlr_mutex);
+}
+
+
+static long dlr_mysql_messages(void)
+{
+ Octstr *sql;
+ int state;
+ long res;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ sql = octstr_format("SELECT count(*) FROM %s;", octstr_get_cstr(fields->table));
+#if defined(DLR_TRACE)
+ debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = mysql_query(connection, octstr_get_cstr(sql));
+ octstr_destroy(sql);
+ if (state != 0) {
+ error(0, "MYSQL: %s", mysql_error(connection));
+ mutex_unlock(dlr_mutex);
+ return -1;
+ }
+ result = mysql_store_result(connection);
+ mutex_unlock(dlr_mutex);
+ if (mysql_num_rows(result) < 1) {
+ debug("dlr.mysql", 0, "Could not get count of DLR table");
+ mysql_free_result(result);
+ return 0;
+ }
+ row = mysql_fetch_row(result);
+ if (row == NULL) {
+ debug("dlr.mysql", 0, "rows found but could not load them");
+ mysql_free_result(result);
+ return 0;
+ }
+ res = atol(row[0]);
+ mysql_free_result(result);
+ return res;
+}
+
+static void dlr_mysql_flush(void)
+{
+ Octstr *sql;
+ int state;
+ MYSQL_RES *result;
+
+ sql = octstr_format("DELETE FROM %s;", octstr_get_cstr(fields->table));
+ mutex_lock(dlr_mutex);
+ state = mysql_query(connection, octstr_get_cstr(sql));
+ octstr_destroy(sql);
+ if (state != 0) {
+ error(0, "MYSQL: %s", mysql_error(connection));
+ }
+ result = mysql_store_result(connection);
+ mutex_unlock(dlr_mutex);
+ mysql_free_result(result);
+}
+
+static struct dlr_storage handles = {
+ .type = "mysql",
+ .dlr_add = dlr_mysql_add,
+ .dlr_get = dlr_mysql_get,
+ .dlr_update = dlr_mysql_update,
+ .dlr_remove = dlr_mysql_remove,
+ .dlr_shutdown = dlr_mysql_shutdown,
+ .dlr_messages = dlr_mysql_messages,
+ .dlr_flush = dlr_mysql_flush
+};
+
+struct dlr_storage *dlr_init_mysql(Cfg* cfg)
+{
+ CfgGroup *grp;
+ List *grplist;
+ Octstr *mysql_host, *mysql_user, *mysql_pass, *mysql_db, *mysql_id;
+ Octstr *p = NULL;
+
+ /*
+ * check for all mandatory directives that specify the field names
+ * of the used MySQL table
+ */
+ if (!(grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))))
+ panic(0, "DLR: MySQL: group 'dlr-db' is not specified!");
+
+ if (!(mysql_id = cfg_get(grp, octstr_imm("id"))))
+ panic(0, "DLR: MySQL: directive 'id' is not specified!");
+
+ fields = dlr_db_fields_create(grp);
+ gw_assert(fields != NULL);
+
+ /*
+ * now grap the required information from the 'mysql-connection' group
+ * with the mysql-id we just obtained
+ *
+ * we have to loop through all available MySQL connection definitions
+ * and search for the one we are looking for
+ */
+
+ grplist = cfg_get_multi_group(cfg, octstr_imm("mysql-connection"));
+ while (grplist && (grp = list_extract_first(grplist)) != NULL) {
+ p = cfg_get(grp, octstr_imm("id"));
+ if (p != NULL && octstr_compare(p, mysql_id) == 0) {
+ goto found;
+ }
+ octstr_destroy(p);
+ }
+ panic(0, "DLR: MySQL: connection settings for id '%s' are not specified!",
+ octstr_get_cstr(mysql_id));
+
+found:
+ octstr_destroy(p);
+ list_destroy(grplist, NULL);
+
+ if (!(mysql_host = cfg_get(grp, octstr_imm("host"))))
+ panic(0, "DLR: MySQL: directive 'host' is not specified!");
+ if (!(mysql_user = cfg_get(grp, octstr_imm("mysql-username"))))
+ panic(0, "DLR: MySQL: directive 'mysql-username' is not specified!");
+ if (!(mysql_pass = cfg_get(grp, octstr_imm("mysql-password"))))
+ panic(0, "DLR: MySQL: directive 'mysql-password' is not specified!");
+ if (!(mysql_db = cfg_get(grp, octstr_imm("database"))))
+ panic(0, "DLR: MySQL: directive 'database' is not specified!");
+
+ /*
+ * ok, ready to connect to MySQL
+ */
+ mysql_init(&mysql);
+ connection = mysql_real_connect(&mysql,
+ octstr_get_cstr(mysql_host), octstr_get_cstr(mysql_user),
+ octstr_get_cstr(mysql_pass), octstr_get_cstr(mysql_db),
+ 0, NULL, 0);
+
+ /*
+ * XXX should a failing connect throw panic?!
+ */
+ if (connection == NULL) {
+ error(0,"DLR: MySQL: can not connect to database!");
+ panic(0,"MYSQL: %s", mysql_error(&mysql));
+ } else {
+ info(0,"Connected to mysql server at %s.", octstr_get_cstr(mysql_host));
+ info(0,"MYSQL: server version %s, client version %s.",
+ mysql_get_server_info(&mysql), mysql_get_client_info());
+ }
+
+ dlr_mutex = mutex_create();
+
+ octstr_destroy(mysql_db);
+ octstr_destroy(mysql_host);
+ octstr_destroy(mysql_user);
+ octstr_destroy(mysql_pass);
+ octstr_destroy(mysql_id);
+
+ return &handles;
+}
+#else
+/*
+ * Return NULL , so we point dlr-core that we were
+ * not compiled in.
+ */
+struct dlr_storage *dlr_init_mysql(Cfg* cfg)
+{
+ return NULL;
+}
+#endif /* DLR_MYSQL */
+
Index: gw/dlr_p.h
===================================================================
RCS file: gw/dlr_p.h
diff -N gw/dlr_p.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gw/dlr_p.h 26 May 2003 21:30:04 -0000
@@ -0,0 +1,114 @@
+/*
+ * gw/dlr_p.h
+ *
+ * Implementation of handling delivery reports (DLRs)
+ * These are private header.
+ *
+ * Andreas Fink <[email protected]>, 18.08.2001
+ * Stipe Tolj <[email protected]>, 22.03.2002
+ * Alexander Malysh <[email protected]>
+*/
+
+#ifndef DLR_P_H
+#define DLR_P_H 1
+
+#define DLR_TRACE 1
+
+/*
+ * The structure of a delivery report entry.
+ */
+struct dlr_entry {
+ Octstr *smsc;
+ Octstr *timestamp;
+ Octstr *source;
+ Octstr *destination;
+ Octstr *service;
+ Octstr *url;
+ Octstr *boxc_id;
+ int mask;
+};
+
+/*
+ * Create struct dlr_entry and initialize it to zero
+ */
+struct dlr_entry *dlr_entry_create();
+
+/*
+ * Destroy struct dlr_entry
+ */
+void dlr_entry_destroy(struct dlr_entry *dlr);
+
+/*
+ * Duplicate dlr entry
+ */
+struct dlr_entry *dlr_entry_duplicate(const struct dlr_entry *dlr);
+
+
+/* Callback functions to hanlde specifical dlr storage type */
+struct dlr_storage {
+ /*
+ * Type of storage. Used for status reguest.
+ */
+ const char* type;
+ /*
+ * Add dlr entry into storage.
+ * NOTE: this function is responsible to destroy struct dlr_entry
+ */
+ void (*dlr_add) (struct dlr_entry *entry);
+ /*
+ * Find and return struct dlr_entry. If entry not found return NULL.
+ * NOTE: Caller will detroy struct dlr_entry
+ */
+ struct dlr_entry* (*dlr_get) (const Octstr *smsc, const Octstr *ts, const Octstr *dst);
+ /*
+ * Remove matching dlr entry from storage
+ */
+ void (*dlr_remove) (const Octstr *smsc, const Octstr *ts, const Octstr *dst);
+ /*
+ * Update dlr entry status field if any.
+ */
+ void (*dlr_update) (const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status);
+ /*
+ * Return count dlr entries in storage.
+ */
+ long (*dlr_messages) (void);
+ /*
+ * Flush storage
+ */
+ void (*dlr_flush) (void);
+ /*
+ * Shutdown storage
+ */
+ void (*dlr_shutdown) (void);
+};
+
+
+/*
+ * Will be used by DB-Based storage types.
+ * We have helper init function also.
+ */
+struct dlr_db_fields {
+ Octstr *table;
+ Octstr *field_smsc;
+ Octstr *field_ts;
+ Octstr *field_src;
+ Octstr *field_dst;
+ Octstr *field_serv;
+ Octstr *field_url;
+ Octstr *field_mask;
+ Octstr *field_status;
+ Octstr *field_boxc;
+};
+
+struct dlr_db_fields *dlr_db_fields_create(CfgGroup *grp);
+void dlr_db_fields_destroy(struct dlr_db_fields *fields);
+
+/*
+ * Storages we have already. This will gone in future
+ * if we have module API implemented.
+ */
+struct dlr_storage *dlr_init_mem(Cfg *cfg);
+struct dlr_storage *dlr_init_mysql(Cfg *cfg);
+struct dlr_storage *dlr_init_sdb(Cfg *cfg);
+
+#endif /* DLR_P_H */
Index: gw/dlr_sdb.c
===================================================================
RCS file: gw/dlr_sdb.c
diff -N gw/dlr_sdb.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gw/dlr_sdb.c 26 May 2003 21:30:05 -0000
@@ -0,0 +1,311 @@
+/*
+ * dlr_sdb.c
+ *
+ * Implementation of handling delivery reports (DLRs)
+ * for LibSDB.
+ *
+ * Andreas Fink <[email protected]>, 18.08.2001
+ * Stipe Tolj <[email protected]>, 22.03.2002
+ * Alexander Malysh <[email protected]> 2003
+*/
+
+#include "gwlib/gwlib.h"
+#include "dlr_p.h"
+
+#ifdef DLR_SDB
+#include <sdb.h>
+static char *connection;
+
+/*
+ * Database fields, which we are use.
+ */
+static struct dlr_db_fields *fields = NULL;
+
+/*
+ * Mutex to protec access to database.
+ */
+static Mutex *dlr_mutex = NULL;
+
+
+static void dlr_sdb_shutdown()
+{
+ sdb_close(connection);
+ dlr_db_fields_destroy(fields);
+ mutex_destroy(dlr_mutex);
+}
+
+static void dlr_add_sdb(struct dlr_entry *dlr)
+{
+ Octstr *sql;
+ int state;
+
+ sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES "
+ "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d')",
+ octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
+ octstr_get_cstr(fields->field_ts),
+ octstr_get_cstr(fields->field_src), octstr_get_cstr(fields->field_dst),
+ octstr_get_cstr(fields->field_serv), octstr_get_cstr(fields->field_url),
+ octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_boxc),
+ octstr_get_cstr(fields->field_status),
+ octstr_get_cstr(dlr->smsc), octstr_get_cstr(dlr->timestamp),
+ octstr_get_cstr(dlr->source), octstr_get_cstr(dlr->destination),
+ octstr_get_cstr(dlr->service), octstr_get_cstr(dlr->url), mask,
+ octstr_get_cstr(dlr->boxc_id), 0);
+
+ mutex_lock(dlr_mutex);
+ state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
+ mutex_unlock(dlr_mutex);
+ if (state == -1)
+ error(0, "SDB: error in inserting DLR");
+
+ octstr_destroy(sql);
+ dlr_entry_destroy(dlr);
+}
+
+static int sdb_callback_add(int n, char **p, void *row)
+{
+ if (!n) {
+ debug("dlr.sdb", 0, "no rows found");
+ return 0;
+ }
+
+ /* strip string into words */
+ row = octstr_split(octstr_imm(p[0]), octstr_imm(" "));
+ if (list_len(row) != 6) {
+ debug("dlr.sdb", 0, "Row has wrong length %ld", list_len(row));
+ return 0;
+ }
+
+ return 0;
+}
+
+static int sdb_callback_msgs(int n, char **p, void *row)
+{}
+
+static struct dlr_entry* dlr_sdb_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ Octstr *sql;
+ int state;
+ List *row;
+ struct dlr_entry *res = NULL;
+
+ sql = octstr_format("SELECT %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s'",
+ octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_serv),
+ octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->field_src),
+ octstr_get_cstr(fields->field_dst), octstr_get_cstr(fields->field_boxc),
+ octstr_get_cstr(fields->table),
+ octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+ octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+
+#if defined(DLR_TRACE)
+ debug("dlr.sdb", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = sdb_query(connection, octstr_get_cstr(sql), sdb_callback_add, row);
+ mutex_unlock(dlr_mutex);
+ octstr_destroy(sql);
+ if (state == -1) {
+ error(0, "SDB: error in finding DLR");
+ return NULL;
+ }
+
+ debug("dlr.sdb", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, row[3]=%s row[4]=%s row[5]=%s",
+ octstr_get_cstr(list_get(row, 0)),
+ octstr_get_cstr(list_get(row, 1)),
+ octstr_get_cstr(list_get(row, 2)),
+ octstr_get_cstr(list_get(row, 3)),
+ octstr_get_cstr(list_get(row, 4)),
+ octstr_get_cstr(list_get(row, 5)));
+
+ res = dlr_entry_create();
+ gw_assert(res);
+ res->dlr_mask = atoi(octstr_get_cstr(list_get(row, 0)));
+ res->dlr_service = octstr_duplicate(list_get(row, 1));
+ res->dlr_url = octstr_duplicate(list_get(row, 2));
+ res->source = octstr_duplicate(list_get(row, 3));
+ res->destination = octstr_duplicate(list_get(row, 4));
+ boxc_id = octstr_duplicate(list_get(row, 5));
+
+ list_destroy(row, octstr_destroy_item);
+
+ return res;
+}
+
+static void dlr_sdb_update(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ Octstr *sql;
+ int state;
+
+ debug("dlr.sdb", 0, "updating DLR status in database");
+ sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s'",
+ octstr_get_cstr(fields->table),
+ octstr_get_cstr(fields->field_status), typ,
+ octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+ octstr_get_cstr(field_ts), octstr_get_cstr(ts));
+
+#if defined(DLR_TRACE)
+ debug("dlr.sdb", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
+ mutex_unlock(dlr_mutex);
+ octstr_destroy(sql);
+ if (state == -1) {
+ error(0, "SDB: error in updating DLR");
+ }
+}
+
+static void dlr_sdb_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
+{
+ Octstr *sql;
+ int state;
+
+ debug("dlr.sdb", 0, "removing DLR from database");
+ sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1",
+ octstr_get_cstr(fields->table),
+ octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
+ octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
+
+#if defined(DLR_TRACE)
+ debug("dlr.sdb", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
+ mutex_unlock(dlr_mutex);
+ octstr_destroy(sql);
+ if (state == -1)
+ error(0, "SDB: error in deleting DLR");
+}
+
+static long dlr_sdb_messages(void)
+{
+ Octstr *sql;
+ int state;
+ long res;
+
+ /*
+ * XXXX select * ... is not efficient.
+ * Please use here SELECT count(*) ... , see mysql for example.
+ */
+ sql = octstr_format("SELECT * FROM %s", octstr_get_cstr(table));
+
+#if defined(DLR_TRACE)
+ debug("dlr.sdb", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = sdb_query(connection, octstr_get_cstr(sql), sdb_callback_msgs, NULL);
+ octstr_destroy(sql);
+ if (state == -1) {
+ error(0, "SDB: error in selecting ammount of waiting DLRs");
+ mutex_unlock(dlr_mutex);
+ return -1;
+ }
+ res = (long) state;
+ mutex_unlock(dlr_mutex);
+ return res;
+}
+
+static void dlr_sdb_flush(void)
+{
+ Octstr *sql;
+ int state;
+
+ sql = octstr_format("DELETE FROM %s", octstr_get_cstr(table));
+
+#if defined(DLR_TRACE)
+ debug("dlr.sdb", 0, "sql: %s", octstr_get_cstr(sql));
+#endif
+
+ mutex_lock(dlr_mutex);
+ state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
+ octstr_destroy(sql);
+ if (state == -1) {
+ error(0, "SDB: error in flusing DLR table");
+ }
+ mutex_unlock(dlr_mutex);
+}
+
+
+static struct dlr_storage handles = {
+ .type = "sdb",
+ .dlr_add = dlr_sdb_add,
+ .dlr_get = dlr_sdb_get,
+ .dlr_update = dlr_sdb_update,
+ .dlr_remove = dlr_sdb_remove,
+ .dlr_shutdown = dlr_sdb_shutdown,
+ .dlr_messages = dlr_sdb_messages,
+ .dlr_flush = dlr_sdb_flush
+};
+
+static struct dlr_storage *dlr_init_sdb(Cfg* cfg)
+{
+ CfgGroup *grp;
+ List *grplist;
+ Octstr *sdb_url, *sdb_id;
+ Octstr *p = NULL;
+
+ /*
+ * check for all mandatory directives that specify the field names
+ * of the used table
+ */
+ if (!(grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))))
+ panic(0, "DLR: SDB: group 'dlr-db' is not specified!");
+
+ if (!(sdb_id = cfg_get(grp, octstr_imm("id"))))
+ panic(0, "DLR: SDB: directive 'id' is not specified!");
+
+ fields = dlr_db_fields_create(grp);
+ gw_assert(fields != NULL);
+ dlr_mutex = mutex_create();
+
+ /*
+ * now grap the required information from the 'mysql-connection' group
+ * with the sdb-id we just obtained
+ *
+ * we have to loop through all available SDB connection definitions
+ * and search for the one we are looking for
+ */
+
+ grplist = cfg_get_multi_group(cfg, octstr_imm("sdb-connection"));
+ while (grplist && (grp = list_extract_first(grplist)) != NULL) {
+ p = cfg_get(grp, octstr_imm("id"));
+ if (p != NULL && octstr_compare(p, sdb_id) == 0) {
+ goto found;
+ }
+ }
+ panic(0, "DLR: SDB: connection settings for id '%s' are not specified!",
+ octstr_get_cstr(sdb_id));
+
+found:
+ octstr_destroy(p);
+ list_destroy(grplist, NULL);
+
+ if (!(sdb_url = cfg_get(grp, octstr_imm("url"))))
+ panic(0, "DLR: SDB: directive 'url' is not specified!");
+
+ /*
+ * ok, ready to connect
+ */
+ info(0,"Connecting to sdb resource <%s>.", octstr_get_cstr(sdb_url));
+ connection = sdb_open(octstr_get_cstr(sdb_url));
+ if (connection == NULL)
+ panic(0, "Could not connect to database");
+
+ octstr_destroy(sdb_url);
+
+ return &handles;
+}
+#else
+/*
+ * Return NULL , so we point dlr-core that we were
+ * not compiled in.
+ */
+struct dlr_storage *dlr_init_sdb(Cfg* cfg)
+{
+ return NULL;
+}
+#endif /* DLR_SDB */
Index: gw/smsc/smsc_at2.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at2.c,v
retrieving revision 1.16
diff -a -b -u -r1.16 smsc_at2.c
--- gw/smsc/smsc_at2.c 27 Mar 2003 08:56:42 -0000 1.16
+++ gw/smsc/smsc_at2.c 26 May 2003 21:30:12 -0000
@@ -1496,8 +1496,7 @@
* any "reserved" values to be "failure", but most reserved values fall into one of the three categories. it will catch
* "reserved" values where the first 3 MSBits are not set as "Success" which may not be correct. */
- if ((dlrmsg = dlr_find(octstr_get_cstr(privdata->conn->id),
- octstr_get_cstr(msg_id), octstr_get_cstr(receiver), type)) == NULL) {
+ if ((dlrmsg = dlr_find(privdata->conn->id, msg_id, receiver, type)) == NULL) {
debug("bb.smsc.at2",1,"AT2[%s]: Received delivery notification but can't find that ID in the DLR storage",
octstr_get_cstr(privdata->name));
goto error;
@@ -1683,14 +1682,7 @@
else {
Octstr *dlrmsgid = octstr_format("%d", msg_id);
- dlr_add(octstr_get_cstr(privdata->conn->id),
- octstr_get_cstr(dlrmsgid),
- octstr_get_cstr(msg->sms.sender),
- octstr_get_cstr(msg->sms.receiver),
- octstr_get_cstr(msg->sms.service),
- octstr_get_cstr(msg->sms.dlr_url),
- msg->sms.dlr_mask,
- octstr_get_cstr(msg->sms.boxc_id));
+ dlr_add(privdata->conn->id, dlrmsgid, msg);
O_DESTROY(dlrmsgid);
}
Index: gw/smsc/smsc_cgw.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_cgw.c,v
retrieving revision 1.5
diff -a -b -u -r1.5 smsc_cgw.c
--- gw/smsc/smsc_cgw.c 4 Mar 2003 15:16:09 -0000 1.5
+++ gw/smsc/smsc_cgw.c 26 May 2003 21:30:16 -0000
@@ -1078,28 +1078,27 @@
switch (stat) {
case 0: /* delivered */
- dlrmsg = dlr_find(octstr_get_cstr(conn->id),
- octstr_get_cstr(ts), /* timestamp */
- octstr_get_cstr(msid), /* destination */
+ dlrmsg = dlr_find(conn->id,
+ ts, /* timestamp */
+ msid, /* destination */
DLR_SUCCESS);
break;
case 1: /* buffered */
- dlrmsg = dlr_find(octstr_get_cstr(conn->id),
- octstr_get_cstr(ts), /* timestamp */
- octstr_get_cstr(msid), /* destination */
+ dlrmsg = dlr_find(conn->id,
+ ts, /* timestamp */
+ msid, /* destination */
DLR_BUFFERED);
break;
case 2: /* not delivered */
- dlrmsg = dlr_find(octstr_get_cstr(conn->id),
- octstr_get_cstr(ts), /* timestamp */
- octstr_get_cstr(msid), /* destination */
+ dlrmsg = dlr_find(conn->id,
+ ts, /* timestamp */
+ msid, /* destination */
DLR_FAIL);
break;
}
octstr_destroy(ts);
if (dlrmsg != NULL) {
-
dlrmsg->sms.msgdata = octstr_duplicate(txt);
bb_smscconn_receive(conn, dlrmsg);
}
@@ -1126,14 +1125,7 @@
octstr_append_char(ts, '-');
octstr_append_decimal(ts, trn);
- dlr_add(octstr_get_cstr(conn->id),
- octstr_get_cstr(ts),
- octstr_get_cstr(msg->sms.sender),
- octstr_get_cstr(msg->sms.receiver),
- octstr_get_cstr(msg->sms.service),
- octstr_get_cstr(msg->sms.dlr_url),
- msg->sms.dlr_mask,
- octstr_get_cstr(msg->sms.boxc_id));
+ dlr_add(conn->id, ts, msg);
octstr_destroy(ts);
privdata->dlr[trn] = 1;
Index: gw/smsc/smsc_cimd2.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_cimd2.c,v
retrieving revision 1.10
diff -a -b -u -r1.10 smsc_cimd2.c
--- gw/smsc/smsc_cimd2.c 3 Apr 2003 12:18:18 -0000 1.10
+++ gw/smsc/smsc_cimd2.c 26 May 2003 21:30:34 -0000
@@ -1883,15 +1883,7 @@
ret = cimd2_request(packet, conn, &ts);
if((ret == 0) && (ts) && (msg->sms.dlr_mask & 0x03) && !pdata->no_dlr) {
-
- dlr_add(octstr_get_cstr(conn->name),
- octstr_get_cstr(ts),
- octstr_get_cstr(msg->sms.sender),
- octstr_get_cstr(msg->sms.receiver),
- octstr_get_cstr(msg->sms.service),
- octstr_get_cstr(msg->sms.dlr_url),
- msg->sms.dlr_mask,
- octstr_get_cstr(msg->sms.boxc_id));
+ dlr_add(conn->name, ts, msg);
}
octstr_destroy(ts);
packet_destroy(packet);
@@ -2024,10 +2016,7 @@
code = 0;
}
if(code)
- msg = dlr_find(octstr_get_cstr(conn->name),
- octstr_get_cstr(timestamp),
- octstr_get_cstr(destination),
- code);
+ msg = dlr_find(conn->name, timestamp, destination, code);
else
msg = NULL;
octstr_destroy(statuscode);
Index: gw/smsc/smsc_emi2.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_emi2.c,v
retrieving revision 1.16
diff -a -b -u -r1.16 smsc_emi2.c
--- gw/smsc/smsc_emi2.c 29 Apr 2003 12:18:26 -0000 1.16
+++ gw/smsc/smsc_emi2.c 26 May 2003 21:30:48 -0000
@@ -716,21 +716,21 @@
switch(st_code)
{
case 0: /* delivered */
- msg = dlr_find(octstr_get_cstr((conn->id ? conn->id : privdata->name)),
- octstr_get_cstr(emimsg->fields[E50_SCTS]), /* timestamp */
- octstr_get_cstr(emimsg->fields[E50_OADC]), /* destination */
+ msg = dlr_find((conn->id ? conn->id : privdata->name),
+ emimsg->fields[E50_SCTS], /* timestamp */
+ emimsg->fields[E50_OADC], /* destination */
DLR_SUCCESS);
break;
case 1: /* buffered */
- msg = dlr_find(octstr_get_cstr((conn->id ? conn->id : privdata->name)),
- octstr_get_cstr(emimsg->fields[E50_SCTS]), /* timestamp */
- octstr_get_cstr(emimsg->fields[E50_OADC]), /* destination */
+ msg = dlr_find((conn->id ? conn->id : privdata->name),
+ emimsg->fields[E50_SCTS], /* timestamp */
+ emimsg->fields[E50_OADC], /* destination */
DLR_BUFFERED);
break;
case 2: /* not delivered */
- msg = dlr_find(octstr_get_cstr((conn->id ? conn->id : privdata->name)),
- octstr_get_cstr(emimsg->fields[E50_SCTS]), /* timestamp */
- octstr_get_cstr(emimsg->fields[E50_OADC]), /* destination */
+ msg = dlr_find((conn->id ? conn->id : privdata->name),
+ emimsg->fields[E50_SCTS], /* timestamp */
+ emimsg->fields[E50_OADC], /* destination */
DLR_FAIL);
break;
}
@@ -892,14 +892,7 @@
octstr_append_char(ts, '-');
octstr_append_decimal(ts, nexttrn);
- dlr_add(octstr_get_cstr((conn->id ? conn->id : PRIVDATA(conn)->name)),
- octstr_get_cstr(ts),
- octstr_get_cstr(msg->sms.sender),
- octstr_get_cstr(emimsg->fields[E50_ADC]),
- octstr_get_cstr(msg->sms.service),
- octstr_get_cstr(msg->sms.dlr_url),
- msg->sms.dlr_mask,
- octstr_get_cstr(msg->sms.boxc_id));
+ dlr_add((conn->id ? conn->id : PRIVDATA(conn)->name), ts, msg);
octstr_destroy(ts);
PRIVDATA(conn)->slots[nexttrn].dlr = 1;
@@ -978,9 +971,9 @@
octstr_append_char(ts, '-');
octstr_append_decimal(ts, emimsg->trn);
- dlrmsg = dlr_find(octstr_get_cstr((conn->id ? conn->id : privdata->name)),
- octstr_get_cstr(ts), /* timestamp */
- octstr_get_cstr(origmsg->sms.receiver), /* destination */
+ dlrmsg = dlr_find((conn->id ? conn->id : privdata->name),
+ ts, /* timestamp */
+ origmsg->sms.receiver, /* destination */
(octstr_get_char(emimsg->fields[0], 0) == 'A' ?
DLR_SMSC_SUCCESS : DLR_SMSC_FAIL));
@@ -1027,14 +1020,7 @@
info(0,"EMI2[%s]: uhhh m is NULL, very bad",
octstr_get_cstr(privdata->name));
} else if ((m->sms.dlr_mask & (DLR_SUCCESS|DLR_FAIL|DLR_BUFFERED))) {
- dlr_add(octstr_get_cstr((conn->id ? conn->id : privdata->name)),
- octstr_get_cstr(ts),
- octstr_get_cstr(m->sms.sender),
- octstr_get_cstr(adc),
- m->sms.service ? octstr_get_cstr(m->sms.service) : NULL,
- m->sms.dlr_url ? octstr_get_cstr(m->sms.dlr_url) : NULL,
- m->sms.dlr_mask,
- octstr_get_cstr(m->sms.boxc_id));
+ dlr_add((conn->id ? conn->id : privdata->name), ts, m);
}
octstr_destroy(ts);
octstr_destroy(adc);
Index: gw/smsc/smsc_oisd.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_oisd.c,v
retrieving revision 1.1
diff -a -b -u -r1.1 smsc_oisd.c
--- gw/smsc/smsc_oisd.c 28 Jan 2003 00:10:04 -0000 1.1
+++ gw/smsc/smsc_oisd.c 26 May 2003 21:30:51 -0000
@@ -1042,14 +1042,7 @@
if ((ret == 0) && (ts) && (msg->sms.dlr_mask & 0x03)) {
debug("bb.sms.oisd", 0, "oisd_submit_msg dlr_add url=%s ",
octstr_get_cstr(msg->sms.dlr_url));
- dlr_add(smsc->name,
- octstr_get_cstr(ts),
- octstr_get_cstr(msg->sms.sender),
- octstr_get_cstr(msg->sms.receiver),
- octstr_get_cstr(msg->sms.service),
- octstr_get_cstr(msg->sms.dlr_url),
- msg->sms.dlr_mask,
- octstr_get_cstr(msg->sms.boxc_id));
+ dlr_add(octstr_imm(smsc->name), ts, msg);
octstr_destroy(ts);
ts = NULL;
}
@@ -1202,9 +1195,9 @@
code = 0;
}
if (code) {
- msg = dlr_find(smsc->name,
- octstr_get_cstr(timestamp),
- octstr_get_cstr(destination),
+ msg = dlr_find(octstr_imm(smsc->name),
+ timestamp,
+ destination,
code);
debug("bb.sms.oisd", 0, "oisd_accept_dlr_message val=%d ",
st_code);
Index: gw/smsc/smsc_smpp.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_smpp.c,v
retrieving revision 1.36
diff -a -b -u -r1.36 smsc_smpp.c
--- gw/smsc/smsc_smpp.c 25 Apr 2003 11:58:57 -0000 1.36
+++ gw/smsc/smsc_smpp.c 26 May 2003 21:30:56 -0000
@@ -789,9 +789,9 @@
}
}
- dlrmsg = dlr_find(octstr_get_cstr(smpp->conn->id),
- octstr_get_cstr(tmp), /* smsc message id */
- octstr_get_cstr(pdu->u.deliver_sm.destination_addr), /* destination */
+ dlrmsg = dlr_find(smpp->conn->id,
+ tmp, /* smsc message id */
+ pdu->u.deliver_sm.destination_addr, /* destination */
dlrstat);
octstr_destroy(tmp);
}
@@ -921,14 +921,7 @@
/* SMSC ACK.. now we have the message id. */
if (msg->sms.dlr_mask & (DLR_SMSC_SUCCESS|DLR_SUCCESS|DLR_FAIL|DLR_BUFFERED))
- dlr_add(octstr_get_cstr(smpp->conn->id),
- octstr_get_cstr(tmp),
- octstr_get_cstr(msg->sms.sender),
- octstr_get_cstr(msg->sms.receiver),
- octstr_get_cstr(msg->sms.service),
- octstr_get_cstr(msg->sms.dlr_url),
- msg->sms.dlr_mask,
- octstr_get_cstr(msg->sms.boxc_id));
+ dlr_add(smpp->conn->id, tmp, msg);
/* gen DLR_SMSC_SUCCESS */
if (msg->sms.dlr_mask & DLR_SMSC_SUCCESS) {
@@ -936,9 +929,9 @@
reply = octstr_format("0x%08lx", pdu->u.submit_sm_resp.command_status);
- dlrmsg = dlr_find(octstr_get_cstr(smpp->conn->id),
- octstr_get_cstr(tmp), /* smsc message id */
- octstr_get_cstr(msg->sms.receiver), /* destination */
+ dlrmsg = dlr_find(smpp->conn->id,
+ tmp, /* smsc message id */
+ msg->sms.receiver, /* destination */
(DLR_SMSC_SUCCESS|((msg->sms.dlr_mask & (DLR_SUCCESS|DLR_FAIL)) ? DLR_BUFFERED : 0)));
if (dlrmsg != NULL) {