1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Neal Horman <neal at wanlink dot com>
28  * Bret McDanel <trixter at 0xdecafbad dot com>
29  * Dale Thatcher <freeswitch at dalethatcher dot com>
30  * Chris Danielson <chris at maxpowersoft dot com>
31  * Rupa Schomaker <rupa@rupa.com>
32  * David Weekly <david@weekly.org>
33  * Joao Mesquita <jmesquita@gmail.com>
34  * Raymond Chandler <intralanman@freeswitch.org>
35  * Seven Du <dujinfang@gmail.com>
36  * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
37  * William King <william.king@quentustech.com>
38  *
39  * mod_conference.c -- Software Conference Bridge
40  *
41  */
42 #include <mod_conference.h>
43 
conference_utils_combine_flag_var(switch_core_session_t * session,const char * var_name)44 const char *conference_utils_combine_flag_var(switch_core_session_t *session, const char *var_name)
45 {
46 	switch_event_header_t *hp;
47 	switch_event_t *event, *cevent;
48 	char *ret = NULL;
49 	switch_channel_t *channel = switch_core_session_get_channel(session);
50 
51 	switch_core_get_variables(&event);
52 	switch_channel_get_variables(channel, &cevent);
53 	switch_event_merge(event, cevent);
54 
55 
56 	for (hp = event->headers; hp; hp = hp->next) {
57 		char *var = hp->name;
58 		char *val = hp->value;
59 
60 		if (!strcasecmp(var, var_name)) {
61 			if (hp->idx) {
62 				int i;
63 				for (i = 0; i < hp->idx; i++) {
64 					if (zstr(ret)) {
65 						ret = switch_core_session_sprintf(session, "%s", hp->array[i]);
66 					} else {
67 						ret = switch_core_session_sprintf(session, "%s|%s", ret, hp->array[i]);
68 					}
69 				}
70 			} else {
71 				if (zstr(ret)) {
72 					ret = switch_core_session_sprintf(session, "%s", val);
73 				} else {
74 					ret = switch_core_session_sprintf(session, "%s|%s", ret, val);
75 				}
76 			}
77 		} else if (!strncasecmp(var, var_name, strlen(var_name)) && switch_true(val)) {
78 			char *p = var + strlen(var_name);
79 
80 			if (*p == '_' && *(p+1)) {
81 				p++;
82 				ret = switch_core_session_sprintf(session, "%s|%s", ret, p);
83 			}
84 		}
85 	}
86 
87 
88 	switch_event_destroy(&event);
89 	switch_event_destroy(&cevent);
90 
91 	return ret;
92 
93 }
94 
conference_utils_set_mflags(const char * flags,member_flag_t * f)95 void conference_utils_set_mflags(const char *flags, member_flag_t *f)
96 {
97 	if (flags) {
98 		char *dup = strdup(flags);
99 		char *p;
100 		char *argv[10] = { 0 };
101 		int i, argc = 0;
102 
103 		f[MFLAG_CAN_SPEAK] = f[MFLAG_CAN_HEAR] = f[MFLAG_CAN_BE_SEEN] = 1;
104 
105 		for (p = dup; p && *p; p++) {
106 			if (*p == ',') {
107 				*p = '|';
108 			}
109 		}
110 
111 		argc = switch_separate_string(dup, '|', argv, (sizeof(argv) / sizeof(argv[0])));
112 
113 		for (i = 0; i < argc && argv[i]; i++) {
114 			if (!strcasecmp(argv[i], "mute")) {
115 				f[MFLAG_CAN_SPEAK] = 0;
116 				f[MFLAG_TALKING] = 0;
117             } else if (!strcasecmp(argv[i], "vmute")) {
118                 f[MFLAG_CAN_BE_SEEN] = 0;
119 			} else if (!strcasecmp(argv[i], "deaf")) {
120 				f[MFLAG_CAN_HEAR] = 0;
121 			} else if (!strcasecmp(argv[i], "blind")) {
122 				f[MFLAG_CAN_SEE] = 0;
123 			} else if (!strcasecmp(argv[i], "mute-detect")) {
124 				f[MFLAG_MUTE_DETECT] = 1;
125 			} else if (!strcasecmp(argv[i], "dist-dtmf")) {
126 				f[MFLAG_DIST_DTMF] = 1;
127 			} else if (!strcasecmp(argv[i], "moderator")) {
128 				f[MFLAG_MOD] = 1;
129 			} else if (!strcasecmp(argv[i], "nomoh")) {
130 				f[MFLAG_NOMOH] = 1;
131 			} else if (!strcasecmp(argv[i], "endconf")) {
132 				f[MFLAG_ENDCONF] = 1;
133 			} else if (!strcasecmp(argv[i], "mintwo")) {
134 				f[MFLAG_MINTWO] = 1;
135 			} else if (!strcasecmp(argv[i], "talk-data-events")) {
136 				f[MFLAG_TALK_DATA_EVENTS] = 1;
137 			} else if (!strcasecmp(argv[i], "video-bridge")) {
138 				f[MFLAG_VIDEO_BRIDGE] = 1;
139 			} else if (!strcasecmp(argv[i], "ghost")) {
140 				f[MFLAG_GHOST] = 1;
141 			} else if (!strcasecmp(argv[i], "join-only")) {
142 				f[MFLAG_JOIN_ONLY] = 1;
143 			} else if (!strcasecmp(argv[i], "flip-video")) {
144 				f[MFLAG_FLIP_VIDEO] = 1;
145 			} else if (!strcasecmp(argv[i], "positional")) {
146 				f[MFLAG_POSITIONAL] = 1;
147 			} else if (!strcasecmp(argv[i], "no-positional")) {
148 				f[MFLAG_NO_POSITIONAL] = 1;
149 			} else if (!strcasecmp(argv[i], "join-vid-floor")) {
150 				f[MFLAG_JOIN_VID_FLOOR] = 1;
151 			} else if (!strcasecmp(argv[i], "no-video-blanks")) {
152 				f[MFLAG_NO_VIDEO_BLANKS] = 1;
153 			} else if (!strcasecmp(argv[i], "no-minimize-encoding")) {
154 				f[MFLAG_NO_MINIMIZE_ENCODING] = 1;
155 			} else if (!strcasecmp(argv[i], "second-screen")) {
156 				f[MFLAG_SECOND_SCREEN] = 1;
157 				f[MFLAG_CAN_SPEAK] = 0;
158 				f[MFLAG_TALKING] = 0;
159 				f[MFLAG_CAN_HEAR] = 0;
160 				f[MFLAG_SILENT] = 1;
161 			}
162 		}
163 
164 		free(dup);
165 	}
166 }
167 
168 
169 
conference_utils_set_cflags(const char * flags,conference_flag_t * f)170 void conference_utils_set_cflags(const char *flags, conference_flag_t *f)
171 {
172 	if (flags) {
173 		char *dup = strdup(flags);
174 		char *p;
175 		char *argv[25] = { 0 };
176 		int i, argc = 0;
177 
178 		for (p = dup; p && *p; p++) {
179 			if (*p == ',') {
180 				*p = '|';
181 			}
182 		}
183 
184 		argc = switch_separate_string(dup, '|', argv, (sizeof(argv) / sizeof(argv[0])));
185 
186 		for (i = 0; i < argc && argv[i]; i++) {
187 			if (!strcasecmp(argv[i], "wait-mod")) {
188 				f[CFLAG_WAIT_MOD] = 1;
189 			} else if (!strcasecmp(argv[i], "video-floor-only")) {
190 				f[CFLAG_VID_FLOOR] = 1;
191 			} else if (!strcasecmp(argv[i], "audio-always")) {
192 				f[CFLAG_AUDIO_ALWAYS] = 1;
193 			} else if (!strcasecmp(argv[i], "restart-auto-record")) {
194 				f[CFLAG_CONF_RESTART_AUTO_RECORD] = 1;
195 			} else if (!strcasecmp(argv[i], "json-events")) {
196 				f[CFLAG_JSON_EVENTS] = 1;
197 			} else if (!strcasecmp(argv[i], "livearray-sync")) {
198 				f[CFLAG_LIVEARRAY_SYNC] = 1;
199 			} else if (!strcasecmp(argv[i], "livearray-json-status")) {
200 				f[CFLAG_JSON_STATUS] = 1;
201 			} else if (!strcasecmp(argv[i], "rfc-4579")) {
202 				f[CFLAG_RFC4579] = 1;
203 			} else if (!strcasecmp(argv[i], "auto-3d-position")) {
204 				f[CFLAG_POSITIONAL] = 1;
205 			} else if (!strcasecmp(argv[i], "minimize-video-encoding")) {
206 				f[CFLAG_MINIMIZE_VIDEO_ENCODING] = 1;
207 			} else if (!strcasecmp(argv[i], "video-bridge-first-two")) {
208 				f[CFLAG_VIDEO_BRIDGE_FIRST_TWO] = 1;
209 			} else if (!strcasecmp(argv[i], "video-required-for-canvas")) {
210 				f[CFLAG_VIDEO_REQUIRED_FOR_CANVAS] = 1;
211 			} else if (!strcasecmp(argv[i], "video-mute-exit-canvas")) {
212 				f[CFLAG_VIDEO_MUTE_EXIT_CANVAS] = 1;
213 			} else if (!strcasecmp(argv[i], "manage-inbound-video-bitrate")) {
214 				f[CFLAG_MANAGE_INBOUND_VIDEO_BITRATE] = 1;
215 			} else if (!strcasecmp(argv[i], "video-muxing-personal-canvas")) {
216 				f[CFLAG_PERSONAL_CANVAS] = 1;
217 			} else if (!strcasecmp(argv[i], "ded-vid-layer-audio-floor")) {
218 				f[CFLAG_DED_VID_LAYER_AUDIO_FLOOR] = 1;
219 			}
220 		}
221 
222 		free(dup);
223 	}
224 }
225 
226 
conference_utils_clear_eflags(char * events,uint32_t * f)227 void conference_utils_clear_eflags(char *events, uint32_t *f)
228 {
229 	char buf[512] = "";
230 	char *next = NULL;
231 	char *event = buf;
232 
233 	if (events) {
234 		switch_copy_string(buf, events, sizeof(buf));
235 
236 		while (event) {
237 			next = strchr(event, ',');
238 			if (next) {
239 				*next++ = '\0';
240 			}
241 
242 			if (!strcmp(event, "del-member")) {
243 				*f &= ~EFLAG_DEL_MEMBER;
244 			} else if (!strcmp(event, "energy-level")) {
245 				*f &= ~EFLAG_ENERGY_LEVEL;
246 			} else if (!strcmp(event, "volume-level")) {
247 				*f &= ~EFLAG_VOLUME_LEVEL;
248 			} else if (!strcmp(event, "gain-level")) {
249 				*f &= ~EFLAG_GAIN_LEVEL;
250 			} else if (!strcmp(event, "dtmf")) {
251 				*f &= ~EFLAG_DTMF;
252 			} else if (!strcmp(event, "stop-talking")) {
253 				*f &= ~EFLAG_STOP_TALKING;
254 			} else if (!strcmp(event, "start-talking")) {
255 				*f &= ~EFLAG_START_TALKING;
256 			} else if (!strcmp(event, "mute-detect")) {
257 				*f &= ~EFLAG_MUTE_DETECT;
258 			} else if (!strcmp(event, "mute-member")) {
259 				*f &= ~EFLAG_MUTE_MEMBER;
260 			} else if (!strcmp(event, "hold-member")) {
261 				*f &= ~EFLAG_HOLD_MEMBER;
262 			} else if (!strcmp(event, "kick-member")) {
263 				*f &= ~EFLAG_KICK_MEMBER;
264 			} else if (!strcmp(event, "dtmf-member")) {
265 				*f &= ~EFLAG_DTMF_MEMBER;
266 			} else if (!strcmp(event, "energy-level-member")) {
267 				*f &= ~EFLAG_ENERGY_LEVEL_MEMBER;
268 			} else if (!strcmp(event, "volume-in-member")) {
269 				*f &= ~EFLAG_VOLUME_IN_MEMBER;
270 			} else if (!strcmp(event, "volume-out-member")) {
271 				*f &= ~EFLAG_VOLUME_OUT_MEMBER;
272 			} else if (!strcmp(event, "play-file")) {
273 				*f &= ~EFLAG_PLAY_FILE;
274 			} else if (!strcmp(event, "play-file-done")) {
275 				*f &= ~EFLAG_PLAY_FILE_DONE;
276 			} else if (!strcmp(event, "play-file-member")) {
277 				*f &= ~EFLAG_PLAY_FILE_MEMBER;
278 			} else if (!strcmp(event, "speak-text")) {
279 				*f &= ~EFLAG_SPEAK_TEXT;
280 			} else if (!strcmp(event, "speak-text-member")) {
281 				*f &= ~EFLAG_SPEAK_TEXT_MEMBER;
282 			} else if (!strcmp(event, "lock")) {
283 				*f &= ~EFLAG_LOCK;
284 			} else if (!strcmp(event, "unlock")) {
285 				*f &= ~EFLAG_UNLOCK;
286 			} else if (!strcmp(event, "transfer")) {
287 				*f &= ~EFLAG_TRANSFER;
288 			} else if (!strcmp(event, "bgdial-result")) {
289 				*f &= ~EFLAG_BGDIAL_RESULT;
290 			} else if (!strcmp(event, "floor-change")) {
291 				*f &= ~EFLAG_FLOOR_CHANGE;
292 			} else if (!strcmp(event, "record")) {
293 				*f &= ~EFLAG_RECORD;
294 			}
295 
296 			event = next;
297 		}
298 	}
299 }
300 
301 
conference_utils_merge_mflags(member_flag_t * a,member_flag_t * b)302 void conference_utils_merge_mflags(member_flag_t *a, member_flag_t *b)
303 {
304 	int x;
305 
306 	for (x = 0; x < MFLAG_MAX; x++) {
307 		if (b[x]) a[x] = 1;
308 	}
309 }
310 
conference_utils_set_flag(conference_obj_t * conference,conference_flag_t flag)311 void conference_utils_set_flag(conference_obj_t *conference, conference_flag_t flag)
312 {
313 	conference->flags[flag] = 1;
314 }
conference_utils_set_flag_locked(conference_obj_t * conference,conference_flag_t flag)315 void conference_utils_set_flag_locked(conference_obj_t *conference, conference_flag_t flag)
316 {
317 	switch_mutex_lock(conference->flag_mutex);
318 	conference->flags[flag] = 1;
319 	switch_mutex_unlock(conference->flag_mutex);
320 }
conference_utils_clear_flag(conference_obj_t * conference,conference_flag_t flag)321 void conference_utils_clear_flag(conference_obj_t *conference, conference_flag_t flag)
322 {
323 	conference->flags[flag] = 0;
324 }
conference_utils_clear_flag_locked(conference_obj_t * conference,conference_flag_t flag)325 void conference_utils_clear_flag_locked(conference_obj_t *conference, conference_flag_t flag)
326 {
327 	switch_mutex_lock(conference->flag_mutex);
328 	conference->flags[flag] = 0;
329 	switch_mutex_unlock(conference->flag_mutex);
330 }
conference_utils_test_flag(conference_obj_t * conference,conference_flag_t flag)331 switch_bool_t conference_utils_test_flag(conference_obj_t *conference, conference_flag_t flag)
332 {
333 	return !!conference->flags[flag];
334 }
335 
336 #if 0
337 void conference_utils_conference_utils_set_mflag(conference_obj_t *conference, member_flag_t mflag)
338 {
339 	conference->mflags[mflag] = 1;
340 }
341 
342 void conference_utils_clear_mflag(conference_obj_t *conference, member_flag_t mflag)
343 {
344 	conference->mflags[mflag] = 0;
345 }
346 
347 switch_bool_t conference_utils_test_mflag(conference_obj_t *conference, member_flag_t mflag)
348 {
349 	return !!conference->mflags[mflag];
350 }
351 #endif
352 
conference_utils_member_set_flag(conference_member_t * member,member_flag_t flag)353 void conference_utils_member_set_flag(conference_member_t *member, member_flag_t flag)
354 {
355 	member->flags[flag] = 1;
356 
357 	if (flag == MFLAG_SECOND_SCREEN) {
358 		member->flags[MFLAG_CAN_SPEAK] = 0;
359 		member->flags[MFLAG_CAN_HEAR] = 0;
360 		member->flags[MFLAG_CAN_BE_SEEN] = 0;
361 	}
362 }
363 
conference_utils_member_set_flag_locked(conference_member_t * member,member_flag_t flag)364 void conference_utils_member_set_flag_locked(conference_member_t *member, member_flag_t flag)
365 {
366 	switch_mutex_lock(member->flag_mutex);
367 	conference_utils_member_set_flag(member, flag);
368 	switch_mutex_unlock(member->flag_mutex);
369 }
370 
check_cleared_flag(conference_member_t * member,member_flag_t flag)371 static void check_cleared_flag(conference_member_t *member, member_flag_t flag)
372 {
373 	if (flag == MFLAG_RUNNING && member->session) {
374 		switch_core_session_kill_channel(member->session, SWITCH_SIG_BREAK);
375 	}
376 }
377 
conference_utils_member_clear_flag(conference_member_t * member,member_flag_t flag)378 void conference_utils_member_clear_flag(conference_member_t *member, member_flag_t flag)
379 {
380 	member->flags[flag] = 0;
381 	check_cleared_flag(member, flag);
382 }
conference_utils_member_clear_flag_locked(conference_member_t * member,member_flag_t flag)383 void conference_utils_member_clear_flag_locked(conference_member_t *member, member_flag_t flag)
384 {
385 	switch_mutex_lock(member->flag_mutex);
386 	member->flags[flag] = 0;
387 	switch_mutex_unlock(member->flag_mutex);
388 	check_cleared_flag(member, flag);
389 }
conference_utils_member_test_flag(conference_member_t * member,member_flag_t flag)390 switch_bool_t conference_utils_member_test_flag(conference_member_t *member, member_flag_t flag)
391 {
392 	return !!member->flags[flag];
393 }
394 
395 /* For Emacs:
396  * Local Variables:
397  * mode:c
398  * indent-tabs-mode:t
399  * tab-width:4
400  * c-basic-offset:4
401  * End:
402  * For VIM:
403  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
404  */
405