dlr.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:28k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /* 
  2.  * gw/dlr.c
  3.  *
  4.  * Implementation of handling delivery reports (DLRs)
  5.  *
  6.  * Andreas Fink <andreas@fink.org>, 18.08.2001
  7.  * Stipe Tolj <tolj@wapme-systems.de>, 22.03.2002
  8.  *
  9.  * Changes:
  10.  * 2001-12-17: andreas@fink.org:
  11.  *     implemented use of mutex to avoid two mysql calls to run at the same time
  12.  * 2002-03-22: tolj@wapme-systems.de:
  13.  *     added more abstraction to fit for several other storage types
  14.  * 2002-08-04: tolj@wapme-systems.de:
  15.  *     added simple database library (sdb) support
  16.  */
  17.  
  18. #include <ctype.h>
  19. #include <time.h>
  20. #include <errno.h>
  21. #include <limits.h>
  22. #include <string.h>
  23. #include <unistd.h>
  24. #include "gwlib/gwlib.h"
  25. #include "sms.h"
  26. #include "dlr.h"
  27. /*
  28. #define DLR_TRACE 1 
  29. */
  30. /* 
  31.  * We use memory based DLR
  32.  * the structure of a delivery report waiting list entry 
  33.  */
  34. typedef struct dlr_wle {
  35.    Octstr *smsc;
  36.    Octstr *timestamp;
  37.    Octstr *source;
  38.    Octstr *destination;
  39.    Octstr *service;
  40.    Octstr *url;
  41.    int mask;
  42. } dlr_wle;
  43. /* 
  44.  * This is the global list where all messages being sent out are being kept track 
  45.  * of his list is looked up once a delivery report comes in 
  46.  */
  47. static List *dlr_waiting_list;
  48. static void dlr_destroy(dlr_wle *dlr);
  49. static void dlr_init_mem(void);
  50. #ifdef DLR_MYSQL
  51. static void dlr_init_mysql(Cfg* cfg);
  52. #endif
  53. #ifdef DLR_SDB
  54. static void dlr_init_sdb(Cfg* cfg);
  55. #endif
  56. static void dlr_shutdown_mem(void);
  57. static void dlr_shutdown_mysql(void);
  58. static dlr_wle *dlr_new(void);
  59. /* 
  60.  * At startup initialize the list, use abstraction to
  61.  * allow to add additional dlr_init_foobar() routines here.
  62.  * 
  63.  * Check 'dlr-storage' directive in core group to see how DLRs are
  64.  * processed.
  65.  */
  66. static void dlr_init_mem()
  67. {
  68.     dlr_waiting_list = list_create();
  69. }
  70. /*
  71.  * Load all configuration directives that are common for all database
  72.  * types that use the 'dlr-db' group to define which attributes are 
  73.  * used in the table
  74.  */
  75. #ifdef DLR_DB
  76. static void dlr_db_init(CfgGroup *grp)
  77. {
  78.     if (!(table = cfg_get(grp, octstr_imm("table"))))
  79.         panic(0, "DLR: DB: directive 'table' is not specified!");
  80.     if (!(field_smsc = cfg_get(grp, octstr_imm("field-smsc"))))
  81.         panic(0, "DLR: DB: directive 'field-smsc' is not specified!");
  82.     if (!(field_ts = cfg_get(grp, octstr_imm("field-timestamp"))))
  83.         panic(0, "DLR: DB: directive 'field-timestamp' is not specified!");
  84.     if (!(field_src = cfg_get(grp, octstr_imm("field-source"))))
  85.         panic(0, "DLR: DB: directive 'field-source' is not specified!");
  86.     if (!(field_dst = cfg_get(grp, octstr_imm("field-destination"))))
  87.         panic(0, "DLR: DB: directive 'field-destination' is not specified!");
  88.     if (!(field_serv = cfg_get(grp, octstr_imm("field-service"))))
  89.         panic(0, "DLR: DB: directive 'field-service' is not specified!");
  90.     if (!(field_url = cfg_get(grp, octstr_imm("field-url"))))
  91.         panic(0, "DLR: DB: directive 'field-url' is not specified!");
  92.     if (!(field_mask = cfg_get(grp, octstr_imm("field-mask"))))
  93.         panic(0, "DLR: DB: directive 'field-mask' is not specified!");
  94.     if (!(field_status = cfg_get(grp, octstr_imm("field-status"))))
  95.         panic(0, "DLR: DB: directive 'field-status' is not specified!");
  96. }
  97. #endif
  98.    
  99. #ifdef DLR_MYSQL
  100. static void dlr_init_mysql(Cfg* cfg)
  101. {
  102.     CfgGroup *grp;
  103.     List *grplist;
  104.     Octstr *mysql_host, *mysql_user, *mysql_pass, *mysql_db, *mysql_id;
  105.     Octstr *p = NULL;
  106.     /*
  107.      * check for all mandatory directives that specify the field names 
  108.      * of the used MySQL table
  109.      */
  110.     if (!(grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))))
  111.         panic(0, "DLR: MySQL: group 'dlr-db' is not specified!");
  112.     if (!(mysql_id = cfg_get(grp, octstr_imm("id"))))
  113.         panic(0, "DLR: MySQL: directive 'id' is not specified!");
  114.     dlr_db_init(grp);
  115.     /*
  116.      * now grap the required information from the 'mysql-connection' group
  117.      * with the mysql-id we just obtained
  118.      *
  119.      * we have to loop through all available MySQL connection definitions 
  120.      * and search for the one we are looking for
  121.      */
  122.      grplist = cfg_get_multi_group(cfg, octstr_imm("mysql-connection"));
  123.      while (grplist && (grp = list_extract_first(grplist)) != NULL) {
  124.         p = cfg_get(grp, octstr_imm("id"));
  125.         if (p != NULL && octstr_compare(p, mysql_id) == 0) {
  126.             goto found;
  127.         }
  128.      }
  129.      panic(0, "DLR: MySQL: connection settings for id '%s' are not specified!", 
  130.            octstr_get_cstr(mysql_id));
  131. found:
  132.     octstr_destroy(p);
  133.     list_destroy(grplist, NULL);
  134.     if (!(mysql_host = cfg_get(grp, octstr_imm("host"))))
  135.         panic(0, "DLR: MySQL: directive 'host' is not specified!");
  136.     if (!(mysql_user = cfg_get(grp, octstr_imm("mysql-username"))))
  137.         panic(0, "DLR: MySQL: directive 'mysql-username' is not specified!");
  138.     if (!(mysql_pass = cfg_get(grp, octstr_imm("mysql-password"))))
  139.         panic(0, "DLR: MySQL: directive 'mysql-password' is not specified!");
  140.     if (!(mysql_db = cfg_get(grp, octstr_imm("database"))))
  141.         panic(0, "DLR: MySQL: directive 'database' is not specified!");
  142.     /*
  143.      * ok, ready to connect to MySQL 
  144.      */
  145.     mysql_init(&mysql);
  146.     connection = mysql_real_connect(&mysql, 
  147.                     octstr_get_cstr(mysql_host), octstr_get_cstr(mysql_user), 
  148.                     octstr_get_cstr(mysql_pass), octstr_get_cstr(mysql_db), 
  149.                     0, NULL, 0);
  150.     /* 
  151.      * XXX should a failing connect throw panic?!
  152.      */
  153.     if (connection == NULL) {
  154.         error(0,"DLR: MySQL: can not connect to database!");
  155.         error(0,"MYSQL: %s", mysql_error(&mysql));
  156.     } else {
  157.         info(0,"Connected to mysql server at %s.", octstr_get_cstr(mysql_host));
  158.         info(0,"MYSQL: server version %s, client version %s.",  
  159.              mysql_get_server_info(&mysql), mysql_get_client_info()); 
  160.     } 
  161.     octstr_destroy(mysql_db);
  162.     octstr_destroy(mysql_host);
  163.     octstr_destroy(mysql_user);
  164.     octstr_destroy(mysql_pass);
  165.     octstr_destroy(mysql_id);
  166. }
  167. #endif /* DLR_MYSQL */
  168. #ifdef DLR_SDB
  169. static void dlr_init_sdb(Cfg* cfg)
  170. {
  171.     CfgGroup *grp;
  172.     List *grplist;
  173.     Octstr *sdb_url, *sdb_id;
  174.     Octstr *p = NULL;
  175.     /*
  176.      * check for all mandatory directives that specify the field names 
  177.      * of the used table
  178.      */
  179.     if (!(grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))))
  180.         panic(0, "DLR: SDB: group 'dlr-db' is not specified!");
  181.     if (!(sdb_id = cfg_get(grp, octstr_imm("id"))))
  182.         panic(0, "DLR: SDB: directive 'id' is not specified!");
  183.     dlr_db_init(grp);
  184.     /*
  185.      * now grap the required information from the 'mysql-connection' group
  186.      * with the sdb-id we just obtained
  187.      *
  188.      * we have to loop through all available SDB connection definitions 
  189.      * and search for the one we are looking for
  190.      */
  191.      grplist = cfg_get_multi_group(cfg, octstr_imm("sdb-connection"));
  192.      while (grplist && (grp = list_extract_first(grplist)) != NULL) {
  193.         p = cfg_get(grp, octstr_imm("id"));
  194.         if (p != NULL && octstr_compare(p, sdb_id) == 0) {
  195.             goto found;
  196.         }
  197.      }
  198.      panic(0, "DLR: SDB: connection settings for id '%s' are not specified!", 
  199.            octstr_get_cstr(sdb_id));
  200. found:
  201.     octstr_destroy(p);
  202.     list_destroy(grplist, NULL);
  203.     if (!(sdb_url = cfg_get(grp, octstr_imm("url"))))
  204.         panic(0, "DLR: SDB: directive 'url' is not specified!");
  205.     /*
  206.      * ok, ready to connect
  207.      */
  208.     info(0,"Connecting to sdb resource <%s>.", octstr_get_cstr(sdb_url));
  209.     connection = sdb_open(octstr_get_cstr(sdb_url));
  210.     octstr_destroy(sdb_url);
  211. }
  212. #endif /* DLR_SDB */
  213. void dlr_init(Cfg* cfg)
  214. {
  215.     CfgGroup *grp;
  216.     /* create the DLR mutex */
  217.     dlr_mutex = mutex_create();
  218.     /* check which DLR storage type we are using */
  219.     grp = cfg_get_single_group(cfg, octstr_imm("core"));
  220.     dlr_type = cfg_get(grp, octstr_imm("dlr-storage"));
  221.     /* 
  222.      * assume we are using internal memory in case no directive
  223.      * has been specified, warn the user anyway
  224.      */
  225.     if (dlr_type == NULL) {
  226.         dlr_type = octstr_imm("internal");
  227.         warning(0, "DLR: using default 'internal' for storage type.");
  228.     }
  229.     /* call the sub-init routine */
  230.     if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
  231. #ifdef DLR_MYSQL
  232.         dlr_init_mysql(cfg);
  233. #else
  234.         panic(0, "DLR: storage type defined as '%s', but no MySQL support build in!", 
  235.               octstr_get_cstr(dlr_type));
  236. #endif        
  237.     } else 
  238.     if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
  239.         dlr_init_mem();
  240.     } else 
  241.     if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
  242. #ifdef DLR_SDB
  243.         dlr_init_sdb(cfg);
  244. #else
  245.         panic(0, "DLR: storage type defined as '%s', but no LibSDB support build in!", 
  246.               octstr_get_cstr(dlr_type));
  247. #endif        
  248.     /*
  249.      * add aditional types here
  250.      */
  251.     } else {
  252.         panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
  253.     }
  254. }
  255. /* 
  256.  * At stutdown destroy the list, use abstraction to
  257.  * allow to add additional dlr_shutdown_foobar() routines here.
  258.  * 
  259.  * Check 'dlr-storage' directive in core group to see how DLRs are
  260.  * processed.
  261.  */
  262. static void dlr_shutdown_mem()
  263. {
  264.     list_destroy(dlr_waiting_list, (list_item_destructor_t *)dlr_destroy);
  265. }
  266. static void dlr_shutdown_mysql()
  267. {
  268. #ifdef DLR_MYSQL
  269.     mysql_close(connection);
  270. #endif
  271. }
  272. static void dlr_shutdown_sdb()
  273. {
  274. #ifdef DLR_SDB
  275.     sdb_close(connection);
  276. #endif
  277. }
  278. void dlr_shutdown()
  279. {
  280.     /* call the sub-init routine */
  281.     if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
  282.         dlr_shutdown_mysql();
  283.     } else 
  284.     if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
  285.         dlr_shutdown_mem();
  286.     } else 
  287.     if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
  288.         dlr_shutdown_sdb();
  289.     /*
  290.      * add aditional types here
  291.      */
  292.     } else {
  293.         panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
  294.     }
  295.     /* destroy the DLR mutex */
  296.     mutex_destroy(dlr_mutex);
  297. }
  298. /* 
  299.  * internal function to allocate a new dlr_wle entry
  300.  * and intialize it to zero 
  301.  */
  302. static dlr_wle *dlr_new()
  303. {
  304. int i;
  305. dlr_wle *dlr;
  306. dlr = gw_malloc(sizeof(dlr_wle));
  307. if (dlr)
  308.         for(i=0;i<sizeof(dlr_wle);i++)
  309. ((char *)dlr)[i] = 0;
  310. return dlr;
  311. }
  312. /*
  313.  * internal function to destroy the dlr_wle entry 
  314.  */
  315. static void dlr_destroy(dlr_wle *dlr)
  316. {
  317. O_DELETE (dlr->smsc);
  318. O_DELETE (dlr->timestamp);
  319. O_DELETE (dlr->source);
  320. O_DELETE (dlr->destination);
  321. O_DELETE (dlr->service);
  322. O_DELETE (dlr->url);
  323. dlr->mask = 0;
  324. gw_free(dlr);
  325. }
  326. /*
  327.  * external functions
  328.  */
  329. static void dlr_add_mem(char *smsc, char *ts, char *src, char *dst, 
  330.                         char *service, char *url, int mask)
  331. {
  332.    dlr_wle *dlr;
  333.    if (mask & 0x1F) {
  334.         dlr = dlr_new(); 
  335.         debug("dlr.dlr", 0, "Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d", 
  336.               smsc, ts, src, dst, mask);
  337.         dlr->smsc = octstr_create(smsc);
  338.         dlr->timestamp = octstr_create(ts);
  339.         dlr->source = octstr_create(src);
  340.         dlr->destination = octstr_create(dst);
  341.         dlr->service = octstr_create(service); 
  342.         dlr->url = octstr_create(url);
  343.         dlr->mask = mask;
  344.         list_append(dlr_waiting_list,dlr);
  345.     }
  346. }
  347. static void dlr_add_mysql(char *smsc, char *ts, char *src, char *dst, 
  348.                           char *service, char *url, int mask)
  349. {
  350. #ifdef DLR_MYSQL
  351.     Octstr *sql;
  352.     int state;
  353. #if defined(DLR_TRACE)
  354.         debug("dlr.dlr", 0, "Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d",
  355.               smsc, ts, src, dst, mask);
  356. #endif
  357.     sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s) VALUES "
  358.                         "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%d');",
  359.                 octstr_get_cstr(table), octstr_get_cstr(field_smsc), 
  360.                         octstr_get_cstr(field_ts), 
  361.                         octstr_get_cstr(field_src), octstr_get_cstr(field_dst),
  362.                         octstr_get_cstr(field_serv), octstr_get_cstr(field_url), 
  363.                         octstr_get_cstr(field_mask), octstr_get_cstr(field_status),
  364.                         smsc, ts, src, dst, service, url, mask, 0);
  365.     mutex_lock(dlr_mutex);
  366.   
  367.     state = mysql_query(connection, octstr_get_cstr(sql));
  368.     if (state != 0)
  369.         error(0, "MYSQL: %s", mysql_error(connection));
  370. #if defined(DLR_TRACE)
  371.         debug("dlr.dlr", 0, "sql: %s", octstr_get_cstr(sql));
  372. #endif
  373. octstr_destroy(sql);
  374.     mutex_unlock(dlr_mutex);
  375. #endif
  376. }
  377. static void dlr_add_sdb(char *smsc, char *ts, char *src, char *dst, 
  378.                         char *service, char *url, int mask)
  379. {
  380. #ifdef DLR_SDB
  381.     Octstr *sql;
  382.     int state;
  383.     sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s) VALUES "
  384.                         "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%d')",
  385.                 octstr_get_cstr(table), octstr_get_cstr(field_smsc), 
  386.                         octstr_get_cstr(field_ts), 
  387.                         octstr_get_cstr(field_src), octstr_get_cstr(field_dst), 
  388.                         octstr_get_cstr(field_serv), octstr_get_cstr(field_url), 
  389.                         octstr_get_cstr(field_mask), octstr_get_cstr(field_status),
  390.                         smsc, ts, src, dst, service, url, mask, 0);
  391.     mutex_lock(dlr_mutex);
  392.   
  393.     state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
  394.     if (state == -1)
  395.         error(0, "SDB: error in inserting DLR");
  396.     
  397.     octstr_destroy(sql);
  398.     mutex_unlock(dlr_mutex);
  399. #endif
  400. }
  401. void dlr_add(char *smsc, char *ts, char *src, char *dst, 
  402.              char *keyword, char *id, int mask)
  403. {
  404.     if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
  405.         dlr_add_mem(smsc, ts, src, dst, keyword, id, mask);
  406.     } else 
  407.     if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
  408.         dlr_add_mysql(smsc, ts, src, dst, keyword, id, mask);
  409.     } else 
  410.     if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
  411.         dlr_add_sdb(smsc, ts, src, dst, keyword, id, mask);
  412.     /*
  413.      * add aditional types here
  414.      */
  415.     } else {
  416.         panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
  417.     }
  418. }
  419. static Msg *dlr_find_mem(char *smsc, char *ts, char *dst, int typ)
  420. {
  421.     long i;
  422.     long len;
  423.     dlr_wle *dlr;
  424.     Msg *msg;
  425.     int dlr_mask;
  426.     
  427.     debug("dlr.dlr", 0, "Looking for DLR smsc=%s, ts=%s, dst=%s, type=%d", smsc, ts, dst, typ);
  428.     len = list_len(dlr_waiting_list);
  429.     for (i=0; i < len; i++) {
  430.         dlr = list_get(dlr_waiting_list, i);
  431.         if((strcmp(octstr_get_cstr(dlr->smsc),smsc) == 0) &&
  432.        (strcmp(octstr_get_cstr(dlr->timestamp),ts) == 0)) {
  433.             dlr_mask = dlr->mask;
  434.             if ((typ & dlr_mask) > 0) {
  435.                 /* its an entry we are interested in */
  436.                 msg = msg_create(sms);
  437.                 msg->sms.sms_type = report;
  438.                 msg->sms.service = octstr_duplicate(dlr->service);
  439.                 msg->sms.dlr_mask = typ;
  440.                 msg->sms.sms_type = report;
  441.                 msg->sms.smsc_id = octstr_create(smsc);
  442.                 msg->sms.sender = octstr_duplicate(dlr->destination);
  443.                 msg->sms.receiver = octstr_duplicate(dlr->source);
  444.                 /* if dlr_url was present, recode it here again */
  445.                 msg->sms.dlr_url = octstr_len(dlr->url) ? 
  446.                     octstr_duplicate(dlr->url) : NULL;
  447.                 /* 
  448.                  * insert orginal message to the data segment 
  449.                  * later in the smsc module 
  450.                  */
  451.                 msg->sms.msgdata = NULL;
  452.                 time(&msg->sms.time);
  453.                 debug("dlr.dlr", 0, "created DLR message for URL <%s>", 
  454.                       octstr_get_cstr(msg->sms.dlr_url));
  455.             } else {
  456.                 debug("dlr.dlr", 0, "ignoring DLR message because of mask");
  457.                 /* ok that was a status report but we where not interested in having it */
  458.                 msg = NULL;
  459.             }
  460.             if ((typ & DLR_BUFFERED) && ((dlr_mask & DLR_SUCCESS) || (dlr_mask & DLR_FAIL))) {
  461.                 info(0, "dlr not destroyed, still waiting for other delivery report"); 
  462.             } else {
  463.                 list_delete(dlr_waiting_list, i, 1);
  464.                 dlr_destroy(dlr);
  465.             }
  466.             return msg;
  467.         }
  468.     }
  469.     debug("dlr.dlr", 0, "DLR not found!");
  470.     /* we couldnt find a matching entry */
  471.     return NULL;
  472. }
  473. static Msg *dlr_find_mysql(char *smsc, char *ts, char *dst, int typ)
  474. {
  475.     Msg *msg = NULL;
  476. #ifdef DLR_MYSQL
  477.     Octstr *sql;
  478.     int state;
  479.     int dlr_mask;
  480.     Octstr *dlr_service;
  481.     Octstr *dlr_url;
  482.     Octstr *source_addr;
  483.     MYSQL_RES *result;
  484.     MYSQL_ROW row;
  485.     
  486.     sql = octstr_format("SELECT %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s';",
  487.                         octstr_get_cstr(field_mask), octstr_get_cstr(field_serv), 
  488.                         octstr_get_cstr(field_url), octstr_get_cstr(field_src),
  489.                         octstr_get_cstr(table), octstr_get_cstr(field_smsc),
  490.                         smsc, octstr_get_cstr(field_ts), ts);
  491.     mutex_lock(dlr_mutex);
  492.     
  493.     state = mysql_query(connection, octstr_get_cstr(sql));
  494. #if defined(DLR_TRACE)
  495.         debug("dlr.dlr", 0, "sql: %s", octstr_get_cstr(sql));
  496. #endif        
  497.     octstr_destroy(sql);
  498.     if (state != 0) {
  499.         error(0, "MYSQL: %s", mysql_error(connection));
  500.         mutex_unlock(dlr_mutex);
  501.         return NULL;
  502.     }
  503.     result = mysql_store_result(connection);
  504.     if (mysql_num_rows(result) < 1) {
  505.         debug("dlr.mysql", 0, "no rows found");
  506.         mysql_free_result(result);
  507.         mutex_unlock(dlr_mutex);
  508.         return NULL;
  509.     }
  510.     row = mysql_fetch_row(result);
  511.     if (!row) {
  512.         debug("dlr.mysql", 0, "rows found but could not load them");
  513.         mysql_free_result(result);
  514.      mutex_unlock(dlr_mutex);
  515.         return NULL;
  516.     }
  517.     
  518.     debug("dlr.mysql", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, row[3]=%s", 
  519.           row[0], row[1], row[2], row[3] ? row[3] : "NULL");
  520.     dlr_mask = atoi(row[0]);
  521.     dlr_service = octstr_create(row[1]);
  522.     dlr_url = octstr_create(row[2]);
  523.     if(row[3])
  524.      source_addr = octstr_create(row[3]);
  525.     else
  526. source_addr = octstr_create("");
  527.     mysql_free_result(result);
  528.     
  529.     mutex_unlock(dlr_mutex);
  530.     
  531.     sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s';",
  532.                         octstr_get_cstr(table), octstr_get_cstr(field_status), 
  533.                         typ, octstr_get_cstr(field_smsc), smsc, 
  534.                         octstr_get_cstr(field_ts), ts);
  535.     
  536.     mutex_lock(dlr_mutex);
  537.     
  538.     state = mysql_query(connection, octstr_get_cstr(sql));
  539.     octstr_destroy(sql);
  540.     if (state != 0) {
  541.         error(0, "MYSQL: %s", mysql_error(connection));
  542.         mutex_unlock(dlr_mutex);
  543.         return NULL;
  544.     }
  545.     mutex_unlock(dlr_mutex);
  546.     if ((typ & dlr_mask)) {
  547.         /* its an entry we are interested in */
  548.         msg = msg_create(sms);
  549.         msg->sms.service = octstr_duplicate(dlr_service);
  550.         msg->sms.dlr_mask = typ;
  551.         msg->sms.sms_type = report;
  552.         msg->sms.smsc_id = octstr_create(smsc);
  553.         msg->sms.sender = octstr_duplicate(source_addr);
  554.         msg->sms.receiver = octstr_create(dst);
  555.         /* if dlr_url was present, recode it here again */
  556.         msg->sms.dlr_url = octstr_len(dlr_url) ? 
  557.         octstr_duplicate(dlr_url) : NULL;
  558.         /* 
  559.          * insert orginal message to the data segment 
  560.          * later in the smsc module 
  561.          */
  562.         msg->sms.msgdata = NULL;
  563.         time(&msg->sms.time);
  564.         debug("dlr.dlr", 0, "created DLR message for URL <%s>", 
  565.               octstr_get_cstr(msg->sms.dlr_url));
  566.     } else {
  567.         debug("dlr.dlr", 0, "ignoring DLR message because of mask");
  568.     }
  569.  
  570.     if ((typ & DLR_BUFFERED) && ((dlr_mask & DLR_SUCCESS) || (dlr_mask & DLR_FAIL))) {
  571.         debug("dlr.mysql", 0, "DLR not deleted because we wait on more reports");
  572.     } else {
  573.         debug("dlr.mysql", 0, "removing DLR from database");
  574.         sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1;",
  575.                             octstr_get_cstr(table), octstr_get_cstr(field_smsc), 
  576.                             smsc, octstr_get_cstr(field_ts), ts);
  577.         
  578.         mutex_lock(dlr_mutex);
  579.         state = mysql_query(connection, octstr_get_cstr(sql));
  580.         octstr_destroy(sql);
  581.         if (state != 0) {
  582.             error(0, "MYSQL: %s", mysql_error(connection));
  583.         }
  584.         mutex_unlock(dlr_mutex);
  585.     }
  586.     octstr_destroy(dlr_service);
  587.     octstr_destroy(dlr_url);
  588.     octstr_destroy(source_addr);
  589. #endif
  590.     return msg;
  591. }
  592. #ifdef DLR_SDB
  593. static int sdb_callback_add(int n, char **p, void *row)
  594. {
  595. if (!n) {
  596.         debug("dlr.sdb", 0, "no rows found");
  597.         return 0;
  598.     }
  599.     /* strip string into words */
  600.     row = octstr_split(octstr_imm(p[0]), octstr_imm(" "));
  601.     if (list_len(row) != 4) {
  602.         debug("dlr.sdb", 0, "Row has wrong length %ld", list_len(row));
  603.         return 0;
  604.     }
  605.            
  606. return 0;
  607. }
  608. static int sdb_callback_msgs(int n, char **p, void *row)
  609. {}
  610. #endif
  611. static Msg *dlr_find_sdb(char *smsc, char *ts, char *dst, int typ)
  612. {
  613.     Msg *msg = NULL;
  614. #ifdef DLR_SDB
  615.     Octstr *sql;
  616.     int state;
  617.     int dlr_mask;
  618.     Octstr *dlr_service;
  619.     Octstr *dlr_url;
  620.     Octstr *source_addr;
  621.     List *row;
  622.     
  623.     sql = octstr_format("SELECT %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s'",
  624.                         octstr_get_cstr(field_mask), octstr_get_cstr(field_serv), 
  625.                         octstr_get_cstr(field_url), octstr_get_cstr(field_src), 
  626.                         octstr_get_cstr(table), octstr_get_cstr(field_smsc),
  627.                         smsc, octstr_get_cstr(field_ts), ts);
  628.     mutex_lock(dlr_mutex);
  629.     
  630.     state = sdb_query(connection, octstr_get_cstr(sql), sdb_callback_add, row);
  631.     octstr_destroy(sql);
  632.     if (state == -1) {
  633.         error(0, "SDB: error in finding DLR");
  634.         mutex_unlock(dlr_mutex);
  635.         return NULL;
  636.     }
  637.     debug("dlr.sdb", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, row[3]=%s", 
  638.           octstr_get_cstr(list_get(row, 0)), 
  639.           octstr_get_cstr(list_get(row, 1)), 
  640.           octstr_get_cstr(list_get(row, 2)),
  641.           octstr_get_cstr(list_get(row, 3)));
  642.     dlr_mask = atoi(octstr_get_cstr(list_get(row, 0)));
  643.     dlr_service = octstr_duplicate(list_get(row, 1));
  644.     dlr_url = octstr_duplicate(list_get(row, 2));
  645.     source_addr = octstr_duplicate(list_get(row, 3));
  646.     list_destroy(row, octstr_destroy_item);
  647.     
  648.     mutex_unlock(dlr_mutex);
  649.     
  650.     sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s'",
  651.                         octstr_get_cstr(table), octstr_get_cstr(field_status), 
  652.                         typ, octstr_get_cstr(field_smsc), smsc, 
  653.                         octstr_get_cstr(field_ts), ts);
  654.     
  655.     mutex_lock(dlr_mutex);
  656.     
  657.     state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
  658.     octstr_destroy(sql);
  659.     if (state == -1) {
  660.         error(0, "SDB: error in updating DLR");
  661.         mutex_unlock(dlr_mutex);
  662.         return NULL;
  663.     }
  664.     mutex_unlock(dlr_mutex);
  665.     if ((typ & dlr_mask)) {
  666.         /* its an entry we are interested in */
  667.         msg = msg_create(sms);
  668.         msg->sms.service = octstr_duplicate(dlr_service);
  669.         msg->sms.dlr_mask = typ;
  670.         msg->sms.sms_type = report;
  671.         msg->sms.smsc_id = octstr_create(smsc);
  672.      msg->sms.sender = octstr_duplicate(source_addr);
  673.         msg->sms.receiver = octstr_create(dst);
  674.         
  675.         /* if dlr_url was present, recode it here again */
  676.         msg->sms.dlr_url = octstr_len(dlr_url) ? 
  677.         octstr_duplicate(dlr_url) : NULL;
  678.         /* 
  679.          * insert orginal message to the data segment 
  680.          * later in the smsc module 
  681.          */
  682.         msg->sms.msgdata = NULL;
  683.         time(&msg->sms.time);
  684.         debug("dlr.dlr", 0, "created DLR message for URL <%s>", 
  685.               octstr_get_cstr(msg->sms.dlr_url));
  686.     } else {
  687.         debug("dlr.dlr", 0, "ignoring DLR message because of mask");
  688.     }
  689.  
  690.     if ((typ & DLR_BUFFERED) && ((dlr_mask & DLR_SUCCESS) || (dlr_mask & DLR_FAIL))) {
  691.         debug("dlr.sdb", 0, "DLR not deleted because we wait on more reports");
  692.     } else {
  693.         debug("dlr.sdb", 0, "removing DLR from database");
  694.         sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1",
  695.                             octstr_get_cstr(table), octstr_get_cstr(field_smsc), 
  696.                             smsc, octstr_get_cstr(field_ts), ts);
  697.         
  698.         mutex_lock(dlr_mutex);
  699.         state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
  700.         octstr_destroy(sql);
  701.         if (state == -1) {
  702.             error(0, "SDB: error in deleting DLR");
  703.         }
  704.         mutex_unlock(dlr_mutex);
  705.     }
  706.     octstr_destroy(dlr_service);
  707.     octstr_destroy(dlr_url);
  708.     octstr_destroy(source_addr);
  709. #endif
  710.     return msg;
  711. }
  712. Msg *dlr_find(char *smsc, char *ts, char *dst, int typ)
  713. {
  714.     Msg *msg = NULL;
  715.     if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
  716.         msg = dlr_find_mem(smsc, ts, dst, typ);
  717.     } else 
  718.     if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
  719.         msg = dlr_find_mysql(smsc, ts, dst, typ);
  720.     } else 
  721.     if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
  722.         msg = dlr_find_sdb(smsc, ts, dst, typ);
  723.     /*
  724.      * add aditional types here
  725.      */
  726.     } else {
  727.         panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
  728.     }
  729.     return msg;
  730. }
  731. long dlr_messages(void)
  732. {
  733.     if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
  734.         return list_len(dlr_waiting_list);
  735.     } else 
  736.     if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
  737. #ifdef DLR_MYSQL
  738.         Octstr *sql;
  739.         int state;
  740.         long res;
  741.         MYSQL_RES *result;
  742.         
  743.         sql = octstr_format("SELECT * FROM %s;", octstr_get_cstr(table));
  744.         mutex_lock(dlr_mutex);
  745.         state = mysql_query(connection, octstr_get_cstr(sql));
  746.         octstr_destroy(sql);
  747.         if (state != 0) {
  748.             error(0, "MYSQL: %s", mysql_error(connection));
  749.             mutex_unlock(dlr_mutex);
  750.             return -1;
  751.         }
  752.         result = mysql_store_result(connection);
  753.         res = mysql_num_rows(result);
  754.         mysql_free_result(result);
  755.         mutex_unlock(dlr_mutex);
  756.         return res;
  757. #endif
  758.     } else 
  759.     if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
  760. #ifdef DLR_SDB
  761.         Octstr *sql;
  762.         int state;
  763.         long res;
  764.         
  765.         sql = octstr_format("SELECT * FROM %s", octstr_get_cstr(table));
  766.         mutex_lock(dlr_mutex);
  767.         state = sdb_query(connection, octstr_get_cstr(sql), sdb_callback_msgs, NULL);
  768.         octstr_destroy(sql);
  769.         if (state == -1) {
  770.             error(0, "SDB: error in selecting ammount of waiting DLRs");
  771.             mutex_unlock(dlr_mutex);
  772.             return -1;
  773.         }
  774.         res = (long) state;
  775.         mutex_unlock(dlr_mutex);
  776.         return res;
  777. #endif
  778.     /*
  779.      * add aditional types here
  780.      */
  781.     } else {
  782.         panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
  783.     }
  784.     return -1;
  785. }
  786. void dlr_flush(void)
  787. {
  788.     long i;
  789.     long len;
  790.  
  791.     info(0, "Flushing all %ld queued DLR messages in %s storage", dlr_messages(), 
  792.             octstr_get_cstr(dlr_type));
  793.  
  794.     if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
  795.         len = list_len(dlr_waiting_list);
  796.         for (i=0; i < len; i++)
  797.             list_delete(dlr_waiting_list, i, 1);
  798.         
  799.     } else 
  800.     if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
  801. #ifdef DLR_MYSQL
  802.         Octstr *sql;
  803.         int state;
  804.         MYSQL_RES *result;
  805.         
  806.         sql = octstr_format("DELETE FROM %s;", octstr_get_cstr(table));
  807.         mutex_lock(dlr_mutex);
  808.         state = mysql_query(connection, octstr_get_cstr(sql));
  809.         octstr_destroy(sql);
  810.         if (state != 0) {
  811.             error(0, "MYSQL: %s", mysql_error(connection));
  812.         }
  813.         result = mysql_store_result(connection);
  814.         mysql_free_result(result);
  815.         mutex_unlock(dlr_mutex);
  816. #endif
  817.     } else 
  818.     if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
  819. #ifdef DLR_SDB
  820.         Octstr *sql;
  821.         int state;
  822.         
  823.         sql = octstr_format("DELETE FROM %s", octstr_get_cstr(table));
  824.         mutex_lock(dlr_mutex);
  825.         state = sdb_query(connection, octstr_get_cstr(sql), NULL, NULL);
  826.         octstr_destroy(sql);
  827.         if (state == -1) {
  828.             error(0, "SDB: error in flusing DLR table");
  829.         }
  830.         mutex_unlock(dlr_mutex);
  831. #endif
  832.     /*
  833.      * add aditional types here
  834.      */
  835.     } else {
  836.         panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
  837.     }
  838. }