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: 124127 $")
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 if (chan)
00090 ast_autoservice_stop(chan);
00091
00092 return 0;
00093 }
00094
00095 static int function_realtime_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00096 {
00097 int res = 0;
00098 AST_DECLARE_APP_ARGS(args,
00099 AST_APP_ARG(family);
00100 AST_APP_ARG(fieldmatch);
00101 AST_APP_ARG(value);
00102 AST_APP_ARG(field);
00103 );
00104
00105 if (ast_strlen_zero(data)) {
00106 ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch,value,newcol) - missing argument!\n");
00107 return -1;
00108 }
00109
00110 if (chan)
00111 ast_autoservice_start(chan);
00112
00113 AST_STANDARD_APP_ARGS(args, data);
00114
00115 res = ast_update_realtime(args.family, args.fieldmatch, args.value, args.field, (char *)value, SENTINEL);
00116
00117 if (res < 0) {
00118 ast_log(LOG_WARNING, "Failed to update. Check the debug log for possible data repository related entries.\n");
00119 }
00120
00121 if (chan)
00122 ast_autoservice_stop(chan);
00123
00124 return 0;
00125 }
00126
00127 static int function_realtime_store(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00128 {
00129 int res = 0;
00130 char storeid[32];
00131 char *valcopy;
00132 AST_DECLARE_APP_ARGS(a,
00133 AST_APP_ARG(family);
00134 AST_APP_ARG(f)[30];
00135 );
00136
00137 AST_DECLARE_APP_ARGS(v,
00138 AST_APP_ARG(v)[30];
00139 );
00140
00141 if (ast_strlen_zero(data)) {
00142 ast_log(LOG_WARNING, "Syntax: REALTIME_STORE(family,field1,field2,...,field30) - missing argument!\n");
00143 return -1;
00144 }
00145
00146 if (chan)
00147 ast_autoservice_start(chan);
00148
00149 valcopy = ast_strdupa(value);
00150 AST_STANDARD_APP_ARGS(a, data);
00151 AST_STANDARD_APP_ARGS(v, valcopy);
00152
00153 res = ast_store_realtime(a.family,
00154 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],
00155 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],
00156 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],
00157 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],
00158 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],
00159 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
00160 );
00161
00162 if (res < 0) {
00163 ast_log(LOG_WARNING, "Failed to store. Check the debug log for possible data repository related entries.\n");
00164 } else {
00165 snprintf(storeid, sizeof(storeid), "%d", res);
00166 pbx_builtin_setvar_helper(chan, "RTSTOREID", storeid);
00167 }
00168
00169 if (chan)
00170 ast_autoservice_stop(chan);
00171
00172 return 0;
00173 }
00174
00175 static int function_realtime_readdestroy(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00176 {
00177 struct ast_variable *var, *head;
00178 struct ast_str *out;
00179 size_t resultslen;
00180 int n;
00181 AST_DECLARE_APP_ARGS(args,
00182 AST_APP_ARG(family);
00183 AST_APP_ARG(fieldmatch);
00184 AST_APP_ARG(value);
00185 AST_APP_ARG(delim1);
00186 AST_APP_ARG(delim2);
00187 );
00188
00189 if (ast_strlen_zero(data)) {
00190 ast_log(LOG_WARNING, "Syntax: REALTIME_DESTROY(family,fieldmatch[,value[,delim1[,delim2]]]) - missing argument!\n");
00191 return -1;
00192 }
00193
00194 AST_STANDARD_APP_ARGS(args, data);
00195
00196 if (!args.delim1)
00197 args.delim1 = ",";
00198 if (!args.delim2)
00199 args.delim2 = "=";
00200
00201 if (chan)
00202 ast_autoservice_start(chan);
00203
00204 head = ast_load_realtime_all(args.family, args.fieldmatch, args.value, SENTINEL);
00205
00206 if (!head) {
00207 if (chan)
00208 ast_autoservice_stop(chan);
00209 return -1;
00210 }
00211
00212 resultslen = 0;
00213 n = 0;
00214 for (var = head; var; n++, var = var->next)
00215 resultslen += strlen(var->name) + strlen(var->value);
00216
00217 resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1;
00218
00219 out = ast_str_alloca(resultslen);
00220 for (var = head; var; var = var->next) {
00221 ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1);
00222 }
00223 ast_copy_string(buf, out->str, len);
00224
00225 ast_destroy_realtime(args.family, args.fieldmatch, args.value, SENTINEL);
00226
00227 if (chan)
00228 ast_autoservice_stop(chan);
00229
00230 return 0;
00231 }
00232
00233 struct ast_custom_function realtime_function = {
00234 .name = "REALTIME",
00235 .synopsis = "RealTime Read/Write Functions",
00236 .syntax = "REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) on read\n"
00237 "REALTIME(family,fieldmatch,value,field) on write",
00238 .desc = "This function will read or write values from/to a RealTime repository.\n"
00239 "REALTIME(....) will read names/values from the repository, and \n"
00240 "REALTIME(....)= will write a new value/field to the repository. On a\n"
00241 "read, this function returns a delimited text string. The name/value \n"
00242 "pairs are delimited by delim1, and the name and value are delimited \n"
00243 "between each other with delim2. The default for delim1 is ',' and \n"
00244 "the default for delim2 is '='. If there is no match, NULL will be \n"
00245 "returned by the function. On a write, this function will always \n"
00246 "return NULL. \n",
00247 .read = function_realtime_read,
00248 .write = function_realtime_write,
00249 };
00250
00251 struct ast_custom_function realtime_store_function = {
00252 .name = "REALTIME_STORE",
00253 .synopsis = "RealTime Store Function",
00254 .syntax = "REALTIME_STORE(family,field1,field2,...,field30) = value1,value2,...,value30",
00255 .desc = "This function will insert a new set of values into the RealTime repository.\n"
00256 "If RT engine provides an unique ID of the stored record, REALTIME_STORE(...)=..\n"
00257 "creates channel variable named RTSTOREID, which contains value of unique ID.\n"
00258 "Currently, a maximum of 30 field/value pairs is supported.\n",
00259 .write = function_realtime_store,
00260 };
00261
00262 struct ast_custom_function realtime_destroy_function = {
00263 .name = "REALTIME_DESTROY",
00264 .synopsis = "RealTime Destroy Function",
00265 .syntax = "REALTIME_DESTROY(family,fieldmatch[,value[,delim1[,delim2]]])\n",
00266 .desc = "This function acts in the same way as REALTIME(....) does, except that\n"
00267 "it destroys matched record in RT engine.\n",
00268 .read = function_realtime_readdestroy,
00269 };
00270
00271 static int unload_module(void)
00272 {
00273 int res = 0;
00274 res |= ast_custom_function_unregister(&realtime_function);
00275 res |= ast_custom_function_unregister(&realtime_store_function);
00276 res |= ast_custom_function_unregister(&realtime_destroy_function);
00277 return res;
00278 }
00279
00280 static int load_module(void)
00281 {
00282 int res = 0;
00283 res |= ast_custom_function_register(&realtime_function);
00284 res |= ast_custom_function_register(&realtime_store_function);
00285 res |= ast_custom_function_register(&realtime_destroy_function);
00286 return res;
00287 }
00288
00289 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read/Write/Store/Destroy values from a RealTime repository");