Kannel: Open Source WAP and SMS gateway  svn-r5335
sqlbox_sdb.c
Go to the documentation of this file.
1 #include "gwlib/gwlib.h"
2 #ifdef HAVE_SDB
3 #include "gwlib/dbpool.h"
4 #include <sdb.h>
5 #include "sqlbox_sdb.h"
6 
7 #define sql_update sdb_update
8 #define sql_select sdb_select
9 
10 static Octstr *sqlbox_logtable;
11 static Octstr *sqlbox_insert_table;
12 
13 
14 /*
15  * Our connection pool to sdb.
16  */
17 
18 static DBPool *pool = NULL;
19 
20 static struct sqlbox_db_fields *fields = NULL;
21 
22 static struct sqlbox_db_queries *queries = NULL;
23 
24 enum {
25  SDB_MYSQL,
26  SDB_ORACLE,
27  SDB_POSTGRES,
28  SDB_SQLITE,
29  SDB_SQLITE3,
30  SDB_OTHER
31 };
32 
33 static long sdb_conn_type = SDB_OTHER;
34 
35 /*
36  *-------------------------------------------------
37  * sdb thingies
38  *-------------------------------------------------
39 */
40 
41 #define octstr_null_create(x) ((x != NULL) ? octstr_create(x) : octstr_create(""))
42 #define atol_null(x) ((x != NULL) ? atol(x) : -1)
43 #define get_sdb_octstr_col(x) (octstr_create(octstr_get_cstr(gwlist_get(row,x))))
44 #define get_sdb_long_col(x) (atol(octstr_get_cstr(gwlist_get(row,x))))
45 
46 static int sdb_update(DBPoolConn *conn, const Octstr *sql)
47 {
48  int state;
49 
50 #if defined(SQLBOX_TRACE)
51  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(sql));
52 #endif
53 
54  state = sdb_query(conn->conn, octstr_get_cstr(sql), NULL, NULL);
55  if (state < 0) {
56  error(0, "SDB: Error updating rows");
57  return -1;
58  }
59  return state;
60 }
61 
62 static int sdb_select(DBPoolConn *conn, const Octstr *sql,
63  int (*callback)(int, char **, void *), void *closure)
64 {
65  int state;
66 
67 #if defined(SQLBOX_TRACE)
68  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(sql));
69 #endif
70 
71  state = sdb_query(conn->conn, octstr_get_cstr(sql), callback, closure);
72  if (state < 0) {
73  error(0, "SDB: Error selecting rows");
74  return -1;
75  }
76  return state;
77 }
78 
79 void sdb_callback_addrow(int n, char **data, List **rows)
80 {
81  int i;
82  List *row = gwlist_create();
83  for (i = 0; i < n; i++) {
84  gwlist_insert(row, i, octstr_null_create(data[i]));
85  }
86  gwlist_append(*rows, row);
87 }
88 
89 void sqlbox_configure_sdb(Cfg* cfg)
90 {
91  CfgGroup *grp;
92  Octstr *sql;
93  DBPoolConn *pc;
94 
95  if (!(grp = cfg_get_single_group(cfg, octstr_imm("sqlbox"))))
96  panic(0, "SQLBOX: Sdb: group 'sqlbox' is not specified!");
97 
98  sqlbox_logtable = cfg_get(grp, octstr_imm("sql-log-table"));
99  if (sqlbox_logtable == NULL) {
100  panic(0, "Parameter 'sql-log-table' not configured.");
101  }
102  sqlbox_insert_table = cfg_get(grp, octstr_imm("sql-insert-table"));
103  if (sqlbox_insert_table == NULL) {
104  panic(0, "Parameter 'sql-insert-table' not configured.");
105  }
106 
107  pc = dbpool_conn_consume(pool);
108  if (pc == NULL) {
109  error(0, "SDB: Database pool got no connection! DB update failed!");
110  return;
111  }
112 
113  /* create send_sms && sent_sms tables if they do not exist */
114  sqlbox_run_query(queries->create_log_table, sqlbox_logtable);
115  sqlbox_run_query(queries->create_log_sequence, sqlbox_logtable);
116  sqlbox_run_query(queries->create_log_trigger, sqlbox_logtable);
117  sqlbox_run_query(queries->create_insert_table, sqlbox_insert_table);
118  sqlbox_run_query(queries->create_insert_sequence, sqlbox_insert_table);
119  sqlbox_run_query(queries->create_insert_trigger, sqlbox_insert_table);
120  /* end table creation */
121 
123 }
124 
125 Msg *sdb_fetch_msg()
126 {
127  Msg *msg = NULL;
128  Octstr *sql, *delet, *id;
129  List *res, *row;
130  DBPoolConn *pc;
131 
132  pc = dbpool_conn_consume(pool);
133  if (pc == NULL) {
134  error(0, "SDB: Database pool got no connection! DB update failed!");
135  return NULL;
136  }
137  res = gwlist_create();
138  gw_assert(res != NULL);
139  sql = octstr_format(queries->select_query, sqlbox_insert_table);
140 #if defined(SQLBOX_TRACE)
141  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(sql));
142 #endif
143  if (sql_select(pc, sql, (void *)sdb_callback_addrow, &res) < 0) {
144  debug("sqlbox", 0, "SQL statement failed: %s", octstr_get_cstr(sql));
145  } else {
146  if (gwlist_len(res) > 0) {
147  row = gwlist_extract_first(res);
148  gw_assert(row != NULL);
149  id = get_sdb_octstr_col(0);
150  /* save fields in this row as msg struct */
151  msg = msg_create(sms);
152  /* we abuse the foreign_id field in the message struct for our sql_id value */
153  msg->sms.foreign_id = get_sdb_octstr_col(0);
154  msg->sms.sender = get_sdb_octstr_col(2);
155  msg->sms.receiver = get_sdb_octstr_col(3);
156  msg->sms.udhdata = get_sdb_octstr_col(4);
157  msg->sms.msgdata = get_sdb_octstr_col(5);
158  msg->sms.time = get_sdb_long_col(6);
159  msg->sms.smsc_id = get_sdb_octstr_col(7);
160  msg->sms.service = get_sdb_octstr_col(8);
161  msg->sms.account = get_sdb_octstr_col(9);
162  /* msg->sms.id = get_sdb_long_col(10); */
163  msg->sms.sms_type = get_sdb_long_col(11);
164  msg->sms.mclass = get_sdb_long_col(12);
165  msg->sms.mwi = get_sdb_long_col(13);
166  msg->sms.coding = get_sdb_long_col(14);
167  msg->sms.compress = get_sdb_long_col(15);
168  msg->sms.validity = get_sdb_long_col(16);
169  msg->sms.deferred = get_sdb_long_col(17);
170  msg->sms.dlr_mask = get_sdb_long_col(18);
171  msg->sms.dlr_url = get_sdb_octstr_col(19);
172  msg->sms.pid = get_sdb_long_col(20);
173  msg->sms.alt_dcs = get_sdb_long_col(21);
174  msg->sms.rpi = get_sdb_long_col(22);
175  msg->sms.charset = get_sdb_octstr_col(23);
176  msg->sms.binfo = get_sdb_octstr_col(25);
177  msg->sms.meta_data = get_sdb_octstr_col(26);
178  if (gwlist_get(row,24) == NULL) {
179  msg->sms.boxc_id= octstr_duplicate(sqlbox_id);
180  }
181  else {
182  msg->sms.boxc_id= get_sdb_octstr_col(24);
183  }
184  /* delete current row */
185  delet = octstr_format(queries->delete_query, sqlbox_insert_table, id);
186 #if defined(SQLBOX_TRACE)
187  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(delet));
188 #endif
189  sql_update(pc, delet);
190  octstr_destroy(id);
191  octstr_destroy(delet);
193  }
194  }
195  gwlist_destroy(res, NULL);
196  octstr_destroy(sql);
198  return msg;
199 }
200 
201 static Octstr *get_numeric_value_or_return_null(long int num)
202 {
203  if (num == -1) {
204  return octstr_create("NULL");
205  }
206  return octstr_format("%ld", num);
207 }
208 
209 static Octstr *get_string_value_or_return_null(Octstr *str)
210 {
211  if (str == NULL) {
212  return octstr_create("NULL");
213  }
214  if (octstr_compare(str, octstr_imm("")) == 0) {
215  return octstr_create("NULL");
216  }
217  octstr_replace(str, octstr_imm("\\"), octstr_imm("\\\\"));
218  octstr_replace(str, octstr_imm("\'"), octstr_imm("\\\'"));
219  return octstr_format("\'%S\'", str);
220 }
221 
222 #define st_num(x) (stuffer[stuffcount++] = get_numeric_value_or_return_null(x))
223 #define st_str(x) (stuffer[stuffcount++] = get_string_value_or_return_null(x))
224 
225 void sdb_save_msg(Msg *msg, Octstr *momt /*, Octstr smsbox_id */)
226 {
227  Octstr *sql;
228  Octstr *stuffer[30];
229  int stuffcount = 0;
230  DBPoolConn *pc;
231 
232  pc = dbpool_conn_consume(pool);
233  if (pc == NULL) {
234  error(0, "SDB: Database pool got no connection! DB update failed!");
235  return;
236  }
237 
238  sql = octstr_format(queries->insert_query, sqlbox_logtable, st_str(momt), st_str(msg->sms.sender),
239  st_str(msg->sms.receiver), st_str(msg->sms.udhdata), st_str(msg->sms.msgdata), st_num(msg->sms.time),
240  st_str(msg->sms.smsc_id), st_str(msg->sms.service), st_str(msg->sms.account), st_num(msg->sms.sms_type),
241  st_num(msg->sms.mclass), st_num(msg->sms.mwi), st_num(msg->sms.coding), st_num(msg->sms.compress),
242  st_num(msg->sms.validity), st_num(msg->sms.deferred), st_num(msg->sms.dlr_mask), st_str(msg->sms.dlr_url),
243  st_num(msg->sms.pid), st_num(msg->sms.alt_dcs), st_num(msg->sms.rpi), st_str(msg->sms.charset),
244  st_str(msg->sms.boxc_id), st_str(msg->sms.binfo), st_str(msg->sms.meta_data), st_str(msg->sms.foreign_id));
245  sql_update(pc, sql);
246  while (stuffcount > 0) {
247  octstr_destroy(stuffer[--stuffcount]);
248  }
249  octstr_destroy(sql);
251 }
252 
253 void sdb_leave()
254 {
255  dbpool_destroy(pool);
256 }
257 
258 struct server_type *sqlbox_init_sdb(Cfg* cfg)
259 {
260  CfgGroup *grp;
261  List *grplist;
262  Octstr *sdb_url, *sdb_id;
263  Octstr *p = NULL;
264  long pool_size;
265  DBConf *db_conf = NULL;
266  struct server_type *res = NULL;
267 
268  /*
269  * check for all mandatory directives that specify the field names
270  * of the used Sdb table
271  */
272  if (!(grp = cfg_get_single_group(cfg, octstr_imm("sqlbox"))))
273  panic(0, "SQLBOX: Sdb: group 'sqlbox' is not specified!");
274 
275  if (!(sdb_id = cfg_get(grp, octstr_imm("id"))))
276  panic(0, "SQLBOX: Sdb: directive 'id' is not specified!");
277 
278  /*
279  * now grap the required information from the 'sdb-connection' group
280  * with the sdb-id we just obtained
281  *
282  * we have to loop through all available Sdb connection definitions
283  * and search for the one we are looking for
284  */
285 
286  grplist = cfg_get_multi_group(cfg, octstr_imm("sdb-connection"));
287  while (grplist && (grp = (CfgGroup *)gwlist_extract_first(grplist)) != NULL) {
288  p = cfg_get(grp, octstr_imm("id"));
289  if (p != NULL && octstr_compare(p, sdb_id) == 0) {
290  goto found;
291  }
292  if (p != NULL) octstr_destroy(p);
293  }
294  panic(0, "SQLBOX: Sdb: connection settings for id '%s' are not specified!",
295  octstr_get_cstr(sdb_id));
296 
297 found:
298  octstr_destroy(p);
299  gwlist_destroy(grplist, NULL);
300 
301  if (cfg_get_integer(&pool_size, grp, octstr_imm("max-connections")) == -1 || pool_size == 0)
302  pool_size = 1;
303 
304  if (!(sdb_url = cfg_get(grp, octstr_imm("url"))))
305  panic(0, "SQLBOX: SDB: directive 'url' is not specified!");
306 
307  queries = gw_malloc(sizeof(struct sqlbox_db_queries));
308  gw_assert(queries != NULL);
309 
310  if (octstr_search(sdb_url, octstr_imm("mysql:"), 0) == 0) {
311  warning(0, "SQLBOX[sdb]: Please use native MySQL support, instead of libsdb.");
312  sdb_conn_type = SDB_MYSQL;
313  queries->create_insert_table = SQLBOX_MYSQL_CREATE_INSERT_TABLE;
314  queries->create_insert_sequence = NULL;
315  queries->create_insert_trigger = NULL;
316  queries->create_log_table = SQLBOX_MYSQL_CREATE_LOG_TABLE;
317  queries->create_log_sequence = NULL;
318  queries->create_log_trigger = NULL;
319  queries->select_query = SQLBOX_MYSQL_SELECT_QUERY;
320  queries->delete_query = SQLBOX_MYSQL_DELETE_QUERY;
321  queries->insert_query = SQLBOX_MYSQL_INSERT_QUERY;
322  }
323  else if (octstr_search(sdb_url, octstr_imm("oracle:"), 0) == 0) {
324  sdb_conn_type = SDB_ORACLE;
325  queries->create_insert_table = SQLBOX_ORACLE_CREATE_INSERT_TABLE;
326  queries->create_insert_sequence = SQLBOX_ORACLE_CREATE_INSERT_SEQUENCE;
327  queries->create_insert_trigger = SQLBOX_ORACLE_CREATE_INSERT_TRIGGER;
328  queries->create_log_table = SQLBOX_ORACLE_CREATE_LOG_TABLE;
329  queries->create_log_sequence = SQLBOX_ORACLE_CREATE_LOG_SEQUENCE;
330  queries->create_log_trigger = SQLBOX_ORACLE_CREATE_LOG_TRIGGER;
331  queries->select_query = SQLBOX_ORACLE_SELECT_QUERY;
332  queries->delete_query = SQLBOX_ORACLE_DELETE_QUERY;
333  queries->insert_query = SQLBOX_ORACLE_INSERT_QUERY;
334  }
335  else if (octstr_search(sdb_url, octstr_imm("postgres:"), 0) == 0) {
336  sdb_conn_type = SDB_POSTGRES;
337  queries->create_insert_table = SQLBOX_PGSQL_CREATE_INSERT_TABLE;
338  queries->create_insert_sequence = NULL;
339  queries->create_insert_trigger = NULL;
340  queries->create_log_table = SQLBOX_PGSQL_CREATE_LOG_TABLE;
341  queries->create_log_sequence = NULL;
342  queries->create_log_trigger = NULL;
343  queries->select_query = SQLBOX_PGSQL_SELECT_QUERY;
344  queries->delete_query = SQLBOX_PGSQL_DELETE_QUERY;
345  queries->insert_query = SQLBOX_PGSQL_INSERT_QUERY;
346  }
347  else if (octstr_search(sdb_url, octstr_imm("sqlite:"), 0) == 0) {
348  sdb_conn_type = SDB_SQLITE;
349  queries->create_insert_table = SQLBOX_SQLITE_CREATE_INSERT_TABLE;
350  queries->create_insert_sequence = NULL;
351  queries->create_insert_trigger = NULL;
352  queries->create_log_table = SQLBOX_SQLITE_CREATE_LOG_TABLE;
353  queries->create_log_sequence = NULL;
354  queries->create_log_trigger = NULL;
355  queries->select_query = SQLBOX_SQLITE_SELECT_QUERY;
356  queries->delete_query = SQLBOX_SQLITE_DELETE_QUERY;
357  queries->insert_query = SQLBOX_SQLITE_INSERT_QUERY;
358  }
359  else if (octstr_search(sdb_url, octstr_imm("sqlite3:"), 0) == 0) {
360  sdb_conn_type = SDB_SQLITE3;
361  queries->create_insert_table = SQLBOX_SQLITE3_CREATE_INSERT_TABLE;
362  queries->create_insert_sequence = NULL;
363  queries->create_insert_trigger = NULL;
364  queries->create_log_table = SQLBOX_SQLITE3_CREATE_LOG_TABLE;
365  queries->create_log_sequence = NULL;
366  queries->create_log_trigger = NULL;
367  queries->select_query = SQLBOX_SQLITE3_SELECT_QUERY;
368  queries->delete_query = SQLBOX_SQLITE3_DELETE_QUERY;
369  queries->insert_query = SQLBOX_SQLITE3_INSERT_QUERY;
370  }
371  else {
372  sdb_conn_type = SDB_OTHER;
373  queries->create_insert_table = NULL;
374  queries->create_insert_sequence = NULL;
375  queries->create_insert_trigger = NULL;
376  queries->create_log_table = NULL;
377  queries->create_log_sequence = NULL;
378  queries->create_log_trigger = NULL;
379  queries->select_query = SQLBOX_OTHER_SELECT_QUERY;
380  queries->delete_query = SQLBOX_OTHER_DELETE_QUERY;
381  queries->insert_query = SQLBOX_OTHER_INSERT_QUERY;
382  }
383  /*
384  * ok, ready to connect to Sdb
385  */
386  db_conf = gw_malloc(sizeof(DBConf));
387  gw_assert(db_conf != NULL);
388 
389  db_conf->sdb = gw_malloc(sizeof(SDBConf));
390  gw_assert(db_conf->sdb != NULL);
391 
392  db_conf->sdb->url = sdb_url;
393 
394  pool = dbpool_create(DBPOOL_SDB, db_conf, pool_size);
395  gw_assert(pool != NULL);
396 
397  /*
398  * XXX should a failing connect throw panic?!
399  */
400  if (dbpool_conn_count(pool) == 0)
401  panic(0,"SQLBOX: Sdb: database pool has no connections!");
402 
403  octstr_destroy(sdb_id);
404 
405  res = gw_malloc(sizeof(struct server_type));
406  gw_assert(res != NULL);
407 
408  res->type = octstr_create("Sdb");
409  res->sql_enter = sqlbox_configure_sdb;
410  res->sql_leave = sdb_leave;
411  res->sql_fetch_msg = sdb_fetch_msg;
412  res->sql_save_msg = sdb_save_msg;
413  res->sql_fetch_msg_list = NULL;
414  res->sql_save_list = NULL;
415  return res;
416 }
417 #endif
void error(int err, const char *fmt,...)
Definition: log.c:648
int(* sql_fetch_msg_list)(List *, long)
Definition: sqlbox_sql.h:19
void octstr_replace(Octstr *haystack, Octstr *needle, Octstr *repl)
Definition: octstr.c:2649
long dbpool_conn_count(DBPool *p)
DBPool * dbpool_create(enum db_type db_type, DBConf *conf, unsigned int connections)
gw_assert(wtls_machine->packet_to_send !=NULL)
void gwlist_append(List *list, void *item)
Definition: list.c:179
Octstr * url
Definition: dbpool.h:124
char * delete_query
Definition: sqlbox_sql.h:31
long gwlist_len(List *list)
Definition: list.c:166
void * gwlist_get(List *list, long pos)
Definition: list.c:292
SDBConf * sdb
Definition: dbpool.h:167
long octstr_search(const Octstr *haystack, const Octstr *needle, long pos)
Definition: octstr.c:1070
#define cfg_get(grp, varname)
Definition: cfg.h:86
char * create_log_trigger
Definition: sqlbox_sql.h:29
#define msg_create(type)
Definition: msg.h:136
void(* sql_save_list)(List *, Octstr *, int)
Definition: sqlbox_sql.h:20
static Cfg * cfg
Definition: opensmppbox.c:95
void(* sql_leave)()
Definition: sqlbox_sql.h:16
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static struct pid_list * found
void(* sql_enter)(Cfg *)
Definition: sqlbox_sql.h:15
void dbpool_conn_produce(DBPoolConn *conn)
char * select_query
Definition: sqlbox_sql.h:30
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Definition: msg.h:79
Definition: cfg.c:164
void * gwlist_extract_first(List *list)
Definition: list.c:305
Msg *(* sql_fetch_msg)()
Definition: sqlbox_sql.h:17
#define octstr_duplicate(ostr)
Definition: octstr.h:187
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:645
void warning(int err, const char *fmt,...)
Definition: log.c:660
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
void octstr_destroy_item(void *os)
Definition: octstr.c:336
void gwlist_insert(List *list, long pos, void *item)
Definition: list.c:214
char * create_log_sequence
Definition: sqlbox_sql.h:28
Definition: dbpool.h:164
void dbpool_destroy(DBPool *p)
Definition: octstr.c:118
char * create_insert_trigger
Definition: sqlbox_sql.h:26
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
#define panic
Definition: log.h:87
Definition: cfg.c:73
#define gwlist_create()
Definition: list.h:136
char * create_insert_table
Definition: sqlbox_sql.h:24
DBPoolConn * dbpool_conn_consume(DBPool *p)
Octstr * type
Definition: sqlbox_sql.h:14
char * create_insert_sequence
Definition: sqlbox_sql.h:25
void * conn
Definition: dbpool.h:95
#define sqlbox_run_query(query, table)
Definition: sqlbox_sql.h:55
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:639
Octstr * sqlbox_id
Definition: sqlbox.c:95
char * insert_query
Definition: sqlbox_sql.h:32
char * create_log_table
Definition: sqlbox_sql.h:27
Definition: list.c:102
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void(* sql_save_msg)(Msg *, Octstr *)
Definition: sqlbox_sql.h:18
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.