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