1 /*!
2  * \file        ast113.h
3  * \brief       SCCP PBX Asterisk Header
4  * \author      Marcello Ceshia
5  * \author      Diederik de Groot <ddegroot [at] users.sourceforge.net>
6  * \note        This program is free software and may be modified and distributed under the terms of the GNU Public License.
7  *              See the LICENSE file at the top of the source tree.
8  */
9 #pragma once
10 
11 #include "config.h"
12 #include <asterisk/format_compatibility.h>
13 
14 #include "pbx_impl/ast_announce/ast_announce.h"
15 
16 #undef pbx_channel_ref
17 #define pbx_channel_ref ast_channel_ref
18 #undef pbx_channel_unref
19 #define pbx_channel_unref ast_channel_unref
20 #define sccp_sched_context_destroy sched_context_destroy
21 
22 #define PBX_ENDPOINT_TYPE struct ast_endpoint
23 #define PBX_EVENT_SUBSCRIPTION struct stasis_subscription
24 
25 typedef struct ast_format_cap ast_format_t;
26 
27 //int skinny_codecs2pbx_codec_pref(skinny_codec_t * skinny_codecs, struct ast_codec_pref *astCodecPref);
28 int sccp_wrapper_asterisk_set_rtp_peer(PBX_CHANNEL_TYPE * ast, PBX_RTP_TYPE * rtp, PBX_RTP_TYPE * vrtp, PBX_RTP_TYPE * trtp, int codecs, int nat_active);
29 const char *pbx_getformatname(const struct ast_format *format);
30 const char *pbx_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *format);
31 
32 /* Redefinitions for asterisk-trunk, need to be sorted  */
33 #define pbx_channel_name(x) ast_channel_name(x)
34 
35 #undef CS_BRIDGEPEERNAME
36 #undef pbx_channel_uniqueid
37 #undef pbx_channel_flags
38 #undef pbx_channel_call_forward
39 #undef pbx_channel_appl
40 #undef pbx_channel_state
41 #undef pbx_channel_pbx
42 #undef pbx_channel_hangupcause
43 #undef pbx_channel_set_hangupcause
44 #undef pbx_channel_softhangup
45 #undef pbx_channel_context
46 #undef pbx_channel_nativeformats
47 #undef pbx_channel_exten
48 #undef pbx_channel_priority
49 #undef pbx_channel_macroexten
50 #undef pbx_channel_macrocontext
51 #undef pbx_channel_dialcontext
52 #undef pbx_channel_callgroup
53 #undef pbx_channel_masq
54 #undef pbx_channel_setwhentohangup_tv
55 #undef pbx_channel_blocker
56 #undef pbx_channel_blockproc
57 #undef pbx_channel_tech
58 #undef pbx_channel_bridge
59 #undef pbx_channel_set_bridge
60 #undef pbx_channel_language
61 #undef pbx_channel_language_set
62 #undef pbx_channel_cdr
63 #undef pbx_channel_call_forward_set
64 #undef pbx_channel_varshead
65 #undef pbx_channel_redirecting_effective_from
66 #undef pbx_channel_redirecting_effective_to
67 #undef pbx_channel_redirecting_effective_orig
68 #undef pbx_channel_connected_id
69 #undef pbx_channel_connected_source
70 #undef pbx_channel_monitor
71 #undef pbx_channel_string2amaflag
72 #undef pbx_channel_amaflags2string
73 #undef pbx_event_subscribe
74 #undef pbx_event_unsubscribe
75 #undef pbx_bridge_destroy
76 #undef pbx_bridge_new
77 #undef pbx_bridge_change_state
78 
79 #define CS_BRIDGEPEERNAME "DIALEDPEERNAME"
80 #define pbx_channel_uniqueid(_a) ast_channel_uniqueid(_a)
81 #define pbx_channel_flags(_a) ast_channel_flags(_a)
82 #define pbx_channel_call_forward(_a) ast_channel_call_forward(_a)
83 #define pbx_channel_appl(_a) ast_channel_appl(_a)
84 #define pbx_channel_state(_a) ast_channel_state(_a)
85 #define pbx_channel_pbx(_a) ast_channel_pbx(_a)
86 #define pbx_channel_hangupcause(_a) ast_channel_hangupcause(_a)
87 #define pbx_channel_set_hangupcause(_a, _b) ast_channel_hangupcause_set(_a, _b)
88 #define pbx_channel_softhangup(_a) ast_channel_softhangup_internal_flag(_a)
89 #define pbx_channel_set_hangupcause(_a, _b) ast_channel_hangupcause_set(_a, _b)
90 #define pbx_channel_context(_a) ast_channel_context(_a)
91 #define pbx_channel_nativeformats(_a) ast_channel_nativeformats(_a)
92 #define pbx_channel_exten(_a) ast_channel_exten(_a)
93 #define pbx_channel_priority(_a) ast_channel_priority(_a)
94 #define pbx_channel_macroexten(_a) ast_channel_macroexten(_a)
95 #define pbx_channel_macrocontext(_a) ast_channel_macrocontext(_a)
96 #define pbx_channel_dialcontext(_a) ast_channel_dialcontext(_a)
97 #define pbx_channel_callgroup(_a) ast_channel_callgroup(_a)
98 #define pbx_channel_masq(_a) ast_channel_masq(_a)
99 #define pbx_channel_setwhentohangup_tv(_a, _b) ast_channel_setwhentohangup_tv(_a, _b)
100 #define pbx_channel_blocker(_a) ast_channel_blocker(_a)
101 #define pbx_channel_blockproc(_a) ast_channel_blockproc(_a)
102 #define pbx_channel_tech(_a) ast_channel_tech(_a)
103 #define pbx_channel_bridge(_a) ast_channel_bridge(_a)
104 #define pbx_channel_set_bridge(_a, _b) ast_channel_internal_bridge_set(_a, _b)
105 #define pbx_channel_language(_a) ast_channel_language(_a)
106 #define pbx_channel_language_set(_a,_b) ast_channel_language_set(_a,_b)
107 #define pbx_channel_cdr(_a) ast_channel_cdr(_a)
108 #define pbx_channel_call_forward_set ast_channel_call_forward_set
109 #define pbx_channel_varshead(_a) ast_channel_varshead(_a)
110 #define pbx_channel_redirecting_effective_from(_a) ast_channel_redirecting_effective_from(_a)
111 #define pbx_channel_redirecting_effective_to(_a) ast_channel_redirecting_effective_to(_a)
112 #define pbx_channel_redirecting_effective_orig(_a) ast_channel_redirecting_effective_orig(_a)
113 #define pbx_channel_connected_id(_a) ast_channel_connected(_a)->id
114 #define pbx_channel_connected_source(_a) ast_channel_connected(_a)->source
115 #define pbx_channel_monitor(_a) ast_channel_monitor(_a)
116 #define pbx_channel_string2amaflag(_a) ast_channel_string2amaflag(_a)
117 #define pbx_channel_amaflags2string(_a) ast_channel_amaflags2string(_a)
118 #define pbx_event_subscribe(_a) _a = stasis_subscribe(_a)
119 #define pbx_event_unsubscribe(_a) _a = stasis_unsubscribe(_a)
120 #define pbx_bridge_destroy(_x, _y) ast_bridge_destroy(_x, _y)
121 #define pbx_bridge_new(_a, _b, _c, _d, _e) ast_bridge_base_new(_a, _b, _c, _d, _e)
122 #define AST_BRIDGE_CHANNEL_STATE_WAIT BRIDGE_CHANNEL_STATE_WAIT
123 #define pbx_bridge_change_state(_a, _b) ((_a)->state) = (_b)
124 
125 int pbx_manager_register(const char *action, int authority, int (*func) (struct mansession * s, const struct message * m), const char *synopsis, const char *description);
126 
127 #undef CS_AST_CHANNEL_PVT
128 #undef CS_AST_CHANNEL_PVT_TYPE
129 #undef CS_AST_CHANNEL_PVT_CMP_TYPE
130 
131 #define CS_AST_CHANNEL_PVT(_a) ((sccp_channel_t*)ast_channel_tech_pvt(_a))
132 #define CS_AST_CHANNEL_PVT_TYPE(_a) ast_channel_tech(_a)->type
133 #define CS_AST_CHANNEL_PVT_CMP_TYPE(_a,_b) !strncasecmp(CS_AST_CHANNEL_PVT_TYPE(_a), _b, strlen(_b))
134 
135 #define NEWCONST const												// old functions used without const
136 #define OLDCONST												// new function used with const
137 
138 #ifndef DOXYGEN_SHOULD_SKIP_THIS
139 #define CLI_AMI_OUTPUT(fd, s, ...) ({ 										\
140 	if (NULL != (s)) {											\
141 		astman_append((s), __VA_ARGS__);								\
142 		local_line_total++;										\
143 	} else {												\
144 		ast_cli((fd), __VA_ARGS__);									\
145 	}													\
146 })
147 
148 #define CLI_AMI_CAMEL_PARAM(param, camelParam) ({								\
149 	char *current = (param);										\
150 	char *ptr = (camelParam);										\
151 	int CapsNext = 0;											\
152 	while (*current) {											\
153 		if ((*current >= 48 && *current <= 57 /*num*/) || (*current >= 65 && *current <= 90 /*A-Z*/) || (*current >= 97 && *current <= 122 /*a-z*/)) {	\
154 			if (CapsNext) 	*ptr++ = toupper(*current++);						\
155 			else 		*ptr++ = *current++;							\
156 			CapsNext = 0;										\
157 		} else {											\
158 			CapsNext = 1;										\
159 			current++;										\
160 		}												\
161 	}													\
162 	*ptr='\0';												\
163 })
164 
165 #	define CLI_AMI_OUTPUT_PARAM(param, width, fmt, ...)                                                        \
166 		({                                                                                                  \
167 			if (NULL != (s)) {                                                                          \
168 				char camelParam[width + 1];                                                         \
169 				CLI_AMI_CAMEL_PARAM ((param), (camelParam));                                        \
170 				astman_append ((s), "%s: " fmt "\r\n", (camelParam), __VA_ARGS__);                  \
171 				local_line_total++;                                                                 \
172 			} else {                                                                                    \
173 				ast_cli ((fd), "%-*.*s %s " fmt "\n", (width), (width), (param), ":", __VA_ARGS__); \
174 			}                                                                                           \
175 		})
176 
177 #	define CLI_AMI_OUTPUT_BOOL(param, width, value)                                                                    \
178 		({                                                                                                          \
179 			if (NULL != (s)) {                                                                                  \
180 				char camelParam[width + 1];                                                                 \
181 				CLI_AMI_CAMEL_PARAM ((param), (camelParam));                                                \
182 				astman_append ((s), "%s: %s\r\n", (camelParam), ((value) ? "on" : "off"));                  \
183 				local_line_total++;                                                                         \
184 			} else {                                                                                            \
185 				ast_cli ((fd), "%-*.*s %s %s\n", (width), (width), (param), ":", ((value) ? "on" : "off")); \
186 			}                                                                                                   \
187 		})
188 
189 #	define CLI_AMI_OUTPUT_YES_NO(param, width, value)                                                                  \
190 		({                                                                                                          \
191 			if (NULL != (s)) {                                                                                  \
192 				char camelParam[width + 1];                                                                 \
193 				CLI_AMI_CAMEL_PARAM ((param), (camelParam));                                                \
194 				astman_append ((s), "%s: %s\r\n", (camelParam), ((value) ? "yes" : "no"));                  \
195 				local_line_total++;                                                                         \
196 			} else {                                                                                            \
197 				ast_cli ((fd), "%-*.*s %s %s\n", (width), (width), (param), ":", ((value) ? "yes" : "no")); \
198 			}                                                                                                   \
199 		})
200 
201 #	define _CLI_AMI_RETURN_ERROR(fd, s, m, line, fmt, ...)                                 \
202 		({                                                                              \
203 			if (NULL != (s)) {                                                      \
204 				char tmp_##line[101];                                           \
205 				snprintf (tmp_##line, sizeof (tmp_##line), (fmt), __VA_ARGS__); \
206 				astman_send_error ((s), (m), tmp_##line);                       \
207 				local_line_total++;                                             \
208 			} else {                                                                \
209 				ast_cli ((fd), "SCCP CLI ERROR: " fmt, __VA_ARGS__);            \
210 			}                                                                       \
211 			return RESULT_FAILURE;                                                  \
212 		})
213 #	define CLI_AMI_RETURN_ERROR(fd, s, m, fmt, ...) _CLI_AMI_RETURN_ERROR ((fd), (s), (m), __LINE__, fmt, __VA_ARGS__)
214 
215 // CLI_ENTRY
216 //   param1=registration_name
217 //   param2=function to execute when called
218 //   param3=cli string to be types as array of strings
219 //   param4=registration description
220 //   param5=usage string
221 #define CLI_AMI_ENTRY(_FUNCTION_NAME,_CALLED_FUNCTION,_DESCR,_USAGE, _COMPLETER_REPEAT, _EVENTLIST)		\
222 	static int manager_ ## _FUNCTION_NAME(struct mansession *s, const struct message *m)			\
223 	{													\
224 		const char *id = astman_get_header(m, "ActionID");						\
225 		static char *cli_ami_params[] = { CLI_COMMAND, CLI_AMI_PARAMS };				\
226 		static char *arguments[ARRAY_LEN(cli_ami_params)];						\
227 		uint8_t x = 0, i = 0; 										\
228 		for (x=0; x < ARRAY_LEN(cli_ami_params); x++) {							\
229 			if(NULL != cli_ami_params[x] && strlen(cli_ami_params[x]) > 0){				\
230 				arguments[i++]=(char *)astman_get_header(m, cli_ami_params[x]);			\
231 			}											\
232 		}												\
233 		char idtext[256] = "";										\
234 		/*int total = 0; */										\
235 		sccp_cli_totals_t totals = {0};									\
236 		if (!pbx_strlen_zero(id)) {									\
237 			snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);				\
238 		}												\
239 		if ((_EVENTLIST) == TRUE) {									\
240 			astman_send_listack(s, m, AMI_COMMAND " list will follow", "start");			\
241 		}												\
242 		if (RESULT_SUCCESS==_CALLED_FUNCTION(-1, &totals, s, m, ARRAY_LEN(arguments), arguments)) {	\
243 			if ((_EVENTLIST) == TRUE) {								\
244 				astman_append(s,								\
245 				"Event: " AMI_COMMAND "Complete\r\n"						\
246 				"EventList: Complete\r\n"							\
247 				"ListItems: %d\r\n"								\
248 				"ListTableItems: %d\r\n"							\
249 				"%s"										\
250 				"\r\n", totals.lines, totals.tables, idtext);  					\
251 			} else {										\
252 				astman_append(s, "\r\n");							\
253 			}											\
254                 } else {											\
255                         astman_send_error(s, m, "Execution Failed\n");						\
256                 }												\
257 		return 0;											\
258 	}													\
259 														\
260 	static char * cli_ ## _FUNCTION_NAME(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) {	\
261 		const char *cli_command[] = { CLI_COMMAND, NULL };						\
262 		static sccp_cli_completer_t cli_complete[] = { CLI_COMPLETE };					\
263 		static char command[80]="";									\
264 		if (cmd == CLI_INIT) {										\
265 		 	ast_join(command, sizeof(command), cli_command);					\
266 			e->command = command;									\
267 			e->usage = _USAGE;									\
268 			return NULL;										\
269 		}												\
270 		if (cmd == CLI_GENERATE) {									\
271         		uint8_t completer;									\
272 			for (completer=0; completer<ARRAY_LEN(cli_complete); completer++) {			\
273 				if ((unsigned)a->pos == (completer + ARRAY_LEN(cli_command) - 1) || (_COMPLETER_REPEAT) ) {\
274 					return sccp_exec_completer(cli_complete[completer], (char *)a->line, (char *)a->word, a->pos, a->n);\
275 				}										\
276 			}											\
277 			return NULL;										\
278 		}												\
279 		if (a->argc < (int)(ARRAY_LEN(cli_command)-1)) {						\
280 			return CLI_SHOWUSAGE;									\
281 		}												\
282 		static char *cli_ami_params[] = { CLI_COMMAND, CLI_AMI_PARAMS };				\
283 		struct message m = { 0 };									\
284 		size_t hdrlen; 											\
285                 for (int x = 0; x < (int)ARRAY_LEN(cli_ami_params) && x < a->argc; x++) {			\
286                         hdrlen = strlen(cli_ami_params[x]) + 2 + strlen(a->argv[x]) + 1;			\
287                         m.headers[m.hdrcount] = (const char *)sccp_malloc(hdrlen);				\
288                         snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", cli_ami_params[x], a->argv[x]);	\
289                         m.hdrcount++;                                        					\
290                 }												\
291                 int result = (_CALLED_FUNCTION)(a->fd, NULL, NULL, &m, a->argc, (char **) a->argv);		\
292 		for(int x = 0; (int)ARRAY_LEN(cli_ami_params) && x < a->argc; x++) { 				\
293 			sccp_free(m.headers[x]);								\
294 		}												\
295 		switch (result) {										\
296 			case RESULT_SUCCESS: return CLI_SUCCESS;						\
297 			case RESULT_FAILURE: return CLI_FAILURE;						\
298 			case RESULT_SHOWUSAGE: return CLI_SHOWUSAGE;						\
299 			default: return CLI_FAILURE;								\
300 		}												\
301 	};
302 #define CLI_ENTRY(_FUNCTION_NAME,_CALLED_FUNCTION,_DESCR,_USAGE, _COMPLETER_REPEAT)				\
303 	static char *_FUNCTION_NAME(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) {			\
304 		const char *cli_command[] = { CLI_COMMAND, NULL };						\
305 		static sccp_cli_completer_t cli_complete[] = { CLI_COMPLETE };					\
306 		static char command[80]="";									\
307 		if (cmd == CLI_INIT) {										\
308 		 	ast_join(command, sizeof(command), cli_command);					\
309 			e->command = command;									\
310 			e->usage = _USAGE;									\
311 			return NULL;										\
312 		}												\
313 		if (cmd == CLI_GENERATE) {									\
314                         uint8_t completer;									\
315 			for (completer=0; completer<ARRAY_LEN(cli_complete); completer++) {			\
316 				if ((unsigned)a->pos == (completer + ARRAY_LEN(cli_command) -1) || (_COMPLETER_REPEAT) ) {\
317 					return sccp_exec_completer(cli_complete[completer], (char *)a->line, (char *)a->word, a->pos, a->n);\
318 				}										\
319 			}											\
320 			return NULL;										\
321 		}												\
322 		if (a->argc < (int)(ARRAY_LEN(cli_command)-1)) {						\
323 			return CLI_SHOWUSAGE;									\
324 		}												\
325 		switch ((_CALLED_FUNCTION)(a->fd, a->argc, (char **) a->argv)) {				\
326 			case RESULT_SUCCESS: return CLI_SUCCESS;						\
327 			case RESULT_FAILURE: return CLI_FAILURE;						\
328 			case RESULT_SHOWUSAGE: return CLI_SHOWUSAGE;						\
329 			default: return CLI_FAILURE;								\
330 		}												\
331 	};
332 #endif														/* DOXYGEN_SHOULD_SKIP_THIS */
333 // kate: indent-width 8; replace-tabs off; indent-mode cstyle; auto-insert-doxygen on; line-numbers on; tab-indents on; keep-extra-spaces off; auto-brackets off;
334