1 /*!
2  * \file        ast106.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/astobj2.h>
13 
14 #define ast_alloca(size) __builtin_alloca(size)
15 
16 #define sccp_sched_context_destroy sched_context_destroy
17 //#warning "HERE"
18 #if ASTERISK_VERSION_NUMBER >= 10601
19 #define pbx_channel_unref(c) ({ ao2_ref(c, -1); (PBX_CHANNEL_TYPE *) (NULL); })
20 #define pbx_channel_ref(c) ({ ao2_ref(c, 1); (PBX_CHANNEL_TYPE *) c; })
21 #else
22 #define pbx_channel_unref(c) NULL
23 #define pbx_channel_ref(c) ({(PBX_CHANNEL_TYPE *) c;})
24 #endif
25 #define NEWCONST const												// old functions used without const
26 #define OLDCONST												// new function used with const
27 
28 #define PBX_ENDPOINT_TYPE void
29 #define PBX_EVENT_SUBSCRIPTION struct ast_event_sub
30 
31 #define pbx_manager_register ast_manager_register2
32 
33 #undef pbx_channel_get_by_name
34 #define pbx_channel_get_by_name(_x) ast_get_channel_by_name_locked(_x)
35 
36 #ifndef CONFIG_STATUS_FILEMISSING
37 #define CONFIG_STATUS_FILEMISSING (void *)-2
38 #endif
39 
40 #ifndef CONFIG_STATUS_FILEINVALID
41 #define CONFIG_STATUS_FILEINVALID (void *)-2
42 #endif
43 
__do_nothing(void)44 static inline void __do_nothing(void) {}									// will be optimized out
45 
46 #undef pbx_check_hangup_locked
47 #define pbx_check_hangup_locked(_x) ({int res##__LINE__; ast_channel_lock(_x); res##__LINE__ = ast_check_hangup(_x); ast_channel_unlock(_x); (res##__LINE__);})
48 #undef pbx_bridge_lock
49 #undef pbx_bridge_unlock
50 #define pbx_bridge_lock(x) __do_nothing()
51 #define pbx_bridge_unlock(x) __do_nothing()
52 
53 enum AST_CONNECTED_LINE_UPDATE_SOURCE {
54 	/*! Update for unknown reason (May be interpreted to mean from answer) */
55 	AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN,
56 	/*! Update from normal call answering */
57 	AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER,
58 	/*! Update from call diversion (Deprecated, use REDIRECTING updates instead.) */
59 	AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION,
60 	/*! Update from call transfer(active) (Party has already answered) */
61 	AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
62 	/*! Update from call transfer(alerting) (Party has not answered yet) */
63 	AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
64 };
65 
66 #include "pbx_impl/ast/ast.h"
67 typedef int ast_format_t;
68 typedef int64_t format_t;
69 int skinny_codecs2pbx_codec_pref(const skinny_codec_t * const codecs, struct ast_codec_pref *astCodecPref);
70 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);
71 
72 //void *sccp_do_monitor(void *data);
73 //int sccp_restart_monitor(void);
74 char *pbx_getformatname(format_t format);
75 char *pbx_getformatname_multiple(char *buf, size_t size, format_t format);
76 
77 #define pbx_channel_name(x) x->name
78 
79 #ifndef DOXYGEN_SHOULD_SKIP_THIS
80 #define CLI_AMI_OUTPUT(fd, s, ...) 										\
81 	if (NULL != s) {											\
82 		astman_append(s, __VA_ARGS__);									\
83 		local_line_total++;										\
84 	} else {												\
85 		ast_cli(fd, __VA_ARGS__);									\
86 	}
87 
88 #define CLI_AMI_CAMEL_PARAM(param, camelParam)									\
89 	char *current = param;											\
90 	char *ptr = camelParam;											\
91 	int CapsNext = 0;											\
92 	while (*current) {											\
93 		if ((*current >= 48 && *current <= 57 /*num*/) || (*current >= 65 && *current <= 90 /*A-Z*/) || (*current >= 97 && *current <= 122 /*a-z*/)) {	\
94 			if (CapsNext) 	*ptr++ = toupper(*current++);						\
95 			else 		*ptr++ = *current++;							\
96 			CapsNext = 0;										\
97 		} else {											\
98 			CapsNext = 1;										\
99 			current++;										\
100 		}												\
101 	}													\
102 	*ptr='\0';
103 
104 #define CLI_AMI_OUTPUT_PARAM(param, width, fmt, ...) 								\
105 	if (NULL != s) {											\
106 		char *camelParam = pbx_strdupa(param);								\
107 		CLI_AMI_CAMEL_PARAM(param, camelParam);								\
108 		astman_append(s, "%s: " fmt "\r\n", camelParam, __VA_ARGS__);					\
109 		local_line_total++;										\
110 	} else {												\
111 		ast_cli(fd, "%-*.*s %s " fmt "\n", width, width, param, ":", __VA_ARGS__);			\
112 	}
113 
114 #define CLI_AMI_OUTPUT_BOOL(param, width, value) 								\
115 	if (NULL != s) {											\
116 		char *camelParam = pbx_strdupa(param);								\
117 		CLI_AMI_CAMEL_PARAM(param, camelParam);								\
118 		astman_append(s, "%s: %s\r\n", camelParam, ((value) ? "on" : "off"));				\
119 		local_line_total++;										\
120 	} else {												\
121 		ast_cli(fd, "%-*.*s %s %s\n", width, width, param, ":", ((value) ? "on" : "off")); 		\
122 	}
123 
124 #define CLI_AMI_OUTPUT_YES_NO(param, width, value) 								\
125 	if (NULL != s) {											\
126 		char *camelParam = pbx_strdupa(param);								\
127 		CLI_AMI_CAMEL_PARAM(param, camelParam);								\
128 		astman_append(s, "%s: %s\r\n", camelParam, ((value) ? "yes" : "no"));				\
129 		local_line_total++;										\
130 	} else {												\
131 		ast_cli(fd, "%-*.*s %s %s\n", width, width, param, ":", ((value) ? "yes" : "no")); 		\
132 	}
133 
134 #	define _CLI_AMI_RETURN_ERROR(fd, s, m, line, fmt, ...)                     \
135 		/*pbx_log(LOG_WARNING, "SCCP CLI ERROR: " fmt, __VA_ARGS__);*/      \
136 		if(NULL != s) {                                                     \
137 			char tmp_##line[101];                                       \
138 			snprintf(tmp_##line, sizeof(tmp_##line), fmt, __VA_ARGS__); \
139 			astman_send_error(s, m, tmp_##line);                        \
140 			local_line_total++;                                         \
141 		} else {                                                            \
142 			ast_cli(fd, "SCCP CLI ERROR: " fmt, __VA_ARGS__);           \
143 		}                                                                   \
144 		return RESULT_FAILURE;
145 #	define CLI_AMI_RETURN_ERROR(fd, s, m, fmt, ...) _CLI_AMI_RETURN_ERROR(fd, s, m, __LINE__, fmt, __VA_ARGS__)
146 
147 // CLI_ENTRY
148 //   param1=registration_name
149 //   param2=function to execute when called
150 //   param3=cli string to be types as array of strings
151 //   param4=registration description
152 //   param5=usage string
153 #define CLI_AMI_ENTRY(_FUNCTION_NAME,_CALLED_FUNCTION,_DESCR,_USAGE, _COMPLETER_REPEAT, _EVENTLIST)		\
154 	static int manager_ ## _FUNCTION_NAME(struct mansession *s, const struct message *m)			\
155 	{													\
156 		const char *id = astman_get_header(m, "ActionID");						\
157 		static char *cli_ami_params[] = { CLI_COMMAND, CLI_AMI_PARAMS };				\
158 		static char *arguments[ARRAY_LEN(cli_ami_params)];						\
159 		uint8_t x = 0, i = 0; 										\
160 		for (x=0; x<ARRAY_LEN(cli_ami_params); x++) {							\
161 			if(NULL != cli_ami_params[x] && strlen(cli_ami_params[x]) > 0){ 			\
162 				arguments[i++]=(char *)astman_get_header(m, cli_ami_params[x]);		 	\
163 			} 											\
164 		}												\
165 		char idtext[256] = "";										\
166 		sccp_cli_totals_t totals = {0};									\
167 		if (!pbx_strlen_zero(id)) {									\
168 			snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);				\
169 		}												\
170 		if (_EVENTLIST == TRUE) {									\
171 			astman_send_listack(s, m, AMI_COMMAND " list will follow", "start");			\
172 		}												\
173 		if (RESULT_SUCCESS==_CALLED_FUNCTION(-1, &totals, s, m, ARRAY_LEN(arguments), arguments)) {	\
174 			if (_EVENTLIST == TRUE) {								\
175 				astman_append(s,								\
176 				"Event: " AMI_COMMAND "Complete\r\n"						\
177 				"EventList: Complete\r\n"							\
178 				"ListItems: %d\r\n"								\
179 				"ListTableItems: %d\r\n"							\
180 				"%s"										\
181 				"\r\n", totals.lines, totals.tables, idtext);  				\
182 			} else {										\
183 				astman_append(s, "\r\n");							\
184 			}											\
185                 } else {											\
186                          astman_send_error(s, m, "Execution Failed\n");						\
187                 }												\
188 		return 0;											\
189 	}													\
190 														\
191 	static char * cli_ ## _FUNCTION_NAME(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) {	\
192 		char *cli_command[] = { CLI_COMMAND, NULL };							\
193 		static sccp_cli_completer_t cli_complete[] = { CLI_COMPLETE };					\
194 		static char command[80]="";									\
195 		if (cmd == CLI_INIT) {										\
196 		 	ast_join(command, sizeof(command), cli_command);					\
197 			e->command = command;									\
198 			e->usage = _USAGE;									\
199 			return NULL;										\
200 		}												\
201 		if (cmd == CLI_GENERATE) {									\
202         		uint8_t completer;									\
203 			for (completer=0; completer<ARRAY_LEN(cli_complete); completer++) {			\
204 				if ((unsigned)a->pos == (completer + ARRAY_LEN(cli_command) - 1) || _COMPLETER_REPEAT ) {\
205 					return sccp_exec_completer(cli_complete[completer], (char *)a->line, (char *)a->word, a->pos, a->n);\
206 				}										\
207 			}											\
208 			return NULL;										\
209 		}												\
210 		if (a->argc < (int)(ARRAY_LEN(cli_command)-1)) {						\
211 			return CLI_SHOWUSAGE;									\
212 		}												\
213 		static char *cli_ami_params[] = { CLI_COMMAND, CLI_AMI_PARAMS };				\
214 		struct message m = { 0 };									\
215 		size_t hdrlen; 											\
216                 for (int x = 0; x < (int)ARRAY_LEN(cli_ami_params) && x < a->argc; x++) {			\
217                         hdrlen = strlen(cli_ami_params[x]) + 2 + strlen(a->argv[x]) + 1;			\
218                         m.headers[m.hdrcount] = (const char *)sccp_malloc(hdrlen);				\
219                         snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", cli_ami_params[x], a->argv[x]);	\
220                         m.hdrcount++;                                        					\
221                 }												\
222                 int result = (_CALLED_FUNCTION)(a->fd, NULL, NULL, &m, a->argc, (char **) a->argv);		\
223                 for (int x = 0; x < (int)ARRAY_LEN(cli_ami_params) && x < a->argc; x++) {			\
224 			sccp_free(m.headers[x]);								\
225 		}												\
226 		switch (result) {										\
227 			case RESULT_SUCCESS: return CLI_SUCCESS;						\
228 			case RESULT_FAILURE: return CLI_FAILURE;						\
229 			case RESULT_SHOWUSAGE: return CLI_SHOWUSAGE;						\
230 			default: return CLI_FAILURE;								\
231 		}												\
232 	};
233 #define CLI_ENTRY(_FUNCTION_NAME,_CALLED_FUNCTION,_DESCR,_USAGE, _COMPLETER_REPEAT)				\
234 	static char *_FUNCTION_NAME(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) {			\
235 		char *cli_command[] = { CLI_COMMAND, NULL };							\
236 		static sccp_cli_completer_t cli_complete[] = { CLI_COMPLETE };					\
237 		static char command[80]="";									\
238 		if (cmd == CLI_INIT) {										\
239 		 	ast_join(command, sizeof(command), cli_command);					\
240 			e->command = command;									\
241 			e->usage = _USAGE;									\
242 			return NULL;										\
243 		}												\
244 		if (cmd == CLI_GENERATE) {									\
245                         uint8_t completer;									\
246 			for (completer=0; completer<ARRAY_LEN(cli_complete); completer++) {			\
247 				if ((unsigned)a->pos == (completer + ARRAY_LEN(cli_command) -1) || _COMPLETER_REPEAT ) {\
248 					return sccp_exec_completer(cli_complete[completer], (char *)a->line, (char *)a->word, a->pos, a->n);\
249 				}										\
250 			}											\
251 			return NULL;										\
252 		}												\
253 		if (a->argc < (int)(ARRAY_LEN(cli_command)-1)) {						\
254 			return CLI_SHOWUSAGE;									\
255 		}												\
256 		switch (_CALLED_FUNCTION(a->fd, a->argc, (char **) a->argv)) {					\
257 			case RESULT_SUCCESS: return CLI_SUCCESS;						\
258 			case RESULT_FAILURE: return CLI_FAILURE;						\
259 			case RESULT_SHOWUSAGE: return CLI_SHOWUSAGE;						\
260 			default: return CLI_FAILURE;								\
261 		}												\
262 	};
263 #endif														/* DOXYGEN_SHOULD_SKIP_THIS */
264 // 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;
265