a245d92bf160b80770d0988d9e57049802466657
[asterisk/asterisk.git] / cdr / cdr_manager.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2005
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*! \file
18  *
19  * \brief Asterisk Call Manager CDR records.
20  * 
21  * See also
22  * \arg \ref AstCDR
23  * \arg \ref AstAMI
24  * \arg \ref Config_ami
25  * \ingroup cdr_drivers
26  */
27
28 #include "asterisk.h"
29
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31
32 #include <sys/types.h>
33 #include <strings.h>
34 #include <unistd.h>
35 #include <time.h>
36
37 #include "asterisk/channel.h"
38 #include "asterisk/cdr.h"
39 #include "asterisk/module.h"
40 #include "asterisk/logger.h"
41 #include "asterisk/utils.h"
42 #include "asterisk/manager.h"
43 #include "asterisk/config.h"
44 #include "asterisk/pbx.h"
45
46 #define DATE_FORMAT     "%Y-%m-%d %T"
47 #define CONF_FILE       "cdr_manager.conf"
48 #define CUSTOM_FIELDS_BUF_SIZE 1024
49
50 static char *name = "cdr_manager";
51
52 static int enablecdr = 0;
53 struct ast_str *customfields;
54
55 static int load_config(void)
56 {
57         char *cat = NULL;
58         struct ast_config *cfg;
59         struct ast_variable *v;
60         
61         customfields = NULL;
62
63         cfg = ast_config_load(CONF_FILE);
64         if (!cfg) {
65                 /* Standard configuration */
66                 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
67                 enablecdr = 0;
68                 return 0;
69         }
70         
71         while ( (cat = ast_category_browse(cfg, cat)) ) {
72                 if (!strcasecmp(cat, "general")) {
73                         v = ast_variable_browse(cfg, cat);
74                         while (v) {
75                                 if (!strcasecmp(v->name, "enabled")) {
76                                         enablecdr = ast_true(v->value);
77                                 }
78                                 
79                                 v = v->next;
80                         }
81                 } else if (!strcasecmp(cat, "mappings")) {
82                         customfields = ast_str_create(CUSTOM_FIELDS_BUF_SIZE);
83                         v = ast_variable_browse(cfg, cat);
84                         while (v) {
85                                 if (customfields && !ast_strlen_zero(v->name) && !ast_strlen_zero(v->value)) {
86                                         if( (customfields->used + strlen(v->value) + strlen(v->name) + 14) < customfields->len) {
87                                                 ast_str_append(&customfields, -1, "%s: ${CDR(%s)}\r\n", v->value, v->name);
88                                                 ast_log(LOG_NOTICE, "Added mapping %s: ${CDR(%s)}\n", v->value, v->name);
89                                         } else {
90                                                 ast_log(LOG_WARNING, "No more buffer space to add other custom fields\n");
91                                                 break;
92                                         }
93                                         
94                                 }
95                                 v = v->next;
96                         }
97                 }
98         }
99         
100         ast_config_destroy(cfg);
101         return 1;
102 }
103
104 static int manager_log(struct ast_cdr *cdr)
105 {
106         time_t t;
107         struct tm timeresult;
108         char strStartTime[80] = "";
109         char strAnswerTime[80] = "";
110         char strEndTime[80] = "";
111         char buf[CUSTOM_FIELDS_BUF_SIZE];
112         struct ast_channel dummy;
113
114         if (!enablecdr)
115                 return 0;
116
117         t = cdr->start.tv_sec;
118         ast_localtime(&t, &timeresult, NULL);
119         strftime(strStartTime, sizeof(strStartTime), DATE_FORMAT, &timeresult);
120         
121         if (cdr->answer.tv_sec) {
122                 t = cdr->answer.tv_sec;
123                 ast_localtime(&t, &timeresult, NULL);
124                 strftime(strAnswerTime, sizeof(strAnswerTime), DATE_FORMAT, &timeresult);
125         }
126
127         t = cdr->end.tv_sec;
128         ast_localtime(&t, &timeresult, NULL);
129         strftime(strEndTime, sizeof(strEndTime), DATE_FORMAT, &timeresult);
130
131         /* Custom fields handling */
132         memset(buf, 0 , sizeof(buf));
133         if (customfields != NULL && customfields->used > 0) {
134                 memset(&dummy, 0, sizeof(dummy));
135                 dummy.cdr = cdr;
136                 pbx_substitute_variables_helper(&dummy, customfields->str, buf, sizeof(buf) - 1);
137         }
138
139         manager_event(EVENT_FLAG_CALL, "Cdr",
140             "AccountCode: %s\r\n"
141             "Source: %s\r\n"
142             "Destination: %s\r\n"
143             "DestinationContext: %s\r\n"
144             "CallerID: %s\r\n"
145             "Channel: %s\r\n"
146             "DestinationChannel: %s\r\n"
147             "LastApplication: %s\r\n"
148             "LastData: %s\r\n"
149             "StartTime: %s\r\n"
150             "AnswerTime: %s\r\n"
151             "EndTime: %s\r\n"
152             "Duration: %ld\r\n"
153             "BillableSeconds: %ld\r\n"
154             "Disposition: %s\r\n"
155             "AMAFlags: %s\r\n"
156             "UniqueID: %s\r\n"
157             "UserField: %s\r\n"
158             "%s",
159             cdr->accountcode, cdr->src, cdr->dst, cdr->dcontext, cdr->clid, cdr->channel,
160             cdr->dstchannel, cdr->lastapp, cdr->lastdata, strStartTime, strAnswerTime, strEndTime,
161             cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition),
162             ast_cdr_flags2str(cdr->amaflags), cdr->uniqueid, cdr->userfield,buf);
163
164         return 0;
165 }
166
167 static int unload_module(void)
168 {
169         ast_cdr_unregister(name);
170         if (customfields)
171                 ast_free(customfields);
172
173         return 0;
174 }
175
176 static int load_module(void)
177 {
178         int res;
179
180         /* Configuration file */
181         if (!load_config())
182                 return AST_MODULE_LOAD_DECLINE;
183         
184         res = ast_cdr_register(name, "Asterisk Manager Interface CDR Backend", manager_log);
185         if (res) {
186                 ast_log(LOG_ERROR, "Unable to register Asterisk Call Manager CDR handling\n");
187         }
188         
189         return res;
190 }
191
192 static int reload(void)
193 {
194         if (customfields) {
195                 ast_free(customfields);
196         }
197         
198         load_config();
199         return 0;
200 }
201
202 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk Manager Interface CDR Backend",
203                 .load = load_module,
204                 .unload = unload_module,
205                 .reload = reload,
206                );