REALTIME dialplan function. More...
#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
Go to the source code of this file.
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Read/Write/Store/Destroy values from a RealTime repository") | |
AST_THREADSTORAGE (buf3) | |
AST_THREADSTORAGE (buf2) | |
AST_THREADSTORAGE (buf1) | |
static int | function_realtime_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | function_realtime_readdestroy (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | function_realtime_store (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
static int | function_realtime_write (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
static int | function_realtime_writedestroy (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
Wrapper to execute REALTIME_DESTROY from a write operation. Allows execution even if live_dangerously is disabled. | |
static int | load_module (void) |
static int | realtimefield_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | unload_module (void) |
Variables | |
static struct ast_custom_function | realtime_destroy_function |
static struct ast_custom_function | realtime_function |
static struct ast_custom_function | realtime_store_function |
static struct ast_custom_function | realtimefield_function |
static struct ast_custom_function | realtimehash_function |
REALTIME dialplan function.
Definition in file func_realtime.c.
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Read/Write/Store/Destroy values from a RealTime repository" | ||||
) |
AST_THREADSTORAGE | ( | buf3 | ) |
AST_THREADSTORAGE | ( | buf2 | ) |
AST_THREADSTORAGE | ( | buf1 | ) |
static int function_realtime_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 184 of file func_realtime.c.
References args, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_load_realtime_all(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_strlen_zero(), ast_variables_destroy(), LOG_WARNING, ast_variable::next, SENTINEL, value, and var.
00185 { 00186 struct ast_variable *var, *head; 00187 struct ast_str *out; 00188 size_t resultslen; 00189 int n; 00190 AST_DECLARE_APP_ARGS(args, 00191 AST_APP_ARG(family); 00192 AST_APP_ARG(fieldmatch); 00193 AST_APP_ARG(value); 00194 AST_APP_ARG(delim1); 00195 AST_APP_ARG(delim2); 00196 ); 00197 00198 if (ast_strlen_zero(data)) { 00199 ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch[,matchvalue[,delim1[,delim2]]]) - missing argument!\n"); 00200 return -1; 00201 } 00202 00203 AST_STANDARD_APP_ARGS(args, data); 00204 00205 if (!args.delim1) 00206 args.delim1 = ","; 00207 if (!args.delim2) 00208 args.delim2 = "="; 00209 00210 if (chan) 00211 ast_autoservice_start(chan); 00212 00213 head = ast_load_realtime_all(args.family, args.fieldmatch, args.value, SENTINEL); 00214 00215 if (!head) { 00216 if (chan) 00217 ast_autoservice_stop(chan); 00218 return -1; 00219 } 00220 00221 resultslen = 0; 00222 n = 0; 00223 for (var = head; var; n++, var = var->next) 00224 resultslen += strlen(var->name) + strlen(var->value); 00225 /* add space for delimiters and final '\0' */ 00226 resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1; 00227 00228 if (resultslen > len) { 00229 ast_log(LOG_WARNING, "Failed to fetch. Realtime data is too large: need %zu, have %zu.\n", resultslen, len); 00230 return -1; 00231 } 00232 00233 /* len is going to be sensible, so we don't need to check for stack 00234 * overflows here. */ 00235 out = ast_str_alloca(resultslen); 00236 for (var = head; var; var = var->next) 00237 ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); 00238 ast_copy_string(buf, ast_str_buffer(out), len); 00239 00240 ast_variables_destroy(head); 00241 00242 if (chan) 00243 ast_autoservice_stop(chan); 00244 00245 return 0; 00246 }
static int function_realtime_readdestroy | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 411 of file func_realtime.c.
References args, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_destroy_realtime(), ast_load_realtime_all(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_strlen_zero(), ast_variables_destroy(), LOG_WARNING, ast_variable::next, SENTINEL, value, and var.
Referenced by function_realtime_writedestroy().
00412 { 00413 struct ast_variable *var, *head; 00414 struct ast_str *out; 00415 size_t resultslen; 00416 int n; 00417 AST_DECLARE_APP_ARGS(args, 00418 AST_APP_ARG(family); 00419 AST_APP_ARG(fieldmatch); 00420 AST_APP_ARG(value); 00421 AST_APP_ARG(delim1); 00422 AST_APP_ARG(delim2); 00423 ); 00424 00425 if (ast_strlen_zero(data)) { 00426 ast_log(LOG_WARNING, "Syntax: REALTIME_DESTROY(family,fieldmatch[,matchvalue[,delim1[,delim2]]]) - missing argument!\n"); 00427 return -1; 00428 } 00429 00430 AST_STANDARD_APP_ARGS(args, data); 00431 00432 if (!args.delim1) 00433 args.delim1 = ","; 00434 if (!args.delim2) 00435 args.delim2 = "="; 00436 00437 if (chan) 00438 ast_autoservice_start(chan); 00439 00440 head = ast_load_realtime_all(args.family, args.fieldmatch, args.value, SENTINEL); 00441 00442 if (!head) { 00443 if (chan) 00444 ast_autoservice_stop(chan); 00445 return -1; 00446 } 00447 00448 if (len > 0) { 00449 resultslen = 0; 00450 n = 0; 00451 for (var = head; var; n++, var = var->next) { 00452 resultslen += strlen(var->name) + strlen(var->value); 00453 } 00454 /* add space for delimiters and final '\0' */ 00455 resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1; 00456 00457 if (resultslen > len) { 00458 /* Unfortunately this does mean that we cannot destroy 00459 * the row anymore. But OTOH, we're not destroying 00460 * someones data without giving him the chance to look 00461 * at it. */ 00462 ast_log(LOG_WARNING, "Failed to fetch/destroy. Realtime data is too large: need %zu, have %zu.\n", resultslen, len); 00463 return -1; 00464 } 00465 00466 /* len is going to be sensible, so we don't need to check for 00467 * stack overflows here. */ 00468 out = ast_str_alloca(resultslen); 00469 for (var = head; var; var = var->next) { 00470 ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); 00471 } 00472 ast_copy_string(buf, ast_str_buffer(out), len); 00473 } 00474 00475 ast_destroy_realtime(args.family, args.fieldmatch, args.value, SENTINEL); 00476 ast_variables_destroy(head); 00477 00478 if (chan) 00479 ast_autoservice_stop(chan); 00480 00481 return 0; 00482 }
static int function_realtime_store | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 363 of file func_realtime.c.
References AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_store_realtime(), ast_strdupa, ast_strlen_zero(), f, LOG_WARNING, pbx_builtin_setvar_helper(), and SENTINEL.
00364 { 00365 int res = 0; 00366 char storeid[32]; 00367 char *valcopy; 00368 AST_DECLARE_APP_ARGS(a, 00369 AST_APP_ARG(family); 00370 AST_APP_ARG(f)[30]; /* fields */ 00371 ); 00372 00373 AST_DECLARE_APP_ARGS(v, 00374 AST_APP_ARG(v)[30]; /* values */ 00375 ); 00376 00377 if (ast_strlen_zero(data)) { 00378 ast_log(LOG_WARNING, "Syntax: REALTIME_STORE(family,field1,field2,...,field30) - missing argument!\n"); 00379 return -1; 00380 } 00381 00382 if (chan) 00383 ast_autoservice_start(chan); 00384 00385 valcopy = ast_strdupa(value); 00386 AST_STANDARD_APP_ARGS(a, data); 00387 AST_STANDARD_APP_ARGS(v, valcopy); 00388 00389 res = ast_store_realtime(a.family, 00390 a.f[0], v.v[0], a.f[1], v.v[1], a.f[2], v.v[2], a.f[3], v.v[3], a.f[4], v.v[4], 00391 a.f[5], v.v[5], a.f[6], v.v[6], a.f[7], v.v[7], a.f[8], v.v[8], a.f[9], v.v[9], 00392 a.f[10], v.v[10], a.f[11], v.v[11], a.f[12], v.v[12], a.f[13], v.v[13], a.f[14], v.v[14], 00393 a.f[15], v.v[15], a.f[16], v.v[16], a.f[17], v.v[17], a.f[18], v.v[18], a.f[19], v.v[19], 00394 a.f[20], v.v[20], a.f[21], v.v[21], a.f[22], v.v[22], a.f[23], v.v[23], a.f[24], v.v[24], 00395 a.f[25], v.v[25], a.f[26], v.v[26], a.f[27], v.v[27], a.f[28], v.v[28], a.f[29], v.v[29], SENTINEL 00396 ); 00397 00398 if (res < 0) { 00399 ast_log(LOG_WARNING, "Failed to store. Check the debug log for possible data repository related entries.\n"); 00400 } else { 00401 snprintf(storeid, sizeof(storeid), "%d", res); 00402 pbx_builtin_setvar_helper(chan, "RTSTOREID", storeid); 00403 } 00404 00405 if (chan) 00406 ast_autoservice_stop(chan); 00407 00408 return 0; 00409 }
static int function_realtime_write | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 248 of file func_realtime.c.
References args, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_update_realtime(), LOG_WARNING, and SENTINEL.
00249 { 00250 int res = 0; 00251 AST_DECLARE_APP_ARGS(args, 00252 AST_APP_ARG(family); 00253 AST_APP_ARG(fieldmatch); 00254 AST_APP_ARG(value); 00255 AST_APP_ARG(field); 00256 ); 00257 00258 if (ast_strlen_zero(data)) { 00259 ast_log(LOG_WARNING, "Syntax: %s(family,fieldmatch,matchvalue,updatecol) - missing argument!\n", cmd); 00260 return -1; 00261 } 00262 00263 AST_STANDARD_APP_ARGS(args, data); 00264 00265 if (ast_strlen_zero(args.fieldmatch) || ast_strlen_zero(args.field)) { 00266 ast_log(LOG_WARNING, "Syntax: %s(family,fieldmatch,matchvalue,updatecol) - missing argument!\n", cmd); 00267 return -1; 00268 } 00269 00270 if (chan) { 00271 ast_autoservice_start(chan); 00272 } 00273 00274 res = ast_update_realtime(args.family, args.fieldmatch, args.value, args.field, (char *)value, SENTINEL); 00275 00276 if (res < 0) { 00277 ast_log(LOG_WARNING, "Failed to update. Check the debug log for possible data repository related entries.\n"); 00278 } 00279 00280 if (chan) { 00281 ast_autoservice_stop(chan); 00282 } 00283 00284 return res; 00285 }
static int function_realtime_writedestroy | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Wrapper to execute REALTIME_DESTROY from a write operation. Allows execution even if live_dangerously is disabled.
Definition at line 488 of file func_realtime.c.
References function_realtime_readdestroy().
00489 { 00490 return function_realtime_readdestroy(chan, cmd, data, NULL, 0); 00491 }
static int load_module | ( | void | ) | [static] |
Definition at line 532 of file func_realtime.c.
References AST_CFE_READ, ast_custom_function_register, and ast_custom_function_register_escalating.
00533 { 00534 int res = 0; 00535 res |= ast_custom_function_register(&realtime_function); 00536 res |= ast_custom_function_register(&realtime_store_function); 00537 res |= ast_custom_function_register_escalating(&realtime_destroy_function, AST_CFE_READ); 00538 res |= ast_custom_function_register(&realtimefield_function); 00539 res |= ast_custom_function_register(&realtimehash_function); 00540 return res; 00541 }
static int realtimefield_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 287 of file func_realtime.c.
References args, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_load_realtime_all(), ast_log(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_set_escapecommas(), ast_str_thread_get(), ast_strlen_zero(), ast_variables_destroy(), first, LOG_WARNING, ast_variable::name, ast_variable::next, pbx_builtin_setvar_helper(), SENTINEL, ast_variable::value, value, and var.
00288 { 00289 struct ast_variable *var, *head; 00290 struct ast_str *escapebuf = ast_str_thread_get(&buf1, 16); 00291 struct ast_str *fields = ast_str_thread_get(&buf2, 16); 00292 struct ast_str *values = ast_str_thread_get(&buf3, 16); 00293 int first = 0; 00294 enum { rtfield, rthash } which; 00295 AST_DECLARE_APP_ARGS(args, 00296 AST_APP_ARG(family); 00297 AST_APP_ARG(fieldmatch); 00298 AST_APP_ARG(value); 00299 AST_APP_ARG(fieldname); 00300 ); 00301 00302 if (!strcmp(cmd, "REALTIME_FIELD")) { 00303 which = rtfield; 00304 } else { 00305 which = rthash; 00306 } 00307 00308 if (ast_strlen_zero(data)) { 00309 ast_log(LOG_WARNING, "Syntax: %s(family,fieldmatch,matchvalue%s) - missing argument!\n", cmd, which == rtfield ? ",fieldname" : ""); 00310 return -1; 00311 } 00312 00313 AST_STANDARD_APP_ARGS(args, data); 00314 00315 if ((which == rtfield && args.argc != 4) || (which == rthash && args.argc != 3)) { 00316 ast_log(LOG_WARNING, "Syntax: %s(family,fieldmatch,matchvalue%s) - missing argument!\n", cmd, which == rtfield ? ",fieldname" : ""); 00317 return -1; 00318 } 00319 00320 if (chan) { 00321 ast_autoservice_start(chan); 00322 } 00323 00324 if (!(head = ast_load_realtime_all(args.family, args.fieldmatch, args.value, SENTINEL))) { 00325 if (chan) { 00326 ast_autoservice_stop(chan); 00327 } 00328 return -1; 00329 } 00330 00331 ast_str_reset(fields); 00332 ast_str_reset(values); 00333 00334 for (var = head; var; var = var->next) { 00335 if (which == rtfield) { 00336 ast_debug(1, "Comparing %s to %s\n", var->name, args.fieldname); 00337 if (!strcasecmp(var->name, args.fieldname)) { 00338 ast_debug(1, "Match! Value is %s\n", var->value); 00339 ast_copy_string(buf, var->value, len); 00340 break; 00341 } 00342 } else if (which == rthash) { 00343 ast_debug(1, "Setting hash key %s to value %s\n", var->name, var->value); 00344 ast_str_append(&fields, 0, "%s%s", first ? "" : ",", ast_str_set_escapecommas(&escapebuf, 0, var->name, INT_MAX)); 00345 ast_str_append(&values, 0, "%s%s", first ? "" : ",", ast_str_set_escapecommas(&escapebuf, 0, var->value, INT_MAX)); 00346 first = 0; 00347 } 00348 } 00349 ast_variables_destroy(head); 00350 00351 if (which == rthash) { 00352 pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields)); 00353 ast_copy_string(buf, ast_str_buffer(values), len); 00354 } 00355 00356 if (chan) { 00357 ast_autoservice_stop(chan); 00358 } 00359 00360 return 0; 00361 }
static int unload_module | ( | void | ) | [static] |
Definition at line 521 of file func_realtime.c.
References ast_custom_function_unregister().
00522 { 00523 int res = 0; 00524 res |= ast_custom_function_unregister(&realtime_function); 00525 res |= ast_custom_function_unregister(&realtime_store_function); 00526 res |= ast_custom_function_unregister(&realtime_destroy_function); 00527 res |= ast_custom_function_unregister(&realtimefield_function); 00528 res |= ast_custom_function_unregister(&realtimehash_function); 00529 return res; 00530 }
struct ast_custom_function realtime_destroy_function [static] |
{ .name = "REALTIME_DESTROY", .read = function_realtime_readdestroy, .write = function_realtime_writedestroy, }
Definition at line 515 of file func_realtime.c.
struct ast_custom_function realtime_function [static] |
{ .name = "REALTIME", .read = function_realtime_read, .write = function_realtime_write, }
Definition at line 493 of file func_realtime.c.
struct ast_custom_function realtime_store_function [static] |
{ .name = "REALTIME_STORE", .write = function_realtime_store, }
Definition at line 510 of file func_realtime.c.
struct ast_custom_function realtimefield_function [static] |
{ .name = "REALTIME_FIELD", .read = realtimefield_read, .write = function_realtime_write, }
Definition at line 499 of file func_realtime.c.
struct ast_custom_function realtimehash_function [static] |
{ .name = "REALTIME_HASH", .read = realtimefield_read, }
Definition at line 505 of file func_realtime.c.