1 #include "../../lib/srdb1/db.h"
2 #include "ul_db.h"
3 #include "p_usrloc_mod.h"
4 #include "ul_db_layer.h"
5 #include "ul_db_api.h"
6
7 typedef struct res_list {
8 db1_con_t ** h;
9 db1_res_t * r;
10 struct res_list * next;
11 }
12 res_list_t;
13
14 static void add_res(db1_res_t * _r, db1_con_t ** _h);
15 static db1_con_t ** get_handle_by_res(db1_res_t * _r);
16 static void drop_res(db1_res_t * _r);
17
18 static ul_db_api_t p_ul_dbf;
19 static db_func_t dbf;
20
21 static res_list_t * used = NULL;
22 static res_list_t * unused = NULL;
23
24 static ul_domain_db_list_t * domain_db_list = NULL;
25
ul_db_layer_init(void)26 int ul_db_layer_init(void) {
27 if(bind_ul_db(&p_ul_dbf) < 0) {
28 LM_ERR("could not bind ul_db_api.\n");
29 return -1;
30 }
31 if(db_bind_mod(&default_db_url, &dbf) < 0) {
32 LM_ERR("could not bind db.\n");
33 return -1;
34 }
35 return 0;
36 }
37
ul_db_layer_destroy(void)38 void ul_db_layer_destroy(void) {
39 res_list_t * tmp, * del;
40 tmp = used;
41 while(tmp) {
42 del = tmp;
43 tmp = tmp->next;
44 pkg_free(del);
45 }
46 tmp = unused;
47 while(tmp) {
48 del = tmp;
49 tmp = tmp->next;
50 pkg_free(del);
51 }
52 return;
53 }
54
ul_db_layer_single_connect(udomain_t * domain,str * url)55 int ul_db_layer_single_connect(udomain_t * domain, str * url) {
56 if((domain->dbh = dbf.init(url)) == NULL){
57 return -1;
58 }
59 return 1;
60 }
61
ul_db_layer_insert(udomain_t * domain,str * user,str * sipdomain,db_key_t * _k,db_val_t * _v,int _n)62 int ul_db_layer_insert(udomain_t * domain, str * user, str * sipdomain,
63 db_key_t* _k, db_val_t* _v, int _n) {
64 ul_domain_db_t * d;
65 switch(domain->dbt) {
66 case DB_TYPE_CLUSTER: return p_ul_dbf.insert(domain->name, user, sipdomain, _k, _v, _n);
67 case DB_TYPE_SINGLE: if(!domain->dbh){
68 if((d = ul_find_domain(domain->name->s)) == 0){
69 return -1;
70 }
71 if(ul_db_layer_single_connect(domain, &d->url) < 0){
72 return -1;
73 }
74 }
75 if(dbf.use_table(domain->dbh, domain->name) < 0) {
76 return -1;
77 }
78 return dbf.insert(domain->dbh, _k, _v, _n);
79 default: return -1;
80 }
81 }
82
ul_db_layer_update(udomain_t * domain,str * user,str * sipdomain,db_key_t * _k,db_op_t * _o,db_val_t * _v,db_key_t * _uk,db_val_t * _uv,int _n,int _un)83 int ul_db_layer_update(udomain_t * domain, str * user, str * sipdomain, db_key_t* _k, db_op_t* _o, db_val_t* _v,
84 db_key_t* _uk, db_val_t* _uv, int _n, int _un) {
85 ul_domain_db_t * d;
86 switch(domain->dbt) {
87 case DB_TYPE_CLUSTER: return p_ul_dbf.update(domain->name, user, sipdomain, _k, _o, _v, _uk, _uv, _n, _un);
88 case DB_TYPE_SINGLE: if(!domain->dbh){
89 if((d = ul_find_domain(domain->name->s)) == 0){
90 return -1;
91 }
92 if(ul_db_layer_single_connect(domain, &d->url) < 0){
93 return -1;
94 }
95 }
96 if(dbf.use_table(domain->dbh, domain->name) < 0) {
97 return -1;
98 }
99 return dbf.update(domain->dbh, _k, _o, _v, _uk, _uv, _n, _un);
100 default: return -1;
101 }
102 }
103
ul_db_layer_replace(udomain_t * domain,str * user,str * sipdomain,db_key_t * _k,db_val_t * _v,int _n,int _un)104 int ul_db_layer_replace (udomain_t * domain, str * user, str * sipdomain,
105 db_key_t* _k, db_val_t* _v, int _n, int _un) {
106 ul_domain_db_t * d;
107 switch(domain->dbt) {
108 case DB_TYPE_CLUSTER: { return p_ul_dbf.replace(domain->name, user, sipdomain, _k, _v, _n, _un);;}
109 case DB_TYPE_SINGLE: if(!domain->dbh){
110 if((d = ul_find_domain(domain->name->s)) == 0){
111 return -1;
112 }
113 if(ul_db_layer_single_connect(domain, &d->url) < 0){
114 return -1;
115 }
116 }
117 if(dbf.use_table(domain->dbh, domain->name) < 0) {
118 return -1;
119 }
120 return dbf.replace(domain->dbh, _k, _v, _n, _un, 0);
121 default: return -1;
122 }
123 }
124
ul_db_layer_delete(udomain_t * domain,str * user,str * sipdomain,db_key_t * _k,db_op_t * _o,db_val_t * _v,int _n)125 int ul_db_layer_delete(udomain_t * domain, str * user, str * sipdomain,
126 db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n) {
127 ul_domain_db_t * d;
128 switch(domain->dbt) {
129 case DB_TYPE_CLUSTER: return p_ul_dbf.delete(domain->name, user, sipdomain, _k, _o, _v, _n);
130 case DB_TYPE_SINGLE: if(!domain->dbh){
131 if((d = ul_find_domain(domain->name->s)) == 0){
132 return -1;
133 }
134 if(ul_db_layer_single_connect(domain, &d->url) < 0){
135 return -1;
136 }
137 }
138 if(dbf.use_table(domain->dbh, domain->name) < 0) {
139 return -1;
140 }
141 return dbf.delete(domain->dbh, _k, _o, _v, _n);
142 default: return -1;
143 }
144 }
145
ul_db_layer_query(udomain_t * domain,str * user,str * sipdomain,db_key_t * _k,db_op_t * _op,db_val_t * _v,db_key_t * _c,int _n,int _nc,db_key_t _o,db1_res_t ** _r)146 int ul_db_layer_query(udomain_t * domain, str * user, str * sipdomain,
147 db_key_t* _k, db_op_t* _op, db_val_t* _v, db_key_t* _c,
148 int _n, int _nc, db_key_t _o, db1_res_t** _r) {
149 ul_domain_db_t * d;
150 db1_con_t ** h;
151 int ret;
152 switch(domain->dbt) {
153 case DB_TYPE_CLUSTER:{
154 if((ret = p_ul_dbf.query(domain->name, user, sipdomain, &h, _k, _op, _v, _c, _n, _nc, _o, _r)) < 0 || (!_r)) {
155 return -1;
156 }
157 add_res(*_r, h);
158 return ret;
159 }
160 case DB_TYPE_SINGLE: if(!domain->dbh){
161 if((d = ul_find_domain(domain->name->s)) == 0){
162 return -1;
163 }
164 if(ul_db_layer_single_connect(domain, &d->url) < 0){
165 return -1;
166 }
167 }
168 if(dbf.use_table(domain->dbh, domain->name) < 0) {
169 return -1;
170 }
171 return dbf.query(domain->dbh, _k, _op, _v, _c, _n, _nc, _o, _r);
172 default: return -1;
173 }
174 }
175
ul_db_layer_raw_query(udomain_t * domain,str * _s,db1_res_t ** _r)176 int ul_db_layer_raw_query(udomain_t * domain, str* _s, db1_res_t** _r) {
177 ul_domain_db_t * d;
178 switch(domain->dbt) {
179 case DB_TYPE_CLUSTER: {
180 return -1; // not useful in this mode
181 }
182 case DB_TYPE_SINGLE: if(!domain->dbh){
183 if((d = ul_find_domain(domain->name->s)) == 0){
184 return -1;
185 }
186 if(ul_db_layer_single_connect(domain, &d->url) < 0){
187 return -1;
188 }
189 }
190 if(dbf.use_table(domain->dbh, domain->name) < 0) {
191 return -1;
192 }
193 return dbf.raw_query(domain->dbh, _s, _r);
194 default: return -1;
195 }
196 }
197
ul_db_layer_free_result(udomain_t * domain,db1_res_t * res)198 int ul_db_layer_free_result(udomain_t * domain, db1_res_t * res) {
199 db1_con_t ** h;
200 int ret;
201 switch(domain->dbt) {
202 case DB_TYPE_CLUSTER: if((h = get_handle_by_res(res)) == NULL) {
203 return -1;
204 }
205 ret = p_ul_dbf.free_result(h, res);
206 drop_res(res);
207 return ret;
208 case DB_TYPE_SINGLE: return dbf.free_result(domain->dbh, res);
209 default: return -1;
210 }
211 }
212
ul_add_domain_db(str * d,int t,str * url)213 int ul_add_domain_db(str * d, int t, str * url) {
214 ul_domain_db_list_t * new_d = NULL;
215 LM_DBG("%.*s, type: %s\n", d->len, d->s,
216 t==DB_TYPE_SINGLE ? "SINGLE" : "CLUSTER");
217 if((new_d = pkg_malloc(sizeof(ul_domain_db_list_t))) == NULL) {
218 return -1;
219 }
220 memset(new_d, 0, sizeof(ul_domain_db_list_t));
221
222 if(!d || !d->s) goto error;
223
224 if((new_d->domain.name.s = pkg_malloc(d->len + 1)) == NULL) {
225 goto error;
226 }
227
228 if(t == DB_TYPE_SINGLE) {
229 if(url) {
230 LM_DBG("url: %.*s", url->len, url->s);
231 if((new_d->domain.url.s = pkg_malloc(url->len + 1)) == NULL) {
232 goto error;
233 }
234
235 strncpy(new_d->domain.url.s, url->s, url->len);
236 new_d->domain.url.s[url->len] = '\0';
237 new_d->domain.url.len = url->len;
238 } else {
239 if((new_d->domain.url.s = pkg_malloc(default_db_url.len + 1)) == NULL) {
240 goto error;
241 }
242 strcpy(new_d->domain.url.s, default_db_url.s);
243 new_d->domain.url.len = default_db_url.len;
244 }
245 }
246 strncpy(new_d->domain.name.s, d->s, d->len);
247 new_d->domain.name.len = d->len;
248 new_d->domain.dbt = t;
249 new_d->next = domain_db_list;
250 domain_db_list = new_d;
251 return 1;
252 error:
253 pkg_free(new_d);
254 return -1;
255 }
256
ul_find_domain(const char * s)257 ul_domain_db_t * ul_find_domain(const char * s) {
258 ul_domain_db_list_t * tmp;
259 str d;
260 if(!domain_db_list){
261 if(parse_domain_db(&domain_db) < 0){
262 LM_ERR("could not parse domain parameter.\n");
263 return NULL;
264 }
265 }
266 tmp = domain_db_list;
267 while(tmp){
268 LM_DBG("searched domain: %s, actual domain: %.*s, length: %i, type: %s\n",
269 s, tmp->domain.name.len, tmp->domain.name.s, tmp->domain.name.len,
270 tmp->domain.dbt==DB_TYPE_SINGLE ? "SINGLE" : "CLUSTER");
271 if((strlen(s) == tmp->domain.name.len) && (memcmp(s, tmp->domain.name.s, tmp->domain.name.len) == 0)){
272 return &tmp->domain;
273 }
274 tmp = tmp->next;
275 }
276 if((d.s = pkg_malloc(strlen(s) + 1)) == NULL){
277 return NULL;
278 }
279 strcpy(d.s, s);
280 d.len = strlen(s);
281 if(ul_add_domain_db(&d, default_dbt, &default_db_url)){
282 pkg_free(d.s);
283 return ul_find_domain(s);
284 }
285 pkg_free(d.s);
286 return NULL;
287 }
288
free_all_udomains(void)289 void free_all_udomains(void) {
290 ul_domain_db_list_t * tmp, * del;
291 tmp = domain_db_list;
292 while(tmp){
293 del = tmp;
294 tmp = tmp->next;
295 pkg_free(del->domain.name.s);
296 if(del->domain.dbt == DB_TYPE_SINGLE){
297 pkg_free(del->domain.url.s);
298 }
299 pkg_free(del);
300 }
301 return;
302 }
303
parse_domain_db(str * _d)304 int parse_domain_db(str * _d) {
305 #define STATE_START 0
306 #define STATE_DOMAIN 1
307 #define STATE_TYPE 2
308 #define STATE_URL 3
309 char * domains;
310 char * end;
311 str d = {NULL, 0}, u = {NULL, 0}, t = {NULL, 0};
312 int type = 0;
313 int state;
314
315 if (_d->len==0) {
316 return -1;
317 }
318 domains = _d->s;
319 end = domains + _d->len;
320
321 state = STATE_START;
322 while(domains <= end) {
323 switch(*domains) {
324 case '=':
325 switch(state) {
326 case STATE_START: return -1;
327 case STATE_DOMAIN:
328 LM_DBG("found domain %.*s\n", d.len, d.s);
329 state = STATE_TYPE;
330 t.s = domains + 1;
331 t.len = 0;
332 break;
333 case STATE_TYPE: return -1;
334 case STATE_URL: return -1;
335 default: return -1;
336 }
337 break;
338 case ';':
339 switch(state) {
340 case STATE_START: return 1;
341 case STATE_DOMAIN: return -1;
342 case STATE_TYPE:
343 LM_DBG("found type %.*s\n", t.len, t.s);
344 if(strncmp(t.s, DB_TYPE_CLUSTER_STR, strlen(DB_TYPE_CLUSTER_STR)) == 0) {
345 type = DB_TYPE_CLUSTER;
346 } else {
347 type = DB_TYPE_SINGLE;
348 }
349 state = STATE_URL;
350 u.s = domains + 1;
351 u.len = 0;
352 break;
353 case STATE_URL: return -1;
354 break;
355 default: break;
356 }
357 break;
358 case ',':
359 switch(state) {
360 case STATE_START: return -1;
361 case STATE_DOMAIN: return -1;
362 case STATE_TYPE:
363 LM_DBG("found type %.*s\n", t.len, t.s);
364 if(strncmp(t.s, DB_TYPE_CLUSTER_STR, strlen(DB_TYPE_CLUSTER_STR)) == 0) {
365 type = DB_TYPE_CLUSTER;
366 } else {
367 type = DB_TYPE_SINGLE;
368 }
369 ul_add_domain_db(&d, type, NULL);
370 state = STATE_START;
371 break;
372 case STATE_URL:
373 LM_DBG("found url %.*s\n", u.len, u.s);
374 state = STATE_START;
375 ul_add_domain_db(&d, type, &u);
376 break;
377 default: return -1;
378 }
379 break;
380 case '\0':
381 switch(state) {
382 case STATE_START:
383 return 1;
384 case STATE_DOMAIN:
385 return -1;
386 case STATE_TYPE:
387 LM_DBG("found type %.*s\n", t.len, t.s);
388 if(strncmp(t.s, DB_TYPE_CLUSTER_STR, strlen(DB_TYPE_CLUSTER_STR)) == 0) {
389 type = DB_TYPE_CLUSTER;
390 } else {
391 type = DB_TYPE_SINGLE;
392 }
393 ul_add_domain_db(&d, type, NULL);
394 return 1;
395 case STATE_URL:
396 LM_DBG("found url %.*s\n", u.len, u.s);
397 ul_add_domain_db(&d, type, &u);
398 return 1;
399 default: return -1;
400 }
401 break;
402 default:
403 switch(state) {
404 case STATE_START:
405 state = STATE_DOMAIN;
406 d.s = domains;
407 d.len = 1;
408 break;
409 case STATE_DOMAIN:
410 d.len++;
411 break;
412 case STATE_TYPE:
413 t.len++;
414 break;
415 case STATE_URL:
416 u.len++;
417 break;
418 default: break;
419 }
420 break;
421 }
422 domains++;
423 }
424 return 1;
425 }
426
add_res(db1_res_t * _r,db1_con_t ** _h)427 static void add_res(db1_res_t * _r, db1_con_t ** _h) {
428 res_list_t * new_res;
429 if(!unused) {
430 if((new_res = pkg_malloc(sizeof(res_list_t))) == NULL) {
431 return;
432 }
433 memset(new_res, 0, sizeof(res_list_t));
434 } else {
435 new_res = unused;
436 unused = unused->next;
437 }
438 new_res->h = _h;
439 new_res->r = _r;
440 new_res->next = used;
441 used = new_res;
442 return;
443 }
444
get_handle_by_res(db1_res_t * _r)445 static db1_con_t ** get_handle_by_res(db1_res_t * _r) {
446 res_list_t * tmp = used;
447 while(tmp) {
448 if(_r == tmp->r) {
449 return tmp->h;
450 }
451 tmp = tmp->next;
452 }
453 return NULL;
454 }
455
drop_res(db1_res_t * _r)456 static void drop_res(db1_res_t * _r) {
457 res_list_t * prev = NULL;
458 res_list_t * tmp;
459 tmp = used;
460 while(tmp) {
461 if(_r == tmp->r) {
462 if(prev==NULL) {
463 used = tmp->next;
464 } else {
465 prev->next = tmp->next;
466 }
467 tmp->next = unused;
468 unused = tmp;
469 return;
470 }
471 prev = tmp;
472 tmp = tmp->next;
473 }
474 return;
475 }
476
477