00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "asterisk.h"
00028
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 206810 $")
00030
00031 #include "asterisk/file.h"
00032 #include "asterisk/channel.h"
00033 #include "asterisk/pbx.h"
00034 #include "asterisk/config.h"
00035 #include "asterisk/module.h"
00036 #include "asterisk/lock.h"
00037 #include "asterisk/utils.h"
00038 #include "asterisk/app.h"
00039
00040 static int function_realtime_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00041 {
00042 struct ast_variable *var, *head;
00043 struct ast_str *out;
00044 size_t resultslen;
00045 int n;
00046 AST_DECLARE_APP_ARGS(args,
00047 AST_APP_ARG(family);
00048 AST_APP_ARG(fieldmatch);
00049 AST_APP_ARG(value);
00050 AST_APP_ARG(delim1);
00051 AST_APP_ARG(delim2);
00052 );
00053
00054 if (ast_strlen_zero(data)) {
00055 ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) - missing argument!\n");
00056 return -1;
00057 }
00058
00059 AST_STANDARD_APP_ARGS(args, data);
00060
00061 if (!args.delim1)
00062 args.delim1 = ",";
00063 if (!args.delim2)
00064 args.delim2 = "=";
00065
00066 if (chan)
00067 ast_autoservice_start(chan);
00068
00069 head = ast_load_realtime_all(args.family, args.fieldmatch, args.value, SENTINEL);
00070
00071 if (!head) {
00072 if (chan)
00073 ast_autoservice_stop(chan);
00074 return -1;
00075 }
00076
00077 resultslen = 0;
00078 n = 0;
00079 for (var = head; var; n++, var = var->next)
00080 resultslen += strlen(var->name) + strlen(var->value);
00081
00082 resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1;
00083
00084 out = ast_str_alloca(resultslen);
00085 for (var = head; var; var = var->next)
00086 ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1);
00087 ast_copy_string(buf, out->str, len);
00088
00089 ast_variables_destroy(head);
00090
00091 if (chan)
00092 ast_autoservice_stop(chan);
00093
00094 return 0;
00095 }
00096
00097 static int function_realtime_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00098 {
00099 int res = 0;
00100 AST_DECLARE_APP_ARGS(args,
00101 AST_APP_ARG(family);
00102 AST_APP_ARG(fieldmatch);
00103 AST_APP_ARG(value);
00104 AST_APP_ARG(field);
00105 );
00106
00107 if (ast_strlen_zero(data)) {
00108 ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch,value,newcol) - missing argument!\n");
00109 return -1;
00110 }
00111
00112 if (chan)
00113 ast_autoservice_start(chan);
00114
00115 AST_STANDARD_APP_ARGS(args, data);
00116
00117 res = ast_update_realtime(args.family, args.fieldmatch, args.value, args.field, (char *)value, SENTINEL);
00118
00119 if (res < 0) {
00120 ast_log(LOG_WARNING, "Failed to update. Check the debug log for possible data repository related entries.\n");
00121 }
00122
00123 if (chan)
00124 ast_autoservice_stop(chan);
00125
00126 return 0;
00127 }
00128
00129 static int function_realtime_store(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00130 {
00131 int res = 0;
00132 char storeid[32];
00133 char *valcopy;
00134 AST_DECLARE_APP_ARGS(a,
00135 AST_APP_ARG(family);
00136 AST_APP_ARG(f)[30];
00137 );
00138
00139 AST_DECLARE_APP_ARGS(v,
00140 AST_APP_ARG(v)[30];
00141 );
00142
00143 if (ast_strlen_zero(data)) {
00144 ast_log(LOG_WARNING, "Syntax: REALTIME_STORE(family,field1,field2,...,field30) - missing argument!\n");
00145 return -1;
00146 }
00147
00148 if (chan)
00149 ast_autoservice_start(chan);
00150
00151 valcopy = ast_strdupa(value);
00152 AST_STANDARD_APP_ARGS(a, data);
00153 AST_STANDARD_APP_ARGS(v, valcopy);
00154
00155 res = ast_store_realtime(a.family,
00156 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],
00157 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],
00158 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],
00159 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],
00160 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],
00161 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
00162 );
00163
00164 if (res < 0) {
00165 ast_log(LOG_WARNING, "Failed to store. Check the debug log for possible data repository related entries.\n");
00166 } else {
00167 snprintf(storeid, sizeof(storeid), "%d", res);
00168 pbx_builtin_setvar_helper(chan, "RTSTOREID", storeid);
00169 }
00170
00171 if (chan)
00172 ast_autoservice_stop(chan);
00173
00174 return 0;
00175 }
00176
00177 static int function_realtime_readdestroy(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00178 {
00179 struct ast_variable *var, *head;
00180 struct ast_str *out;
00181 size_t resultslen;
00182 int n;
00183 AST_DECLARE_APP_ARGS(args,
00184 AST_APP_ARG(family);
00185 AST_APP_ARG(fieldmatch);
00186 AST_APP_ARG(value);
00187 AST_APP_ARG(delim1);
00188 AST_APP_ARG(delim2);
00189 );
00190
00191 if (ast_strlen_zero(data)) {
00192 ast_log(LOG_WARNING, "Syntax: REALTIME_DESTROY(family,fieldmatch[,value[,delim1[,delim2]]]) - missing argument!\n");
00193 return -1;
00194 }
00195
00196 AST_STANDARD_APP_ARGS(args, data);
00197
00198 if (!args.delim1)
00199 args.delim1 = ",";
00200 if (!args.delim2)
00201 args.delim2 = "=";
00202
00203 if (chan)
00204 ast_autoservice_start(chan);
00205
00206 head = ast_load_realtime_all(args.family, args.fieldmatch, args.value, SENTINEL);
00207
00208 if (!head) {
00209 if (chan)
00210 ast_autoservice_stop(chan);
00211 return -1;
00212 }
00213
00214 resultslen = 0;
00215 n = 0;
00216 for (var = head; var; n++, var = var->next)
00217 resultslen += strlen(var->name) + strlen(var->value);
00218
00219 resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1;
00220
00221 out = ast_str_alloca(resultslen);
00222 for (var = head; var; var = var->next) {
00223 ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1);
00224 }
00225 ast_copy_string(buf, out->str, len);
00226
00227 ast_destroy_realtime(args.family, args.fieldmatch, args.value, SENTINEL);
00228 ast_variables_destroy(head);
00229
00230 if (chan)
00231 ast_autoservice_stop(chan);
00232
00233 return 0;
00234 }
00235
00236 struct ast_custom_function realtime_function = {
00237 .name = "REALTIME",
00238 .synopsis = "RealTime Read/Write Functions",
00239 .syntax = "REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) on read\n"
00240 "REALTIME(family,fieldmatch,value,field) on write",
00241 .desc = "This function will read or write values from/to a RealTime repository.\n"
00242 "REALTIME(....) will read names/values from the repository, and \n"
00243 "REALTIME(....)= will write a new value/field to the repository. On a\n"
00244 "read, this function returns a delimited text string. The name/value \n"
00245 "pairs are delimited by delim1, and the name and value are delimited \n"
00246 "between each other with delim2. The default for delim1 is ',' and \n"
00247 "the default for delim2 is '='. If there is no match, NULL will be \n"
00248 "returned by the function. On a write, this function will always \n"
00249 "return NULL. \n",
00250 .read = function_realtime_read,
00251 .write = function_realtime_write,
00252 };
00253
00254 struct ast_custom_function realtime_store_function = {
00255 .name = "REALTIME_STORE",
00256 .synopsis = "RealTime Store Function",
00257 .syntax = "REALTIME_STORE(family,field1,field2,...,field30) = value1,value2,...,value30",
00258 .desc = "This function will insert a new set of values into the RealTime repository.\n"
00259 "If RT engine provides an unique ID of the stored record, REALTIME_STORE(...)=..\n"
00260 "creates channel variable named RTSTOREID, which contains value of unique ID.\n"
00261 "Currently, a maximum of 30 field/value pairs is supported.\n",
00262 .write = function_realtime_store,
00263 };
00264
00265 struct ast_custom_function realtime_destroy_function = {
00266 .name = "REALTIME_DESTROY",
00267 .synopsis = "RealTime Destroy Function",
00268 .syntax = "REALTIME_DESTROY(family,fieldmatch[,value[,delim1[,delim2]]])\n",
00269 .desc = "This function acts in the same way as REALTIME(....) does, except that\n"
00270 "it destroys matched record in RT engine.\n",
00271 .read = function_realtime_readdestroy,
00272 };
00273
00274 static int unload_module(void)
00275 {
00276 int res = 0;
00277 res |= ast_custom_function_unregister(&realtime_function);
00278 res |= ast_custom_function_unregister(&realtime_store_function);
00279 res |= ast_custom_function_unregister(&realtime_destroy_function);
00280 return res;
00281 }
00282
00283 static int load_module(void)
00284 {
00285 int res = 0;
00286 res |= ast_custom_function_register(&realtime_function);
00287 res |= ast_custom_function_register(&realtime_store_function);
00288 res |= ast_custom_function_register(&realtime_destroy_function);
00289 return res;
00290 }
00291
00292 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read/Write/Store/Destroy values from a RealTime repository");