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