Hi, i found a small memleak after it ... Attached you can find corrected version of this patch. I can say, mysql and internal where tested and works on our production systems without any problems. libsdb is not tested yet, but should work, because i have not changed any calls to the library itself. So please people, who use libsdb, test it!
What happens is pretty simple ;) 1. if dlr_init calls then here storage will be initilialized return pointer to operations struct. pls consult dlr_p.h for possible operations on the storage. 2. If dlr_find calls then core dlr do following: call storage get function create new dlr message check if this end status of message (e.g. delivered or undelivered) and then delete the message by calling of remove storage funct. if end state not reached then call storage update status entry funct. (its optional, that means, if storage define this funct. it will be called otherwise not) 3. dlr_status just call storage status funct. and so on ... So if any questions about this code should be here, then ask! Am Donnerstag, 19. Juni 2003 20:02 schrieb Stipe Tolj: > Nisan Bloch wrote: > > Hi > > > > what happened to this? > > I'm just "reading" it. Unfortunatly it's huge and even in unified diff > almost unreadable to understand what happens. > > Maybe you Nisan can explain a bit?! > > Have you tested Alexander's code again SMSCs? > > Stipe > > [EMAIL PROTECTED] > ------------------------------------------------------------------- > Wapme Systems AG > > Vogelsanger Weg 80 > 40470 Düsseldorf > > Tel: +49-211-74845-0 > Fax: +49-211-74845-299 > > E-Mail: [EMAIL PROTECTED] > Internet: http://www.wapme-systems.de > ------------------------------------------------------------------- > wapme.net - wherever you are -- 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
? 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 -u -b -r1.139 bearerbox.c --- gw/bearerbox.c 26 May 2003 18:37:11 -0000 1.139 +++ gw/bearerbox.c 17 Jun 2003 20:06:20 -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 -u -b -r1.33 dlr.c --- gw/dlr.c 27 Feb 2003 09:48:59 -0000 1.33 +++ gw/dlr.c 17 Jun 2003 20:06:21 -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,191 @@ /* 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 == NULL || handles->dlr_remove == NULL) + 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 = (smsc ? octstr_duplicate(smsc) : octstr_create("")); + dlr->timestamp = (ts ? octstr_duplicate(ts) : octstr_create("")); + dlr->source = (msg->sms.sender ? octstr_duplicate(msg->sms.sender) : octstr_create("")); + dlr->destination = (msg->sms.receiver ? octstr_duplicate(msg->sms.receiver) : octstr_create("")); + dlr->service = (msg->sms.service ? octstr_duplicate(msg->sms.service) : octstr_create("")); + dlr->url = (msg->sms.dlr_url ? octstr_duplicate(msg->sms.dlr_url) : octstr_create("")); + dlr->boxc_id = (msg->sms.boxc_id ? octstr_duplicate(msg->sms.boxc_id) : octstr_create("")); + 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 { - 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"); - } - - 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 - */ - + 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 { - 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; + warning(0, "DLR[%s]: Storage don't have remove operation defined", dlr_type()); } - 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 - */ + dlr_entry_destroy(dlr); - } else { - panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type)); - } - return -1; + return msg; } 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 -u -b -r1.12 dlr.h --- gw/dlr.h 14 Nov 2002 02:29:25 -0000 1.12 +++ gw/dlr.h 17 Jun 2003 20:06:21 -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 17 Jun 2003 20:06:21 -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 17 Jun 2003 20:06:22 -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 17 Jun 2003 20:06:22 -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 17 Jun 2003 20:06:22 -0000 @@ -0,0 +1,312 @@ +/* + * 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)); + res->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.17 diff -a -u -b -r1.17 smsc_at2.c --- gw/smsc/smsc_at2.c 27 May 2003 03:26:04 -0000 1.17 +++ gw/smsc/smsc_at2.c 17 Jun 2003 20:06:27 -0000 @@ -1494,8 +1494,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; @@ -1681,14 +1680,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 -u -b -r1.5 smsc_cgw.c --- gw/smsc/smsc_cgw.c 4 Mar 2003 15:16:09 -0000 1.5 +++ gw/smsc/smsc_cgw.c 17 Jun 2003 20:06:29 -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.12 diff -a -u -b -r1.12 smsc_cimd2.c --- gw/smsc/smsc_cimd2.c 27 May 2003 03:36:59 -0000 1.12 +++ gw/smsc/smsc_cimd2.c 17 Jun 2003 20:06:33 -0000 @@ -1885,15 +1885,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); @@ -2026,10 +2018,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 -u -b -r1.16 smsc_emi2.c --- gw/smsc/smsc_emi2.c 29 Apr 2003 12:18:26 -0000 1.16 +++ gw/smsc/smsc_emi2.c 17 Jun 2003 20:06:36 -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 -u -b -r1.1 smsc_oisd.c --- gw/smsc/smsc_oisd.c 28 Jan 2003 00:10:04 -0000 1.1 +++ gw/smsc/smsc_oisd.c 17 Jun 2003 20:06:38 -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.39 diff -a -u -b -r1.39 smsc_smpp.c --- gw/smsc/smsc_smpp.c 17 Jun 2003 08:18:39 -0000 1.39 +++ gw/smsc/smsc_smpp.c 17 Jun 2003 20:06:41 -0000 @@ -799,9 +799,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); } @@ -931,14 +931,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) { @@ -946,9 +939,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) { Index: gw/smsc/smsc_soap.c =================================================================== RCS file: /home/cvs/gateway/gw/smsc/smsc_soap.c,v retrieving revision 1.1 diff -a -u -b -r1.1 smsc_soap.c --- gw/smsc/smsc_soap.c 28 May 2003 11:45:33 -0000 1.1 +++ gw/smsc/smsc_soap.c 17 Jun 2003 20:06:47 -0000 @@ -1112,18 +1112,15 @@ sprintf(tmpid,"%lld",msgID); debug("bb.soap.read_response",0,"SOAP[%s]: ACK - id: %lld", octstr_get_cstr(privdata->name), msgID); - dlr_add(octstr_get_cstr(conn->id), tmpid, octstr_get_cstr(msg->sms.sender), - "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, octstr_imm(tmpid), msg); /* generate SMSC success DLR */ if (msg->sms.dlr_mask & DLR_SMSC_SUCCESS) { Msg* dlrmsg; - dlrmsg = dlr_find(octstr_get_cstr(conn->id),tmpid, - octstr_get_cstr(msg->sms.receiver), /* destination */ + dlrmsg = dlr_find(conn->id,octstr_imm(tmpid), + msg->sms.receiver, /* destination */ DLR_SMSC_SUCCESS); if (dlrmsg) { @@ -1586,7 +1583,7 @@ /* fetch the DLR */ - dlrmsg = dlr_find(octstr_get_cstr(conn->id),msgid, "receiver", /* destination */ + dlrmsg = dlr_find(conn->id,octstr_imm(msgid), octstr_imm("receiver"), /* destination */ dlrtype); if (!dlrmsg) { @@ -2814,7 +2811,7 @@ /* date on which the message's validity expires */ Octstr* soap_mobitai_validity_date_attribute(Msg* msg) { - return date_create_iso(msg->sms.time+(60*msg->sms.validity)); + return (Octstr *) date_create_iso(msg->sms.time+(60*msg->sms.validity)); } /* validity in seconds */ @@ -2832,7 +2829,7 @@ /* TIMESTAMP */ Octstr* soap_mobitai_date_attribute(Msg* msg) { - return date_create_iso(msg->sms.time); + return (Octstr *) date_create_iso(msg->sms.time); } Octstr* soap_rand_attribute(Msg* msg)