55 #include "beanstalk.h"
59 static const char CONF_FILE[] =
"cel_beanstalkd.conf";
62 #define CEL_BEANSTALK_ENABLED_DEFAULT 0
67 #define CEL_SHOW_USERDEF_DEFAULT 0
69 #define CEL_BACKEND_NAME "Beanstalk Event Logging"
71 #define BEANSTALK_JOB_SIZE 4096
72 #define BEANSTALK_JOB_PRIORITY 99
73 #define BEANSTALK_JOB_TTR 60
74 #define BEANSTALK_JOB_DELAY 0
75 #define DEFAULT_BEANSTALK_HOST "127.0.0.1"
76 #define DEFAULT_BEANSTALK_PORT 11300
77 #define DEFAULT_BEANSTALK_TUBE "asterisk-cel"
84 AST_RWLOCK_DEFINE_STATIC(config_lock);
107 ast_rwlock_rdlock(&config_lock);
108 bs_socket = bs_connect(bs_host, bs_port);
110 if (bs_use(bs_socket, bs_tube) != BS_STATUS_OK) {
111 ast_log(LOG_ERROR,
"Connection to Beanstalk tube %s @ %s:%d had failed", bs_tube, bs_host, bs_port);
112 ast_rwlock_unlock(&config_lock);
117 ast_strftime(start_time,
sizeof(start_time), DATE_FORMAT, &timeresult);
119 ast_rwlock_unlock(&config_lock);
121 t_cel_json =
ast_json_pack(
"{s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s, s:s}",
122 "EventName",
S_OR(record.event_name,
""),
123 "AccountCode",
S_OR(record.account_code,
""),
124 "CallerIDnum",
S_OR(record.caller_id_num,
""),
125 "CallerIDname",
S_OR(record.caller_id_name,
""),
126 "CallerIDani",
S_OR(record.caller_id_ani,
""),
127 "CallerIDrdnis",
S_OR(record.caller_id_rdnis,
""),
128 "CallerIDdnid",
S_OR(record.caller_id_dnid,
""),
129 "Exten",
S_OR(record.extension,
""),
130 "Context",
S_OR(record.context,
""),
131 "Channel",
S_OR(record.channel_name,
""),
132 "Application",
S_OR(record.application_name,
""),
133 "AppData",
S_OR(record.application_data,
""),
134 "EventTime",
S_OR(start_time,
""),
136 "UniqueID",
S_OR(record.unique_id,
""),
137 "LinkedID",
S_OR(record.linked_id,
""),
138 "Userfield",
S_OR(record.user_field,
""),
139 "Peer",
S_OR(record.peer_account,
""),
140 "PeerAccount",
S_OR(record.peer_account,
""),
141 "Extra",
S_OR(record.extra,
"")
149 bs_id = bs_put(bs_socket, priority, BEANSTALK_JOB_DELAY, BEANSTALK_JOB_TTR, cel_buffer, strlen(cel_buffer));
152 ast_log(LOG_DEBUG,
"Successfully created job %d with %s\n", bs_id, cel_buffer);
154 ast_log(LOG_ERROR,
"CDR job creation failed for %s\n", cel_buffer);
157 bs_disconnect(bs_socket);
161 static int load_config(
int reload)
163 const char *cat = NULL;
170 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
174 if (cfg == CONFIG_STATUS_FILEINVALID) {
175 ast_log(LOG_WARNING,
"Configuration file '%s' is invalid. CEL Beanstalkd Module not activated.\n",
179 ast_log(LOG_WARNING,
"Failed to load configuration file. CEL Beanstalkd Module not activated.\n");
188 ast_rwlock_wrlock(&config_lock);
195 bs_port = DEFAULT_BEANSTALK_PORT;
197 priority = BEANSTALK_JOB_PRIORITY;
201 if (strcasecmp(cat,
"general")) {
205 for (v = ast_variable_browse(cfg, cat); v; v = v->
next) {
206 if (!strcasecmp(v->
name,
"enabled")) {
208 }
else if (!strcasecmp(v->
name,
"host")) {
211 }
else if (!strcasecmp(v->
name,
"port")) {
212 bs_port = atoi(v->
value);
213 }
else if (!strcasecmp(v->
name,
"tube")) {
216 }
else if (!strcasecmp(v->
name,
"priority")) {
217 priority = atoi(v->
value);
219 ast_log(LOG_NOTICE,
"Unknown option '%s' specified "
220 "for CEL beanstalk backend.\n", v->
name);
226 ast_rwlock_unlock(&config_lock);
231 if (enablecel && !newenablecel) {
233 }
else if (!enablecel && newenablecel) {
235 ast_log(LOG_ERROR,
"Unable to register Beanstalkd CEL handling\n");
239 enablecel = newenablecel;
244 static int unload_module(
void)
252 static int load_module(
void)
254 if (load_config(0)) {
261 static int reload(
void)
263 return load_config(1);
266 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"Beanstalkd CEL Backend",
267 .support_level = AST_MODULE_SUPPORT_EXTENDED,
269 .unload = unload_module,
struct ast_variable * next
Helper struct for getting the fields out of a CEL event.
Asterisk main include file. File version handling, generic pbx functions.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
#define CEL_BEANSTALK_ENABLED_DEFAULT
Beanstalk CEL is off by default.
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Structure for variables, used for configurations and for channel variables.
#define ast_json_dump_string(root)
Encode a JSON value to a compact string.
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
#define ast_strdup(str)
A wrapper for strdup()
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
uint32_t version
struct ABI version
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Support for logging to various files, console and syslog Configuration in file logger.conf.
Module has failed to load, may be in an inconsistent state.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
Structure used to handle boolean flags.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Abstract JSON element (object, array, string, int, ...).
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
int ast_cel_fill_record(const struct ast_event *event, struct ast_cel_event_record *r)
Fill in an ast_cel_event_record from a CEL event.