yet another bug
[openwrt.git] / openwrt / package / asterisk / patches / asterisk-1.2.0-res_mysql.patch
1 diff -ruN asterisk-1.2.0-old/configs/res_mysql.conf.sample asterisk-1.2.0-new/configs/res_mysql.conf.sample
2 --- asterisk-1.2.0-old/configs/res_mysql.conf.sample 1970-01-01 01:00:00.000000000 +0100
3 +++ asterisk-1.2.0-new/configs/res_mysql.conf.sample 2004-12-03 15:33:44.000000000 +0100
4 @@ -0,0 +1,15 @@
5 +;
6 +; Sample configuration for res_config_mysql.c
7 +;
8 +; The value of dbhost may be either a hostname or an IP address.
9 +; If dbhost is commented out or the string "localhost", a connection
10 +; to the local host is assumed and dbsock is used instead of TCP/IP
11 +; to connect to the server.
12 +;
13 +[general]
14 +;dbhost = 127.0.0.1
15 +;dbname = asterisk
16 +;dbuser = myuser
17 +;dbpass = mypass
18 +;dbport = 3306
19 +;dbsock = /tmp/mysql.sock
20 diff -ruN asterisk-1.2.0-old/res/res_config_mysql.c asterisk-1.2.0-new/res/res_config_mysql.c
21 --- asterisk-1.2.0-old/res/res_config_mysql.c 1970-01-01 01:00:00.000000000 +0100
22 +++ asterisk-1.2.0-new/res/res_config_mysql.c 2005-10-13 21:43:54.000000000 +0200
23 @@ -0,0 +1,675 @@
24 +/*
25 + * Asterisk -- A telephony toolkit for Linux.
26 + *
27 + * Copyright (C) 1999-2005, Digium, Inc.
28 + *
29 + * Mark Spencer <markster@digium.com> - Asterisk Author
30 + * Matthew Boehm <mboehm@cytelcom.com> - MySQL RealTime Driver Author
31 + *
32 + * res_config_mysql.c <mysql plugin for RealTime configuration engine>
33 + *
34 + * v2.0 - (10-07-05) - mutex_lock fixes (bug #4973, comment #0034602)
35 + *
36 + * v1.9 - (08-19-05) - Added support to correctly honor the family database specified
37 + * in extconfig.conf (bug #4973)
38 + *
39 + * v1.8 - (04-21-05) - Modified return values of update_mysql to better indicate
40 + * what really happened.
41 + *
42 + * v1.7 - (01-28-05) - Fixed non-initialization of ast_category struct
43 + * in realtime_multi_mysql function which caused segfault.
44 + *
45 + * v1.6 - (00-00-00) - Skipped to bring comments into sync with version number in CVS.
46 + *
47 + * v1.5.1 - (01-26-05) - Added better(?) locking stuff
48 + *
49 + * v1.5 - (01-26-05) - Brought up to date with new config.h changes (bug #3406)
50 + * - Added in extra locking provided by georg (bug #3248)
51 + *
52 + * v1.4 - (12-02-04) - Added realtime_multi_mysql function
53 + * This function will return an ast_config with categories,
54 + * unlike standard realtime_mysql which only returns
55 + * a linked list of ast_variables
56 + *
57 + * v1.3 - (12-01-04) - Added support other operators
58 + * Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
59 + *
60 + * v1.2 - (11-DD-04) - Added reload. Updated load and unload.
61 + * Code beautification (doc/CODING-GUIDELINES)
62 + */
63 +
64 +#include <asterisk/channel.h>
65 +#include <asterisk/logger.h>
66 +#include <asterisk/config.h>
67 +#include <asterisk/module.h>
68 +#include <asterisk/lock.h>
69 +#include <asterisk/options.h>
70 +#include <asterisk/cli.h>
71 +#include <asterisk/utils.h>
72 +#include <stdlib.h>
73 +#include <string.h>
74 +#include <mysql.h>
75 +#include <mysql_version.h>
76 +#include <errmsg.h>
77 +
78 +static char *res_config_mysql_desc = "MySQL RealTime Configuration Driver";
79 +
80 +AST_MUTEX_DEFINE_STATIC(mysql_lock);
81 +#define RES_CONFIG_MYSQL_CONF "res_mysql.conf"
82 +MYSQL mysql;
83 +static char dbhost[50];
84 +static char dbuser[50];
85 +static char dbpass[50];
86 +static char dbname[50];
87 +static char dbsock[50];
88 +static int dbport;
89 +static int connected;
90 +static time_t connect_time;
91 +
92 +static int parse_config(void);
93 +static int mysql_reconnect(const char *database);
94 +static int realtime_mysql_status(int fd, int argc, char **argv);
95 +
96 +STANDARD_LOCAL_USER;
97 +
98 +LOCAL_USER_DECL;
99 +
100 +static char cli_realtime_mysql_status_usage[] =
101 +"Usage: realtime mysql status\n"
102 +" Shows connection information for the MySQL RealTime driver\n";
103 +
104 +static struct ast_cli_entry cli_realtime_mysql_status = {
105 + { "realtime", "mysql", "status", NULL }, realtime_mysql_status,
106 + "Shows connection information for the MySQL RealTime driver", cli_realtime_mysql_status_usage, NULL };
107 +
108 +static struct ast_variable *realtime_mysql(const char *database, const char *table, va_list ap)
109 +{
110 + MYSQL_RES *result;
111 + MYSQL_ROW row;
112 + MYSQL_FIELD *fields;
113 + int numFields, i;
114 + char sql[256];
115 + char *stringp;
116 + char *chunk;
117 + char *op;
118 + const char *newparam, *newval;
119 + struct ast_variable *var=NULL, *prev=NULL;
120 +
121 + if(!table) {
122 + ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
123 + return NULL;
124 + }
125 +
126 + /* Get the first parameter and first value in our list of passed paramater/value pairs */
127 + newparam = va_arg(ap, const char *);
128 + newval = va_arg(ap, const char *);
129 + if(!newparam || !newval) {
130 + ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
131 + mysql_close(&mysql);
132 + return NULL;
133 + }
134 +
135 + /* Create the first part of the query using the first parameter/value pairs we just extracted
136 + If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
137 +
138 + if(!strchr(newparam, ' ')) op = " ="; else op = "";
139 +
140 + snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
141 + while((newparam = va_arg(ap, const char *))) {
142 + newval = va_arg(ap, const char *);
143 + if(!strchr(newparam, ' ')) op = " ="; else op = "";
144 + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
145 + }
146 + va_end(ap);
147 +
148 + ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
149 +
150 + /* We now have our complete statement; Lets connect to the server and execute it. */
151 + ast_mutex_lock(&mysql_lock);
152 + if(!mysql_reconnect(database)) {
153 + ast_mutex_unlock(&mysql_lock);
154 + return NULL;
155 + }
156 +
157 + if(mysql_real_query(&mysql, sql, strlen(sql))) {
158 + ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
159 + ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
160 + ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
161 + ast_mutex_unlock(&mysql_lock);
162 + return NULL;
163 + }
164 +
165 + if((result = mysql_store_result(&mysql))) {
166 + numFields = mysql_num_fields(result);
167 + fields = mysql_fetch_fields(result);
168 +
169 + while((row = mysql_fetch_row(result))) {
170 + for(i = 0; i < numFields; i++) {
171 + stringp = row[i];
172 + while(stringp) {
173 + chunk = strsep(&stringp, ";");
174 + if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
175 + if(prev) {
176 + prev->next = ast_variable_new(fields[i].name, chunk);
177 + if (prev->next) {
178 + prev = prev->next;
179 + }
180 + } else {
181 + prev = var = ast_variable_new(fields[i].name, chunk);
182 + }
183 + }
184 + }
185 + }
186 + }
187 + } else {
188 + ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
189 + }
190 +
191 + ast_mutex_unlock(&mysql_lock);
192 + mysql_free_result(result);
193 +
194 + return var;
195 +}
196 +
197 +static struct ast_config *realtime_multi_mysql(const char *database, const char *table, va_list ap)
198 +{
199 + MYSQL_RES *result;
200 + MYSQL_ROW row;
201 + MYSQL_FIELD *fields;
202 + int numFields, i;
203 + char sql[256];
204 + const char *initfield = NULL;
205 + char *stringp;
206 + char *chunk;
207 + char *op;
208 + const char *newparam, *newval;
209 + struct ast_realloca ra;
210 + struct ast_variable *var=NULL;
211 + struct ast_config *cfg = NULL;
212 + struct ast_category *cat = NULL;
213 +
214 + if(!table) {
215 + ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
216 + return NULL;
217 + }
218 +
219 + memset(&ra, 0, sizeof(ra));
220 +
221 + cfg = ast_config_new();
222 + if (!cfg) {
223 + /* If I can't alloc memory at this point, why bother doing anything else? */
224 + ast_log(LOG_WARNING, "Out of memory!\n");
225 + return NULL;
226 + }
227 +
228 + /* Get the first parameter and first value in our list of passed paramater/value pairs */
229 + newparam = va_arg(ap, const char *);
230 + newval = va_arg(ap, const char *);
231 + if(!newparam || !newval) {
232 + ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
233 + mysql_close(&mysql);
234 + return NULL;
235 + }
236 +
237 + initfield = ast_strdupa(newparam);
238 + if(initfield && (op = strchr(initfield, ' '))) {
239 + *op = '\0';
240 + }
241 +
242 + /* Create the first part of the query using the first parameter/value pairs we just extracted
243 + If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
244 +
245 + if(!strchr(newparam, ' ')) op = " ="; else op = "";
246 +
247 + snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
248 + while((newparam = va_arg(ap, const char *))) {
249 + newval = va_arg(ap, const char *);
250 + if(!strchr(newparam, ' ')) op = " ="; else op = "";
251 + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
252 + }
253 +
254 + if(initfield) {
255 + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
256 + }
257 +
258 + va_end(ap);
259 +
260 + ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
261 +
262 + /* We now have our complete statement; Lets connect to the server and execute it. */
263 + ast_mutex_lock(&mysql_lock);
264 + if(!mysql_reconnect(database)) {
265 + ast_mutex_unlock(&mysql_lock);
266 + return NULL;
267 + }
268 +
269 + if(mysql_real_query(&mysql, sql, strlen(sql))) {
270 + ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
271 + ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
272 + ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
273 + ast_mutex_unlock(&mysql_lock);
274 + return NULL;
275 + }
276 +
277 + if((result = mysql_store_result(&mysql))) {
278 + numFields = mysql_num_fields(result);
279 + fields = mysql_fetch_fields(result);
280 +
281 + while((row = mysql_fetch_row(result))) {
282 + var = NULL;
283 + cat = ast_category_new("");
284 + if(!cat) {
285 + ast_log(LOG_WARNING, "Out of memory!\n");
286 + continue;
287 + }
288 + for(i = 0; i < numFields; i++) {
289 + stringp = row[i];
290 + while(stringp) {
291 + chunk = strsep(&stringp, ";");
292 + if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
293 + if(initfield && !strcmp(initfield, fields[i].name)) {
294 + ast_category_rename(cat, chunk);
295 + }
296 + var = ast_variable_new(fields[i].name, chunk);
297 + ast_variable_append(cat, var);
298 + }
299 + }
300 + }
301 + ast_category_append(cfg, cat);
302 + }
303 + } else {
304 + ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
305 + }
306 +
307 + ast_mutex_unlock(&mysql_lock);
308 + mysql_free_result(result);
309 +
310 + return cfg;
311 +}
312 +
313 +static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
314 +{
315 + my_ulonglong numrows;
316 + char sql[256];
317 + const char *newparam, *newval;
318 +
319 + if(!table) {
320 + ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
321 + return -1;
322 + }
323 +
324 + /* Get the first parameter and first value in our list of passed paramater/value pairs */
325 + newparam = va_arg(ap, const char *);
326 + newval = va_arg(ap, const char *);
327 + if(!newparam || !newval) {
328 + ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
329 + mysql_close(&mysql);
330 + return -1;
331 + }
332 +
333 + /* Create the first part of the query using the first parameter/value pairs we just extracted
334 + If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
335 +
336 + snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
337 + while((newparam = va_arg(ap, const char *))) {
338 + newval = va_arg(ap, const char *);
339 + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
340 + }
341 + va_end(ap);
342 + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);
343 +
344 + ast_log(LOG_DEBUG,"MySQL RealTime: Update SQL: %s\n", sql);
345 +
346 + /* We now have our complete statement; Lets connect to the server and execute it. */
347 + ast_mutex_lock(&mysql_lock);
348 + if(!mysql_reconnect(database)) {
349 + ast_mutex_unlock(&mysql_lock);
350 + return -1;
351 + }
352 +
353 + if(mysql_real_query(&mysql, sql, strlen(sql))) {
354 + ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
355 + ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
356 + ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
357 + ast_mutex_unlock(&mysql_lock);
358 + return -1;
359 + }
360 +
361 + numrows = mysql_affected_rows(&mysql);
362 + ast_mutex_unlock(&mysql_lock);
363 +
364 + ast_log(LOG_DEBUG,"MySQL RealTime: Updated %llu rows on table: %s\n", numrows, table);
365 +
366 + /* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
367 + * An integer greater than zero indicates the number of rows affected
368 + * Zero indicates that no records were updated
369 + * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
370 + */
371 +
372 + if(numrows >= 0)
373 + return (int)numrows;
374 +
375 + return -1;
376 +}
377 +
378 +static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg)
379 +{
380 + MYSQL_RES *result;
381 + MYSQL_ROW row;
382 + my_ulonglong num_rows;
383 + struct ast_config *new;
384 + struct ast_variable *cur_v, *new_v;
385 + struct ast_category *cur_cat, *new_cat;
386 + char sql[250] = "";
387 + char last[80] = "";
388 + int cat_started = 0;
389 + int var_started = 0;
390 + int last_cat_metric = 0;
391 +
392 + last[0] = '\0';
393 +
394 + if(!file || !strcmp(file, RES_CONFIG_MYSQL_CONF)) {
395 + ast_log(LOG_WARNING, "MySQL RealTime: Cannot configure myself.\n");
396 + return NULL;
397 + }
398 +
399 + snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
400 +
401 + ast_log(LOG_DEBUG, "MySQL RealTime: Static SQL: %s\n", sql);
402 +
403 + /* We now have our complete statement; Lets connect to the server and execute it. */
404 + ast_mutex_lock(&mysql_lock);
405 + if(!mysql_reconnect(database)) {
406 + ast_mutex_unlock(&mysql_lock);
407 + return NULL;
408 + }
409 +
410 + if(mysql_real_query(&mysql, sql, strlen(sql))) {
411 + ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
412 + ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
413 + ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
414 + ast_mutex_unlock(&mysql_lock);
415 + return NULL;
416 + }
417 +
418 + if((result = mysql_store_result(&mysql))) {
419 + num_rows = mysql_num_rows(result);
420 + ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);
421 +
422 + /* There might exist a better way to access the column names other than counting,
423 + but I believe that would require another loop that we don't need. */
424 +
425 + while((row = mysql_fetch_row(result))) {
426 + if(!strcmp(row[1], "#include")) {
427 + if (!ast_config_internal_load(row[2], cfg)) {
428 + mysql_free_result(result);
429 + ast_mutex_unlock(&mysql_lock);
430 + return NULL;
431 + }
432 + continue;
433 + }
434 +
435 + if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
436 + cur_cat = ast_category_new(row[0]);
437 + if (!cur_cat) {
438 + ast_log(LOG_WARNING, "Out of memory!\n");
439 + break;
440 + }
441 + strcpy(last, row[0]);
442 + last_cat_metric = atoi(row[3]);
443 + ast_category_append(cfg, cur_cat);
444 + }
445 + new_v = ast_variable_new(row[1], row[2]);
446 + ast_variable_append(cur_cat, new_v);
447 + }
448 + } else {
449 + ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
450 + }
451 +
452 + mysql_free_result(result);
453 + ast_mutex_unlock(&mysql_lock);
454 +
455 + return cfg;
456 +}
457 +
458 +static struct ast_config_engine mysql_engine = {
459 + .name = "mysql",
460 + .load_func = config_mysql,
461 + .realtime_func = realtime_mysql,
462 + .realtime_multi_func = realtime_multi_mysql,
463 + .update_func = update_mysql
464 +};
465 +
466 +int load_module (void)
467 +{
468 + parse_config();
469 +
470 + ast_mutex_lock(&mysql_lock);
471 +
472 + if(!mysql_reconnect(NULL)) {
473 + ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
474 + ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
475 + }
476 +
477 + ast_config_engine_register(&mysql_engine);
478 + if(option_verbose) {
479 + ast_verbose("MySQL RealTime driver loaded.\n");
480 + }
481 + ast_cli_register(&cli_realtime_mysql_status);
482 +
483 + ast_mutex_unlock(&mysql_lock);
484 +
485 + return 0;
486 +}
487 +
488 +int unload_module (void)
489 +{
490 + /* Aquire control before doing anything to the module itself. */
491 + ast_mutex_lock(&mysql_lock);
492 +
493 + mysql_close(&mysql);
494 + ast_cli_unregister(&cli_realtime_mysql_status);
495 + ast_config_engine_deregister(&mysql_engine);
496 + if(option_verbose) {
497 + ast_verbose("MySQL RealTime unloaded.\n");
498 + }
499 +
500 + STANDARD_HANGUP_LOCALUSERS;
501 +
502 + /* Unlock so something else can destroy the lock. */
503 + ast_mutex_unlock(&mysql_lock);
504 +
505 + return 0;
506 +}
507 +
508 +int reload (void)
509 +{
510 + /* Aquire control before doing anything to the module itself. */
511 + ast_mutex_lock(&mysql_lock);
512 +
513 + mysql_close(&mysql);
514 + connected = 0;
515 + parse_config();
516 +
517 + if(!mysql_reconnect(NULL)) {
518 + ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
519 + ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
520 + }
521 +
522 + ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
523 +
524 + /* Done reloading. Release lock so others can now use driver. */
525 + ast_mutex_unlock(&mysql_lock);
526 +
527 + return 0;
528 +}
529 +
530 +int parse_config (void)
531 +{
532 + struct ast_config *config;
533 + char *s;
534 +
535 + config = ast_config_load(RES_CONFIG_MYSQL_CONF);
536 +
537 + if(config) {
538 + if(!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
539 + ast_log(LOG_WARNING, "MySQL RealTime: No database user found, using 'asterisk' as default.\n");
540 + strncpy(dbuser, "asterisk", sizeof(dbuser) - 1);
541 + } else {
542 + strncpy(dbuser, s, sizeof(dbuser) - 1);
543 + }
544 +
545 + if(!(s=ast_variable_retrieve(config, "general", "dbpass"))) {
546 + ast_log(LOG_WARNING, "MySQL RealTime: No database password found, using 'asterisk' as default.\n");
547 + strncpy(dbpass, "asterisk", sizeof(dbpass) - 1);
548 + } else {
549 + strncpy(dbpass, s, sizeof(dbpass) - 1);
550 + }
551 +
552 + if(!(s=ast_variable_retrieve(config, "general", "dbhost"))) {
553 + ast_log(LOG_WARNING, "MySQL RealTime: No database host found, using localhost via socket.\n");
554 + dbhost[0] = '\0';
555 + } else {
556 + strncpy(dbhost, s, sizeof(dbhost) - 1);
557 + }
558 +
559 + if(!(s=ast_variable_retrieve(config, "general", "dbname"))) {
560 + ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
561 + strncpy(dbname, "asterisk", sizeof(dbname) - 1);
562 + } else {
563 + strncpy(dbname, s, sizeof(dbname) - 1);
564 + }
565 +
566 + if(!(s=ast_variable_retrieve(config, "general", "dbport"))) {
567 + ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
568 + dbport = 3306;
569 + } else {
570 + dbport = atoi(s);
571 + }
572 +
573 + if(dbhost && !(s=ast_variable_retrieve(config, "general", "dbsock"))) {
574 + ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
575 + strncpy(dbsock, "/tmp/mysql.sock", sizeof(dbsock) - 1);
576 + } else {
577 + strncpy(dbsock, s, sizeof(dbsock) - 1);
578 + }
579 + }
580 + ast_config_destroy(config);
581 +
582 + if(dbhost) {
583 + ast_log(LOG_DEBUG, "MySQL RealTime Host: %s\n", dbhost);
584 + ast_log(LOG_DEBUG, "MySQL RealTime Port: %i\n", dbport);
585 + } else {
586 + ast_log(LOG_DEBUG, "MySQL RealTime Socket: %s\n", dbsock);
587 + }
588 + ast_log(LOG_DEBUG, "MySQL RealTime User: %s\n", dbuser);
589 + ast_log(LOG_DEBUG, "MySQL RealTime Password: %s\n", dbpass);
590 +
591 + return 1;
592 +}
593 +
594 +char *description (void)
595 +{
596 + return res_config_mysql_desc;
597 +}
598 +
599 +int usecount (void)
600 +{
601 + /* Try and get a lock. If unsuccessful, than that means another thread is using the mysql object. */
602 + if(ast_mutex_trylock(&mysql_lock)) {
603 + ast_log(LOG_DEBUG, "MySQL RealTime: Module usage count is 1.\n");
604 + return 1;
605 + }
606 + ast_mutex_unlock(&mysql_lock);
607 + return 0;
608 +}
609 +
610 +char *key ()
611 +{
612 + return ASTERISK_GPL_KEY;
613 +}
614 +
615 +static int mysql_reconnect(const char *database)
616 +{
617 + char my_database[50];
618 +
619 + if(!database || ast_strlen_zero(database))
620 + ast_copy_string(my_database, dbname, sizeof(my_database));
621 + else
622 + ast_copy_string(my_database, database, sizeof(my_database));
623 +
624 + /* mutex lock should have been locked before calling this function. */
625 +
626 + if((!connected) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
627 + if(!mysql_init(&mysql)) {
628 + ast_log(LOG_WARNING, "MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
629 + connected = 0;
630 + return 0;
631 + }
632 + if(mysql_real_connect(&mysql, dbhost, dbuser, dbpass, my_database, dbport, dbsock, 0)) {
633 + ast_log(LOG_DEBUG, "MySQL RealTime: Successfully connected to database.\n");
634 + connected = 1;
635 + connect_time = time(NULL);
636 + return 1;
637 + } else {
638 + ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", dbname, dbhost);
639 + ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
640 + connected = 0;
641 + return 0;
642 + }
643 + } else {
644 + if(mysql_ping(&mysql) != 0) {
645 + connected = 0;
646 + ast_log(LOG_ERROR, "MySQL RealTime: Failed to reconnect. Check debug for more info.\n");
647 + ast_log(LOG_DEBUG, "MySQL RealTime: Server Error: %s\n", mysql_error(&mysql));
648 + return 0;
649 + }
650 +
651 + connected = 1;
652 +
653 + if(mysql_select_db(&mysql, my_database) != 0) {
654 + ast_log(LOG_WARNING, "MySQL RealTime: Unable to select database: %s. Still Connected.\n", my_database);
655 + ast_log(LOG_DEBUG, "MySQL RealTime: Database Select Failed: %s\n", mysql_error(&mysql));
656 + return 0;
657 + }
658 +
659 + ast_log(LOG_DEBUG, "MySQL RealTime: Everything is fine.\n");
660 + return 1;
661 + }
662 +}
663 +
664 +static int realtime_mysql_status(int fd, int argc, char **argv)
665 +{
666 + char status[256], status2[100] = "";
667 + int ctime = time(NULL) - connect_time;
668 +
669 + if(mysql_reconnect(NULL)) {
670 + if(dbhost) {
671 + snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
672 + } else if(dbsock) {
673 + snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
674 + } else {
675 + snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
676 + }
677 +
678 + if(dbuser && *dbuser) {
679 + snprintf(status2, 99, " with username %s", dbuser);
680 + }
681 +
682 + if (ctime > 31536000) {
683 + ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
684 + } else if (ctime > 86400) {
685 + ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
686 + } else if (ctime > 3600) {
687 + ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
688 + } else if (ctime > 60) {
689 + ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
690 + } else {
691 + ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
692 + }
693 +
694 + return RESULT_SUCCESS;
695 + } else {
696 + return RESULT_FAILURE;
697 + }
698 +}
This page took 0.104688 seconds and 5 git commands to generate.