Exemple #1
0
/************************************************************
 * Read data from ring buffer.
 * Will not return until all the data has been read.
 */
long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer)
{
	long bytesRead = 0;
	char *p = (char *) data;
	long avail, totalBytes = 0, neededBytes = aStream->bytesPerFrame * numFrames;
	int max = 5000;

	switch_core_timer_next(timer);

	while (totalBytes < neededBytes && --max > 0) {

		avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[chan]);
		//printf("AVAILABLE BYTES %ld pass %d\n", avail, 5000 - max);
		if (avail >= neededBytes * 6) {
			PaUtil_FlushRingBuffer(&aStream->inFIFOs[chan]);
			avail = 0;
		} else {

			bytesRead = 0;

			if (totalBytes < neededBytes && avail >= neededBytes) {
				bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFOs[chan], p, neededBytes);
				totalBytes += bytesRead;
			}

			if (bytesRead) {
				p += bytesRead;
			} else {
				switch_cond_next();
			}
		}
	}

	return totalBytes / aStream->bytesPerFrame;
}
Exemple #2
0
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
    switch_channel_t *channel = NULL;
    private_t *tech_pvt = NULL;
    //switch_time_t started = switch_time_now();
    //unsigned int elapsed;
    switch_byte_t *data;

    channel = switch_core_session_get_channel(session);
    assert(channel != NULL);

    tech_pvt = switch_core_session_get_private(session);
    assert(tech_pvt != NULL);
    tech_pvt->read_frame.flags = SFF_NONE;
    *frame = NULL;

    while (switch_test_flag(tech_pvt, TFLAG_IO)) {

        if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
            switch_clear_flag(tech_pvt, TFLAG_BREAK);
            goto cng;
        }

        if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
            return SWITCH_STATUS_FALSE;
        }

        if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
            switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
            if (!tech_pvt->read_frame.datalen) {
                continue;
            }
            *frame = &tech_pvt->read_frame;
#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
            if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
                switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
            }
#endif
            return SWITCH_STATUS_SUCCESS;
        }

        switch_cond_next();
    }


    return SWITCH_STATUS_FALSE;

cng:
    data = (switch_byte_t *) tech_pvt->read_frame.data;
    data[0] = 65;
    data[1] = 0;
    tech_pvt->read_frame.datalen = 2;
    tech_pvt->read_frame.flags = SFF_CNG;
    *frame = &tech_pvt->read_frame;
    return SWITCH_STATUS_SUCCESS;

}
Exemple #3
0
static void switch_channel_wait_for_state_or_greater(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
{

	switch_assert(channel);
	
	for (;;) {
		if ((switch_channel_get_state(channel) < CS_HANGUP && 
			 switch_channel_get_state(channel) == switch_channel_get_running_state(channel) && switch_channel_get_running_state(channel) >= want_state) ||
			(other_channel && switch_channel_down_nosig(other_channel)) || switch_channel_down(channel)) {
			break;
		}
		switch_cond_next();
	}
}
Exemple #4
0
SWITCH_DECLARE(switch_status_t) switch_log_shutdown(void)
{
	switch_status_t st;

	THREAD_RUNNING = -1;
	switch_queue_push(LOG_QUEUE, NULL);
	while (THREAD_RUNNING) {
		switch_cond_next();
	}

	switch_thread_join(&st, thread);

	switch_core_memory_reclaim_logger();

	return SWITCH_STATUS_SUCCESS;
}
Exemple #5
0
SWITCH_DECLARE(switch_status_t) switch_log_init(switch_memory_pool_t *pool, switch_bool_t colorize)
{
	switch_threadattr_t *thd_attr;;

	switch_assert(pool != NULL);

	LOG_POOL = pool;

	switch_threadattr_create(&thd_attr, LOG_POOL);
	switch_threadattr_detach_set(thd_attr, 1);


	switch_queue_create(&LOG_QUEUE, SWITCH_CORE_QUEUE_LEN, LOG_POOL);
#ifdef SWITCH_LOG_RECYCLE
	switch_queue_create(&LOG_RECYCLE_QUEUE, SWITCH_CORE_QUEUE_LEN, LOG_POOL);
#endif
	switch_mutex_init(&BINDLOCK, SWITCH_MUTEX_NESTED, LOG_POOL);
	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
	switch_thread_create(&thread, thd_attr, log_thread, NULL, LOG_POOL);

	while (!THREAD_RUNNING) {
		switch_cond_next();
	}

	if (colorize) {
#ifdef WIN32
		hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
		if (switch_core_get_console() == stdout && hStdout != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) {
			wOldColorAttrs = csbiInfo.wAttributes;
			COLORIZE = SWITCH_TRUE;
		}
#else
		COLORIZE = SWITCH_TRUE;
#endif
	}


	return SWITCH_STATUS_SUCCESS;
}
void do_telecast(switch_stream_handle_t *stream)
{
	char *path_info = switch_event_get_header(stream->param_event, "http-path-info");
	char *uuid = strdup(path_info + 4);
	switch_core_session_t *tsession;
	char *fname = "stream.mp3";

	if ((fname = strchr(uuid, '/'))) {
		*fname++ = '\0';
	}

	if (!(tsession = switch_core_session_locate(uuid))) {
		char *ref = switch_event_get_header(stream->param_event, "http-referer");
		stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>Not Found!</h2>\n" "<META http-equiv=\"refresh\" content=\"1;URL=%s\">", ref);
	} else {
		switch_media_bug_t *bug = NULL;
		switch_buffer_t *buffer = NULL;
		switch_mutex_t *mutex;
		switch_channel_t *channel = switch_core_session_get_channel(tsession);
		lame_global_flags *gfp = NULL;
		switch_codec_implementation_t read_impl = { 0 };
		switch_core_session_get_read_impl(tsession, &read_impl);

		if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stepping into media path so this will work!\n");
			switch_ivr_media(uuid, SMF_REBRIDGE);
		}

		if (!(gfp = lame_init())) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
			goto end;
		}
		lame_set_num_channels(gfp, read_impl.number_of_channels);
		lame_set_in_samplerate(gfp, read_impl.actual_samples_per_second);
		lame_set_brate(gfp, 16 * (read_impl.actual_samples_per_second / 8000) * read_impl.number_of_channels);
		lame_set_mode(gfp, 3);
		lame_set_quality(gfp, 2);
		lame_set_errorf(gfp, log_error);
		lame_set_debugf(gfp, log_debug);
		lame_set_msgf(gfp, log_msg);
		lame_set_bWriteVbrTag(gfp, 0);
		lame_mp3_tags_fid(gfp, NULL);
		lame_init_params(gfp);
		lame_print_config(gfp);

		switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
		switch_buffer_create_dynamic(&buffer, 1024, 2048, 0);
		switch_buffer_add_mutex(buffer, mutex);

		if (switch_core_media_bug_add(tsession, "telecast", NULL,
									  telecast_callback, buffer, 0,
									  SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING, &bug) != SWITCH_STATUS_SUCCESS) {
			goto end;
		}

		stream->write_function(stream, "Content-type: audio/mpeg\r\n" "Content-Disposition: inline; filename=\"%s\"\r\n\r\n", fname);

		while (switch_channel_ready(channel)) {
			unsigned char mp3buf[TC_BUFFER_SIZE] = "";
			int rlen;
			uint8_t buf[1024];
			switch_size_t bytes = 0;

			if (switch_buffer_inuse(buffer) >= 1024) {
				switch_buffer_lock(buffer);
				bytes = switch_buffer_read(buffer, buf, sizeof(buf));
				switch_buffer_unlock(buffer);
			} else {
				if (!bytes) {
					switch_cond_next();
					continue;
				}
				memset(buf, 0, bytes);
			}

			if ((rlen = lame_encode_buffer(gfp, (void *) buf, NULL, bytes / 2, mp3buf, sizeof(mp3buf))) < 0) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
				goto end;
			}

			if (rlen) {
				if (stream->raw_write_function(stream, mp3buf, rlen)) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n");
					goto end;
				}
			}
		}

	  end:

		switch_safe_free(uuid);

		if (gfp) {
			lame_close(gfp);
			gfp = NULL;
		}

		if (bug) {
			switch_core_media_bug_remove(tsession, &bug);
		}

		if (buffer) {
			switch_buffer_destroy(&buffer);
		}

		switch_core_session_rwunlock(tsession);
	}
}
Exemple #7
0
SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
															   int stream_id)
{
	switch_io_event_hook_read_frame_t *ptr;
	switch_status_t status = SWITCH_STATUS_FALSE;
	int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0;
	switch_codec_implementation_t codec_impl;
	unsigned int flag = 0;

	switch_assert(session != NULL);


	if (switch_mutex_trylock(session->codec_read_mutex) == SWITCH_STATUS_SUCCESS) {
		switch_mutex_unlock(session->codec_read_mutex);
	} else {
		switch_cond_next();
		*frame = &runtime.dummy_cng_frame;
		return SWITCH_STATUS_SUCCESS;
	}

	if (!(session->read_codec && session->read_codec->implementation && switch_core_codec_ready(session->read_codec))) {
		if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_get_state(session->channel) == CS_HIBERNATE) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s reading on a session with no media!\n",
							  switch_channel_get_name(session->channel));
			switch_cond_next();
			*frame = &runtime.dummy_cng_frame;
			return SWITCH_STATUS_SUCCESS;
		}
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
		switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
		return SWITCH_STATUS_FALSE;
	}

	switch_mutex_lock(session->codec_read_mutex);

	if (!switch_core_codec_ready(session->read_codec)) {
		switch_mutex_unlock(session->codec_read_mutex);
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
		switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
		*frame = &runtime.dummy_cng_frame;
        return SWITCH_STATUS_FALSE;
	}

	switch_mutex_lock(session->read_codec->mutex);

  top:
	
	if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) {
		switch_ivr_dmachine_ping(session->dmachine, NULL);
	}
	
	if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) {
		*frame = NULL;
		status = SWITCH_STATUS_FALSE;
		goto even_more_done;
	}


	status = SWITCH_STATUS_FALSE;
	need_codec = perfect = 0;

	*frame = NULL;

	if (session->read_codec && !session->track_id && session->track_duration) {
		if (session->read_frame_count == 0) {
			switch_event_t *event;
			session->read_frame_count = (session->read_impl.actual_samples_per_second / session->read_impl.samples_per_packet) * session->track_duration;

			switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT);
			switch_channel_event_set_data(session->channel, event);
			switch_event_fire(&event);
		} else {
			session->read_frame_count--;
		}
	}


	if (switch_channel_test_flag(session->channel, CF_HOLD)) {
		switch_yield(session->read_impl.microseconds_per_packet);
		status = SWITCH_STATUS_BREAK;
		goto even_more_done;
	}

	if (session->endpoint_interface->io_routines->read_frame) {
		switch_mutex_unlock(session->read_codec->mutex);
		switch_mutex_unlock(session->codec_read_mutex);
		if ((status = session->endpoint_interface->io_routines->read_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
			for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) {
				if ((status = ptr->read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
					break;
				}
			}
		}

		if (!SWITCH_READ_ACCEPTABLE(status) || !session->read_codec || !switch_core_codec_ready(session->read_codec)) {
			*frame = NULL;
			return SWITCH_STATUS_FALSE;
		}

		switch_mutex_lock(session->codec_read_mutex);

		if (!switch_core_codec_ready(session->read_codec)) {
			switch_mutex_unlock(session->codec_read_mutex);
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
			switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
			*frame = &runtime.dummy_cng_frame;
			return SWITCH_STATUS_FALSE;
		}

		switch_mutex_lock(session->read_codec->mutex);
		if (!switch_core_codec_ready(session->read_codec)) {
			*frame = NULL;
			status = SWITCH_STATUS_FALSE;
			goto even_more_done;			
		}

	}

	if (status != SWITCH_STATUS_SUCCESS) {
		goto done;
	}

	if (!(*frame)) {
		goto done;
	}

	switch_assert(*frame != NULL);

	if (switch_test_flag(*frame, SFF_PROXY_PACKET)) {
		/* Fast PASS! */
		status = SWITCH_STATUS_SUCCESS;
		goto done;
	}

	if (switch_test_flag(*frame, SFF_CNG)) {
		status = SWITCH_STATUS_SUCCESS;
		if (!session->bugs && !session->plc) {
			goto done;
		}
		is_cng = 1;
	}

	switch_assert((*frame)->codec != NULL);

	if (!(session->read_codec && (*frame)->codec && (*frame)->codec->implementation) && switch_core_codec_ready((*frame)->codec)) {
		status = SWITCH_STATUS_FALSE;
		goto done;
	}

	codec_impl = *(*frame)->codec->implementation;

	if (session->read_codec->implementation->impl_id != codec_impl.impl_id) {
		need_codec = TRUE;
	} 
	
	if (codec_impl.actual_samples_per_second != session->read_impl.actual_samples_per_second) {
		do_resample = 1;
	}

	if (session->bugs && !need_codec) {
		do_bugs = 1;
		need_codec = 1;
	}

	if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) {
		switch_core_session_t *other_session;
		const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE);
		switch_clear_flag(session, SSF_READ_TRANSCODE);
		
		if (uuid && (other_session = switch_core_session_locate(uuid))) {
			switch_set_flag(other_session, SSF_READ_CODEC_RESET);
			switch_set_flag(other_session, SSF_READ_CODEC_RESET);
			switch_set_flag(other_session, SSF_WRITE_CODEC_RESET);
			switch_core_session_rwunlock(other_session);
		}
	}

	if (switch_test_flag(session, SSF_READ_CODEC_RESET)) {
		switch_core_codec_reset(session->read_codec);
		switch_clear_flag(session, SSF_READ_CODEC_RESET);
	}

	




	if (status == SWITCH_STATUS_SUCCESS && need_codec) {
		switch_frame_t *enc_frame, *read_frame = *frame;

		switch_set_flag(session, SSF_READ_TRANSCODE);

		if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) {
			switch_core_session_message_t msg = { 0 };

			msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY;
			switch_core_session_receive_message(session, &msg);
			switch_set_flag(session, SSF_WARN_TRANSCODE);
		}

		if (read_frame->codec || is_cng) {
			session->raw_read_frame.datalen = session->raw_read_frame.buflen;

			if (is_cng) {
				if (session->plc) {
					plc_fillin(session->plc, session->raw_read_frame.data, read_frame->codec->implementation->decoded_bytes_per_packet / 2);
					is_cng = 0;
					flag &= !SFF_CNG;
				} else {
					memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet);
				}

				session->raw_read_frame.timestamp = 0;
				session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
				session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
				read_frame = &session->raw_read_frame;
				status = SWITCH_STATUS_SUCCESS;
			} else {
				switch_codec_t *use_codec = read_frame->codec;
				if (do_bugs) {
					switch_thread_rwlock_wrlock(session->bug_rwlock);
					if (!session->bugs) {
						do_bugs = 0;
						switch_thread_rwlock_unlock(session->bug_rwlock);
						goto done;
					}

					if (!switch_core_codec_ready(&session->bug_codec)) {
						switch_core_codec_copy(read_frame->codec, &session->bug_codec, NULL);
					}
					use_codec = &session->bug_codec;
					switch_thread_rwlock_unlock(session->bug_rwlock);

					switch_thread_rwlock_wrlock(session->bug_rwlock);
					if (!session->bugs) {
						do_bugs = 0;
					}
					switch_thread_rwlock_unlock(session->bug_rwlock);
					if (!do_bugs) goto done;
				}

				if (switch_test_flag(read_frame, SFF_PLC)) {
					session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
					session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
					memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen);
					status = SWITCH_STATUS_SUCCESS;
				} else {
					status = switch_core_codec_decode(use_codec,
													  session->read_codec,
													  read_frame->data,
													  read_frame->datalen,
													  session->read_impl.actual_samples_per_second,
													  session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate, 
													  &read_frame->flags);
				}
				
				if (status == SWITCH_STATUS_SUCCESS) {
					if ((switch_channel_test_flag(session->channel, CF_JITTERBUFFER) || switch_channel_test_flag(session->channel, CF_CNG_PLC)) 
						&& !session->plc) {
						session->plc = plc_init(NULL);
					}
				
					if (session->plc) {
						if (switch_test_flag(read_frame, SFF_PLC)) {
							plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
							switch_clear_flag(read_frame, SFF_PLC);
						} else {
							plc_rx(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);
						}
					}
				}


			}

			if (do_resample && ((status == SWITCH_STATUS_SUCCESS) || is_cng)) {
				status = SWITCH_STATUS_RESAMPLE;
			}

			switch (status) {
			case SWITCH_STATUS_RESAMPLE:
				if (!session->read_resampler) {
					switch_mutex_lock(session->resample_mutex);
					status = switch_resample_create(&session->read_resampler,
													read_frame->codec->implementation->actual_samples_per_second,
													session->read_impl.actual_samples_per_second,
													session->read_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1);

					switch_mutex_unlock(session->resample_mutex);

					if (status != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to allocate resampler\n");
						status = SWITCH_STATUS_FALSE;
						goto done;
					}
				}
			case SWITCH_STATUS_SUCCESS:
				session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
				session->raw_read_frame.rate = read_frame->rate;
				if (read_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) {
					session->raw_read_frame.timestamp = 0;
				} else {
					session->raw_read_frame.timestamp = read_frame->timestamp;
				}
				session->raw_read_frame.ssrc = read_frame->ssrc;
				session->raw_read_frame.seq = read_frame->seq;
				session->raw_read_frame.m = read_frame->m;
				session->raw_read_frame.payload = read_frame->payload;
				session->raw_read_frame.flags = 0;
				if (switch_test_flag(read_frame, SFF_PLC)) {
					session->raw_read_frame.flags |= SFF_PLC;
				}
				read_frame = &session->raw_read_frame;
				break;
			case SWITCH_STATUS_NOOP:
				if (session->read_resampler) {
					switch_mutex_lock(session->resample_mutex);
					switch_resample_destroy(&session->read_resampler);
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n");
					switch_mutex_unlock(session->resample_mutex);
				}

				status = SWITCH_STATUS_SUCCESS;
				break;
			case SWITCH_STATUS_BREAK:
				memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet);
				session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet;
				session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
				session->raw_read_frame.timestamp = read_frame->timestamp;
				session->raw_read_frame.rate = read_frame->rate;
				session->raw_read_frame.ssrc = read_frame->ssrc;
				session->raw_read_frame.seq = read_frame->seq;
				session->raw_read_frame.m = read_frame->m;
				session->raw_read_frame.payload = read_frame->payload;
				session->raw_read_frame.flags = 0;
				if (switch_test_flag(read_frame, SFF_PLC)) {
					session->raw_read_frame.flags |= SFF_PLC;
				}

				read_frame = &session->raw_read_frame;
				status = SWITCH_STATUS_SUCCESS;
				break;
			case SWITCH_STATUS_NOT_INITALIZED:
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
				goto done;
			default:
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
								  session->read_codec->codec_interface->interface_name);
				goto done;
			}
		}

		if (session->bugs) {
			switch_media_bug_t *bp;
			switch_bool_t ok = SWITCH_TRUE;
			int prune = 0;
			switch_thread_rwlock_rdlock(session->bug_rwlock);

			for (bp = session->bugs; bp; bp = bp->next) {
				if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
					continue;
				}

				if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
					continue;
				}
				if (switch_test_flag(bp, SMBF_PRUNE)) {
					prune++;
					continue;
				}

				if (bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) {
					switch_mutex_lock(bp->read_mutex);
					switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
					if (bp->callback) {
						ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ);
					}
					switch_mutex_unlock(bp->read_mutex);
				}

				if (ok && switch_test_flag(bp, SMBF_READ_REPLACE)) {
					do_bugs = 0;
					if (bp->callback) {
						bp->read_replace_frame_in = read_frame;
						bp->read_replace_frame_out = read_frame;
						if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) {
							read_frame = bp->read_replace_frame_out;
						}
					}
				}

				if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
					switch_set_flag(bp, SMBF_PRUNE);
					prune++;
				}


			}
			switch_thread_rwlock_unlock(session->bug_rwlock);
			if (prune) {
				switch_core_media_bug_prune(session);
			}
		}

		if (do_bugs) {
			goto done;
		}

		if (session->read_codec) {
			if (session->read_resampler) {
				short *data = read_frame->data;
				switch_mutex_lock(session->resample_mutex);
				switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2);
				memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2);
				read_frame->samples = session->read_resampler->to_len;
				read_frame->datalen = session->read_resampler->to_len * 2;
				read_frame->rate = session->read_resampler->to_rate;
				switch_mutex_unlock(session->resample_mutex);
			}

			if (read_frame->datalen == session->read_impl.decoded_bytes_per_packet) {
				perfect = TRUE;
			} else {
				if (!session->raw_read_buffer) {
					switch_size_t bytes = session->read_impl.decoded_bytes_per_packet;
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes vs %u\n",
									  (uint32_t) bytes, (uint32_t) (*frame)->datalen);
					switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0);
				}

				if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
					status = SWITCH_STATUS_MEMERR;
					goto done;
				}
			}

			if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_impl.decoded_bytes_per_packet) {
				if (perfect) {
					enc_frame = read_frame;
					session->raw_read_frame.rate = read_frame->rate;
				} else {
					session->raw_read_frame.datalen = (uint32_t) switch_buffer_read(session->raw_read_buffer,
																					session->raw_read_frame.data,
																					session->read_impl.decoded_bytes_per_packet);

					session->raw_read_frame.rate = session->read_impl.actual_samples_per_second;
					enc_frame = &session->raw_read_frame;
				}
				session->enc_read_frame.datalen = session->enc_read_frame.buflen;

				switch_assert(session->read_codec != NULL);
				switch_assert(enc_frame != NULL);
				switch_assert(enc_frame->data != NULL);

				status = switch_core_codec_encode(session->read_codec,
												  enc_frame->codec,
												  enc_frame->data,
												  enc_frame->datalen,
												  session->read_impl.actual_samples_per_second,
												  session->enc_read_frame.data, &session->enc_read_frame.datalen, &session->enc_read_frame.rate, &flag);

				switch (status) {
				case SWITCH_STATUS_RESAMPLE:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 1\n");
				case SWITCH_STATUS_SUCCESS:
					session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t);
					if (perfect) {
						if (enc_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) {
							session->enc_read_frame.timestamp = 0;
						} else {
							session->enc_read_frame.timestamp = read_frame->timestamp;
						}
						session->enc_read_frame.rate = read_frame->rate;
						session->enc_read_frame.ssrc = read_frame->ssrc;
						session->enc_read_frame.seq = read_frame->seq;
						session->enc_read_frame.m = read_frame->m;
						session->enc_read_frame.payload = session->read_impl.ianacode;
					}
					*frame = &session->enc_read_frame;
					break;
				case SWITCH_STATUS_NOOP:
					session->raw_read_frame.samples = enc_frame->codec->implementation->samples_per_packet;
					session->raw_read_frame.timestamp = read_frame->timestamp;
					session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode;
					session->raw_read_frame.m = read_frame->m;
					session->raw_read_frame.ssrc = read_frame->ssrc;
					session->raw_read_frame.seq = read_frame->seq;
					*frame = enc_frame;
					status = SWITCH_STATUS_SUCCESS;
					break;
				case SWITCH_STATUS_NOT_INITALIZED:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
					*frame = NULL;
					status = SWITCH_STATUS_GENERR;
					break;
				default:
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
									  session->read_codec->codec_interface->interface_name);
					*frame = NULL;
					status = SWITCH_STATUS_GENERR;
					break;
				}
			} else {
				goto top;
			}
		}
	}

  done:
	if (!(*frame)) {
		status = SWITCH_STATUS_FALSE;
	} else {
		if (flag & SFF_CNG) {
			switch_set_flag((*frame), SFF_CNG);
		}
		if (session->bugs) {
			switch_media_bug_t *bp;
			switch_bool_t ok = SWITCH_TRUE;
			int prune = 0;
			switch_thread_rwlock_rdlock(session->bug_rwlock);
			for (bp = session->bugs; bp; bp = bp->next) {
				if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
					continue;
				}

				if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
					continue;
				}

				if (switch_test_flag(bp, SMBF_PRUNE)) {
					prune++;
					continue;
				}

				if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) {
					switch_mutex_lock(bp->read_mutex);
					if (bp->callback) {
						if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_PING) == SWITCH_FALSE
							|| (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
							ok = SWITCH_FALSE;
						}
					}
					switch_mutex_unlock(bp->read_mutex);
				}

				if (ok == SWITCH_FALSE) {
					switch_set_flag(bp, SMBF_PRUNE);
					prune++;
				}
			}
			switch_thread_rwlock_unlock(session->bug_rwlock);
			if (prune) {
				switch_core_media_bug_prune(session);
			}
		}
	}

  even_more_done:

	if (!*frame || !(*frame)->codec || !(*frame)->codec->implementation || !switch_core_codec_ready((*frame)->codec)) {
		*frame = &runtime.dummy_cng_frame;
	}

	switch_mutex_unlock(session->read_codec->mutex);
	switch_mutex_unlock(session->codec_read_mutex);

	return status;
}
Exemple #8
0
void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj)
{
	rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)obj;
	io->base.running = 1;
	
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: I/O Thread starting\n", io->base.profile->name);
	
	
	while(io->base.running) {
		const switch_pollfd_t *fds;
		int32_t numfds;
		int32_t i;
		switch_status_t status;
		
		switch_mutex_lock(io->mutex);
		status = switch_pollset_poll(io->pollset, 500000, &numfds, &fds);
		switch_mutex_unlock(io->mutex);
		
		if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n");
			continue;
		} else if (status == SWITCH_STATUS_TIMEOUT) {
			switch_cond_next();
		}
		
		for (i = 0; i < numfds; i++) {
			if (!fds[i].client_data) { 
				switch_socket_t *newsocket;
				if (switch_socket_accept(&newsocket, io->listen_socket, io->base.pool) != SWITCH_STATUS_SUCCESS) {
					if (io->base.running) {
						/* Don't spam the logs if we are shutting down */
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));	
					} else {
						return NULL;
					}
				} else {
					rtmp_session_t *rsession;
					
					if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n");
					}

					if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n");
					}
					
					if (rtmp_session_request(io->base.profile, &rsession) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n");
						switch_socket_close(newsocket);
					} else {
						switch_sockaddr_t *addr = NULL;
						char ipbuf[200];
						
						/* Create out private data and attach it to the rtmp session structure */
						rtmp_tcp_io_private_t *pvt = switch_core_alloc(rsession->pool, sizeof(*pvt));
						rsession->io_private = pvt;
						pvt->socket = newsocket;
						switch_socket_create_pollfd(&pvt->pollfd, newsocket, SWITCH_POLLIN | SWITCH_POLLERR, rsession, rsession->pool);
						switch_pollset_add(io->pollset, pvt->pollfd);
						switch_buffer_create_dynamic(&pvt->sendq, 512, 1024, 0);
						
						/* Get the remote address/port info */
						switch_socket_addr_get(&addr, SWITCH_TRUE, newsocket);
						switch_get_addr(ipbuf, sizeof(ipbuf), addr);
						rsession->remote_address = switch_core_strdup(rsession->pool, ipbuf);
						rsession->remote_port = switch_sockaddr_get_port(addr);
						switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Rtmp connection from %s:%i\n",
										  rsession->remote_address, rsession->remote_port);
					}
				}
			} else {
				rtmp_session_t *rsession = (rtmp_session_t*)fds[i].client_data;
				rtmp_tcp_io_private_t *io_pvt = (rtmp_tcp_io_private_t*)rsession->io_private;
				
				if (fds[i].rtnevents & SWITCH_POLLOUT && switch_buffer_inuse(io_pvt->sendq) > 0) {
					/* Send as much remaining data as possible */
					switch_size_t sendlen;
					const void *ptr;
					sendlen = switch_buffer_peek_zerocopy(io_pvt->sendq, &ptr);
					switch_socket_send_nonblock(io_pvt->socket, ptr, &sendlen);
					switch_buffer_toss(io_pvt->sendq, sendlen);
					if (switch_buffer_inuse(io_pvt->sendq) == 0) {
						/* Remove our fd from OUT polling */
						rtmp_tcp_alter_pollfd(rsession, SWITCH_FALSE);
					}
				} else 	if (fds[i].rtnevents & SWITCH_POLLIN && rtmp_handle_data(rsession) != SWITCH_STATUS_SUCCESS) {
					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "Closing socket\n");
					
					switch_mutex_lock(io->mutex);
					switch_pollset_remove(io->pollset, io_pvt->pollfd);
					switch_mutex_unlock(io->mutex);
					
					switch_socket_close(io_pvt->socket);
					io_pvt->socket = NULL;
					
					rtmp_session_destroy(&rsession);
				}
			}
		}
	}
	
	io->base.running = -1;
	switch_socket_close(io->listen_socket);
	
	return NULL;
}
switch_memory_pool_t *switch_core_memory_init(void)
{
#ifndef INSTANTLY_DESTROY_POOLS
	switch_threadattr_t *thd_attr;
#endif
#ifdef PER_POOL_LOCK
	apr_allocator_t *my_allocator = NULL;
	apr_thread_mutex_t *my_mutex;
#endif

	memset(&memory_manager, 0, sizeof(memory_manager));

#ifdef PER_POOL_LOCK
	if ((apr_allocator_create(&my_allocator)) != APR_SUCCESS) {
		abort();
	}

	if ((apr_pool_create_ex(&memory_manager.memory_pool, NULL, NULL, my_allocator)) != APR_SUCCESS) {
		apr_allocator_destroy(my_allocator);
		my_allocator = NULL;
		abort();
	}

	if ((apr_thread_mutex_create(&my_mutex, APR_THREAD_MUTEX_NESTED, memory_manager.memory_pool)) != APR_SUCCESS) {
		abort();
	}

	apr_allocator_mutex_set(my_allocator, my_mutex);
	apr_pool_mutex_set(memory_manager.memory_pool, my_mutex);
	apr_allocator_owner_set(my_allocator, memory_manager.memory_pool);
	apr_pool_tag(memory_manager.memory_pool, "core_pool");
#else
	apr_pool_create(&memory_manager.memory_pool, NULL);
	switch_assert(memory_manager.memory_pool != NULL);
#endif

#ifdef USE_MEM_LOCK
	switch_mutex_init(&memory_manager.mem_lock, SWITCH_MUTEX_NESTED, memory_manager.memory_pool);
#endif

#ifdef INSTANTLY_DESTROY_POOLS
	{
		void *foo;
		foo = (void *) (intptr_t) pool_thread;
	}
#else

	switch_queue_create(&memory_manager.pool_queue, 50000, memory_manager.memory_pool);
	switch_queue_create(&memory_manager.pool_recycle_queue, 50000, memory_manager.memory_pool);

	switch_threadattr_create(&thd_attr, memory_manager.memory_pool);

	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
	switch_thread_create(&pool_thread_p, thd_attr, pool_thread, NULL, memory_manager.memory_pool);

	while (!memory_manager.pool_thread_running) {
		switch_cond_next();
	}
#endif

	return memory_manager.memory_pool;
}
Exemple #10
0
static switch_status_t cepstral_speech_read_tts(switch_speech_handle_t *sh, void *data, size_t *datalen, switch_speech_flag_t *flags)
{
	cepstral_t *cepstral;
	size_t desired = *datalen;
	switch_status_t status = SWITCH_STATUS_FALSE;
	size_t used, padding = 0;

	assert(sh != NULL);
	cepstral = sh->private_info;
	assert(cepstral != NULL);

	while (!cepstral->done) {
		if (!cepstral->done_gen) {
			int check = swift_port_status(cepstral->port, cepstral->tts_stream);

			if (!check == SWIFT_STATUS_RUNNING) {
				cepstral->done_gen = 1;
			}
		}

		switch_mutex_lock(cepstral->audio_lock);
		used = switch_buffer_inuse(cepstral->audio_buffer);
		switch_mutex_unlock(cepstral->audio_lock);


		if (!used && cepstral->done_gen) {

			status = SWITCH_STATUS_BREAK;
			break;
		}

		/* wait for the right amount of data (unless there is no blocking flag) */
		if (used < desired) {
			if (cepstral->done_gen) {
				padding = desired - used;
				desired = used;
			}
			if (!(*flags & SWITCH_SPEECH_FLAG_BLOCKING)) {
				*datalen = 0;
				status = SWITCH_STATUS_SUCCESS;
				break;
			}
			switch_cond_next();
			continue;
		}

		/* There is enough, read it and return */
		switch_mutex_lock(cepstral->audio_lock);
		*datalen = switch_buffer_read(cepstral->audio_buffer, data, desired);
		if (padding) {
			size_t x = 0;
			unsigned char *p = data;

			for (x = 0; x < padding; x++) {
				*(p + x) = 0;
				(*datalen)++;
			}
		}

		switch_mutex_unlock(cepstral->audio_lock);
		status = SWITCH_STATUS_SUCCESS;

		break;
	}

	return status;
}
SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
{
	switch_channel_state_t state = CS_NEW, midstate = CS_DESTROY, endstate;
	const switch_endpoint_interface_t *endpoint_interface;
	const switch_state_handler_table_t *driver_state_handler = NULL;
	const switch_state_handler_table_t *application_state_handler = NULL;
	int silly = 0;
	uint32_t new_loops = 60000;

	/*
	   Life of the channel. you have channel and pool in your session
	   everywhere you go you use the session to malloc with
	   switch_core_session_alloc(session, <size>)

	   The endpoint module gets the first crack at implementing the state
	   if it wants to, it can cancel the default behavior by returning SWITCH_STATUS_FALSE

	   Next comes the channel's event handler table that can be set by an application
	   which also can veto the next behavior in line by returning SWITCH_STATUS_FALSE

	   Finally the default state behavior is called.


	 */
	switch_assert(session != NULL);

	switch_set_flag(session, SSF_THREAD_RUNNING);
	endpoint_interface = session->endpoint_interface;
	switch_assert(endpoint_interface != NULL);

	driver_state_handler = endpoint_interface->state_handler;
	switch_assert(driver_state_handler != NULL);

	switch_mutex_lock(session->mutex);

	while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) {

		if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) {
			switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL);
			if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) {
				break;
			}
		}

		midstate = state;
		if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) {
			int index = 0;
			int proceed = 1;
			int global_proceed = 1;
			int do_extra_handlers = 1;
			switch_io_event_hook_state_run_t *ptr;
			switch_status_t rstatus = SWITCH_STATUS_SUCCESS;

			switch_channel_set_running_state(session->channel, state);
			switch_channel_clear_flag(session->channel, CF_TRANSFER);
			switch_channel_clear_flag(session->channel, CF_REDIRECT);
			
			if (session->endpoint_interface->io_routines->state_run) {
				rstatus = session->endpoint_interface->io_routines->state_run(session);
			}
			
			if (rstatus == SWITCH_STATUS_SUCCESS) {
				for (ptr = session->event_hooks.state_run; ptr; ptr = ptr->next) {
					if ((rstatus = ptr->state_run(session)) != SWITCH_STATUS_SUCCESS) {
						break;
					}
				}
			}
			
			switch (state) {
			case CS_NEW:		/* Just created, Waiting for first instructions */
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel));
				break;
			case CS_DESTROY:
				goto done;
			case CS_REPORTING:	/* Call Detail */
				{
					switch_core_session_reporting_state(session);
					switch_channel_set_state(session->channel, CS_DESTROY);
				}
				goto done;
			case CS_HANGUP:	/* Deactivate and end the thread */
				{
					switch_core_session_hangup_state(session, SWITCH_TRUE);
					switch_channel_set_state(session->channel, CS_REPORTING);
				}

				break;
			case CS_INIT:		/* Basic setup tasks */
				{
					switch_event_t *event;

					STATE_MACRO(init, "INIT");
					
					if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CREATE) == SWITCH_STATUS_SUCCESS) {
						switch_channel_event_set_data(session->channel, event);
						switch_event_fire(&event);
					}
				}
				break;
			case CS_ROUTING:	/* Look for a dialplan and find something to do */
				STATE_MACRO(routing, "ROUTING");
				break;
			case CS_RESET:		/* Reset */
				STATE_MACRO(reset, "RESET");
				break;
				/* These other states are intended for prolonged durations so we do not signal lock for them */
			case CS_EXECUTE:	/* Execute an Operation */
				STATE_MACRO(execute, "EXECUTE");
				break;
			case CS_EXCHANGE_MEDIA:	/* loop all data back to source */
				STATE_MACRO(exchange_media, "EXCHANGE_MEDIA");
				break;
			case CS_SOFT_EXECUTE:	/* send/recieve data to/from another channel */
				STATE_MACRO(soft_execute, "SOFT_EXECUTE");
				break;
			case CS_PARK:		/* wait in limbo */
				STATE_MACRO(park, "PARK");
				break;
			case CS_CONSUME_MEDIA:	/* wait in limbo */
				STATE_MACRO(consume_media, "CONSUME_MEDIA");
				break;
			case CS_HIBERNATE:	/* sleep */
				STATE_MACRO(hibernate, "HIBERNATE");
				break;
			case CS_NONE:
				abort();
				break;
			}

			if (midstate == CS_DESTROY) {
				break;
			}

		}

		endstate = switch_channel_get_state(session->channel);

		if (endstate == switch_channel_get_running_state(session->channel)) {
			if (endstate == CS_NEW) {
				switch_cond_next();
				switch_ivr_parse_all_events(session);
				if (!--new_loops) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s Timeout waiting for next instruction in CS_NEW!\n",
									  session->uuid_str);
					switch_channel_hangup(session->channel, SWITCH_CAUSE_INVALID_CALL_REFERENCE);
				}
			} else {
				switch_ivr_parse_all_events(session);
				switch_ivr_parse_all_events(session);

				if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
					switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING);
					if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
						switch_thread_cond_wait(session->cond, session->mutex);
					}
					switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING);
				}

				switch_ivr_parse_all_events(session);
				switch_ivr_parse_all_events(session);
			}
		}
	}
  done:
	switch_mutex_unlock(session->mutex);

	switch_clear_flag(session, SSF_THREAD_RUNNING);
}
Exemple #12
0
switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
{
	skinny_message_t *request;
	switch_size_t mlen, bytes = 0;
	char mbuf[SKINNY_MESSAGE_MAXSIZE] = "";
	char *ptr;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	request = calloc(1,SKINNY_MESSAGE_MAXSIZE);

	if (!request) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate memory.\n");
		return SWITCH_STATUS_MEMERR;
	}

	ptr = mbuf;

	while (listener_is_ready(listener)) {
		uint8_t do_sleep = 1;
		if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
			switch_safe_free(request);
			return SWITCH_STATUS_TIMEOUT;
		}
		if(bytes < SKINNY_MESSAGE_FIELD_SIZE) {
			/* We have nothing yet, get length header field */
			mlen = SKINNY_MESSAGE_FIELD_SIZE - bytes;
		} else {
			/* We now know the message size */
			mlen = request->length + 2*SKINNY_MESSAGE_FIELD_SIZE - bytes;
		}

		status = switch_socket_recv(listener->sock, ptr, &mlen);

		if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
			switch_safe_free(request);
			return SWITCH_STATUS_TIMEOUT;
		}

		if (!listener_is_ready(listener)) {
			switch_safe_free(request);
			break;
		}
		if (!switch_status_is_timeup(status) && !SWITCH_STATUS_IS_BREAK(status) && (status != SWITCH_STATUS_SUCCESS)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket break with status=%d.\n", status);
			switch_safe_free(request);
			return SWITCH_STATUS_FALSE;
		}

		if(mlen) {
			bytes += mlen;

			if(bytes >= SKINNY_MESSAGE_FIELD_SIZE) {
				do_sleep = 0;
				ptr += mlen;
				memcpy(request, mbuf, bytes);
#ifdef SKINNY_MEGA_DEBUG
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						"Got request: length=%d,version=%x,type=%x\n",
						request->length,request->version,request->type);
#endif
				if(request->length < SKINNY_MESSAGE_FIELD_SIZE) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
							"Skinny client sent invalid data. Length should be greater than 4 but got %d.\n",
							request->length);
					switch_safe_free(request);
					return SWITCH_STATUS_FALSE;
				}
				if(request->length + 2*SKINNY_MESSAGE_FIELD_SIZE > SKINNY_MESSAGE_MAXSIZE) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
							"Skinny client sent too huge data. Got %d which is above threshold %d.\n",
							request->length, SKINNY_MESSAGE_MAXSIZE - 2*SKINNY_MESSAGE_FIELD_SIZE);
					switch_safe_free(request);
					return SWITCH_STATUS_FALSE;
				}
				if(bytes >= request->length + 2*SKINNY_MESSAGE_FIELD_SIZE) {
					/* Message body */
					*req = request;
					/* Do not free here, caller needs to do it */
					return  SWITCH_STATUS_SUCCESS;
				}
			}
		}

		if (listener->digit_timeout_time && listener->digit_timeout_time < switch_mono_micro_time_now()) {
			switch_safe_free(request);
			return SWITCH_STATUS_TIMEOUT;
		}

		if (do_sleep) {
			switch_cond_next();
		}
	}

	switch_safe_free(request);
	return SWITCH_STATUS_SUCCESS;
}
Exemple #13
0
/* NB. this starts the input thread after some initial setup for the call leg */
void conference_loop_output(conference_member_t *member)
{
	switch_channel_t *channel;
	switch_frame_t write_frame = { 0 };
	uint8_t *data = NULL;
	switch_timer_t timer = { 0 };
	uint32_t interval;
	uint32_t samples;
	//uint32_t csamples;
	uint32_t tsamples;
	uint32_t flush_len;
	uint32_t low_count, bytes;
	call_list_t *call_list, *cp;
	switch_codec_implementation_t read_impl = { 0 };
	int sanity;
	switch_status_t st;

	switch_core_session_get_read_impl(member->session, &read_impl);


	channel = switch_core_session_get_channel(member->session);
	interval = read_impl.microseconds_per_packet / 1000;
	samples = switch_samples_per_packet(member->conference->rate, interval);
	//csamples = samples;
	tsamples = member->orig_read_impl.samples_per_packet;
	low_count = 0;
	bytes = samples * 2 * member->conference->channels;
	call_list = NULL;
	cp = NULL;

	member->loop_loop = 0;

	switch_assert(member->conference != NULL);

	flush_len = switch_samples_per_packet(member->conference->rate, member->conference->interval) * 2 * member->conference->channels * (500 / member->conference->interval);

	if (switch_core_timer_init(&timer, member->conference->timer_name, interval, tsamples, NULL) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Timer Setup Failed.  Conference Cannot Start\n");
		return;
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Setup timer %s success interval: %u  samples: %u\n",
					  member->conference->timer_name, interval, tsamples);


	write_frame.data = data = switch_core_session_alloc(member->session, SWITCH_RECOMMENDED_BUFFER_SIZE);
	write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;


	write_frame.codec = &member->write_codec;

	/* Start the input thread */
	conference_loop_launch_input(member, switch_core_session_get_pool(member->session));

	if ((call_list = switch_channel_get_private(channel, "_conference_autocall_list_"))) {
		const char *cid_name = switch_channel_get_variable(channel, "conference_auto_outcall_caller_id_name");
		const char *cid_num = switch_channel_get_variable(channel, "conference_auto_outcall_caller_id_number");
		const char *toval = switch_channel_get_variable(channel, "conference_auto_outcall_timeout");
		const char *flags = switch_channel_get_variable(channel, "conference_utils_auto_outcall_flags");
		const char *profile = switch_channel_get_variable(channel, "conference_auto_outcall_profile");
		const char *ann = switch_channel_get_variable(channel, "conference_auto_outcall_announce");
		const char *prefix = switch_channel_get_variable(channel, "conference_auto_outcall_prefix");
		const char *maxwait = switch_channel_get_variable(channel, "conference_auto_outcall_maxwait");
		const char *delimiter_val = switch_channel_get_variable(channel, "conference_auto_outcall_delimiter");
		int to = 60;
		int wait_sec = 2;
		int loops = 0;

		if (ann && !switch_channel_test_app_flag_key("conference_silent", channel, CONF_SILENT_REQ)) {
			member->conference->special_announce = switch_core_strdup(member->conference->pool, ann);
		}

		switch_channel_set_private(channel, "_conference_autocall_list_", NULL);

		conference_utils_set_flag(member->conference, CFLAG_OUTCALL);

		if (toval) {
			to = atoi(toval);
			if (to < 10 || to > 500) {
				to = 60;
			}
		}

		for (cp = call_list; cp; cp = cp->next) {
			int argc;
			char *argv[512] = { 0 };
			char *cpstr = strdup(cp->string);
			int x = 0;

			switch_assert(cpstr);
			if (!zstr(delimiter_val) && strlen(delimiter_val) == 1) {
				char delimiter = *delimiter_val;
				argc = switch_separate_string(cpstr, delimiter, argv, (sizeof(argv) / sizeof(argv[0])));
			} else {
				argc = switch_separate_string(cpstr, ',', argv, (sizeof(argv) / sizeof(argv[0])));
			}
			for (x = 0; x < argc; x++) {
				char *dial_str = switch_mprintf("%s%s", switch_str_nil(prefix), argv[x]);
				switch_assert(dial_str);
				conference_outcall_bg(member->conference, NULL, NULL, dial_str, to, switch_str_nil(flags), cid_name, cid_num, NULL,
									  profile, &member->conference->cancel_cause, NULL);
				switch_safe_free(dial_str);
			}
			switch_safe_free(cpstr);
		}

		if (maxwait) {
			int tmp = atoi(maxwait);
			if (tmp > 0) {
				wait_sec = tmp;
			}
		}


		loops = wait_sec * 10;

		switch_channel_set_app_flag(channel, CF_APP_TAGGED);
		do {
			switch_ivr_sleep(member->session, 100, SWITCH_TRUE, NULL);
		} while(switch_channel_up(channel) && (member->conference->originating && --loops));
		switch_channel_clear_app_flag(channel, CF_APP_TAGGED);

		if (!switch_channel_ready(channel)) {
			member->conference->cancel_cause = SWITCH_CAUSE_ORIGINATOR_CANCEL;
			goto end;
		}

		conference_member_play_file(member, "tone_stream://%(500,0,640)", 0, SWITCH_TRUE);
	}

	if (!conference_utils_test_flag(member->conference, CFLAG_ANSWERED)) {
		switch_channel_answer(channel);
	}


	sanity = 2000;
	while(!conference_utils_member_test_flag(member, MFLAG_ITHREAD) && sanity > 0) {
		switch_cond_next();
		sanity--;
	}

	/* Fair WARNING, If you expect the caller to hear anything or for digit handling to be processed,      */
	/* you better not block this thread loop for more than the duration of member->conference->timer_name!  */
	while (!member->loop_loop && conference_utils_member_test_flag(member, MFLAG_RUNNING) && conference_utils_member_test_flag(member, MFLAG_ITHREAD)
		   && switch_channel_ready(channel)) {
		switch_event_t *event;
		int use_timer = 0;
		switch_buffer_t *use_buffer = NULL;
		uint32_t mux_used = 0;


		//if (member->reset_media || switch_channel_test_flag(member->channel, CF_CONFERENCE_RESET_MEDIA)) {
		//	switch_cond_next();
		//	continue;
		//}

		switch_mutex_lock(member->write_mutex);


		if (switch_channel_test_flag(member->channel, CF_CONFERENCE_ADV)) {
			if (member->conference->la) {
				conference_event_adv_la(member->conference, member, SWITCH_TRUE);
			}
			switch_channel_clear_flag(member->channel, CF_CONFERENCE_ADV);
		}


		if (switch_core_session_dequeue_event(member->session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
			if (event->event_id == SWITCH_EVENT_MESSAGE) {
				char *from = switch_event_get_header(event, "from");
				char *to = switch_event_get_header(event, "to");
				char *body = switch_event_get_body(event);

				if (to && from && body) {
					if (strchr(to, '+') && strncmp(to, CONF_CHAT_PROTO, strlen(CONF_CHAT_PROTO))) {
						switch_event_del_header(event, "to");
						switch_event_add_header(event, SWITCH_STACK_BOTTOM,
												"to", "%s+%s@%s", CONF_CHAT_PROTO, member->conference->name, member->conference->domain);
					} else {
						switch_event_del_header(event, "to");
						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s", member->conference->name);
					}
					chat_send(event);
				}
			}
			switch_event_destroy(&event);
		}

		if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
			/* test to see if outbound channel has answered */
			if (switch_channel_test_flag(channel, CF_ANSWERED) && !conference_utils_test_flag(member->conference, CFLAG_ANSWERED)) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
								  "Outbound conference channel answered, setting CFLAG_ANSWERED\n");
				conference_utils_set_flag(member->conference, CFLAG_ANSWERED);
			}
		} else {
			if (conference_utils_test_flag(member->conference, CFLAG_ANSWERED) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "CLFAG_ANSWERED set, answering inbound channel\n");
				switch_channel_answer(channel);
			}
		}

		use_buffer = NULL;
		mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);

		use_timer = 1;

		if (mux_used) {
			if (mux_used < bytes) {
				if (++low_count >= 5) {
					/* partial frame sitting around this long is useless and builds delay */
					conference_utils_member_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
				}
			} else if (mux_used > flush_len) {
				/* getting behind, clear the buffer */
				conference_utils_member_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
			}
		}

		if (switch_channel_test_app_flag(channel, CF_APP_TAGGED)) {
			conference_utils_member_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
		} else if (mux_used >= bytes) {
			/* Flush the output buffer and write all the data (presumably muxed) back to the channel */
			switch_mutex_lock(member->audio_out_mutex);
			write_frame.data = data;
			use_buffer = member->mux_buffer;
			low_count = 0;

			if ((write_frame.datalen = (uint32_t) switch_buffer_read(use_buffer, write_frame.data, bytes))) {
				if (write_frame.datalen) {
					write_frame.samples = write_frame.datalen / 2 / member->conference->channels;

					if( !conference_utils_member_test_flag(member, MFLAG_CAN_HEAR)) {
						memset(write_frame.data, 255, write_frame.datalen);
					} else if (member->volume_out_level) { /* Check for output volume adjustments */
						switch_change_sln_volume(write_frame.data, write_frame.samples * member->conference->channels, member->volume_out_level);
					}

					write_frame.timestamp = timer.samplecount;

					if (member->fnode) {
						conference_member_add_file_data(member, write_frame.data, write_frame.datalen);
					}

					conference_member_check_channels(&write_frame, member, SWITCH_FALSE);

					if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
						switch_mutex_unlock(member->audio_out_mutex);
						break;
					}
				}
			}

			switch_mutex_unlock(member->audio_out_mutex);
		}

		if (conference_utils_member_test_flag(member, MFLAG_FLUSH_BUFFER)) {
			if (switch_buffer_inuse(member->mux_buffer)) {
				switch_mutex_lock(member->audio_out_mutex);
				switch_buffer_zero(member->mux_buffer);
				switch_mutex_unlock(member->audio_out_mutex);
			}
			conference_utils_member_clear_flag_locked(member, MFLAG_FLUSH_BUFFER);
		}

		switch_mutex_unlock(member->write_mutex);


		if (conference_utils_member_test_flag(member, MFLAG_INDICATE_MUTE)) {
			if (!zstr(member->conference->muted_sound)) {
				conference_member_play_file(member, member->conference->muted_sound, 0, SWITCH_TRUE);
			} else {
				char msg[512];

				switch_snprintf(msg, sizeof(msg), "Muted");
				conference_member_say(member, msg, 0);
			}
			conference_utils_member_clear_flag(member, MFLAG_INDICATE_MUTE);
		}

		if (conference_utils_member_test_flag(member, MFLAG_INDICATE_MUTE_DETECT)) {
			if (!zstr(member->conference->mute_detect_sound)) {
				conference_member_play_file(member, member->conference->mute_detect_sound, 0, SWITCH_TRUE);
			} else {
				char msg[512];

				switch_snprintf(msg, sizeof(msg), "Currently Muted");
				conference_member_say(member, msg, 0);
			}
			conference_utils_member_clear_flag(member, MFLAG_INDICATE_MUTE_DETECT);
		}

		if (conference_utils_member_test_flag(member, MFLAG_INDICATE_UNMUTE)) {
			if (!zstr(member->conference->unmuted_sound)) {
				conference_member_play_file(member, member->conference->unmuted_sound, 0, SWITCH_TRUE);
			} else {
				char msg[512];

				switch_snprintf(msg, sizeof(msg), "Un-Muted");
				conference_member_say(member, msg, 0);
			}
			conference_utils_member_clear_flag(member, MFLAG_INDICATE_UNMUTE);
		}

		if (switch_core_session_private_event_count(member->session)) {
			switch_channel_set_app_flag(channel, CF_APP_TAGGED);
			switch_ivr_parse_all_events(member->session);
			switch_channel_clear_app_flag(channel, CF_APP_TAGGED);
			conference_utils_member_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
			switch_core_session_set_read_codec(member->session, &member->read_codec);
		} else {
			switch_ivr_parse_all_messages(member->session);
		}

		if (use_timer) {
			switch_core_timer_next(&timer);
		} else {
			switch_cond_next();
		}

	} /* Rinse ... Repeat */

 end:

	if (!member->loop_loop) {
		conference_utils_member_clear_flag_locked(member, MFLAG_RUNNING);

		/* Wait for the input thread to end */
		if (member->input_thread) {
			switch_thread_join(&st, member->input_thread);
			member->input_thread = NULL;
		}
	}

	switch_core_timer_destroy(&timer);

	if (member->loop_loop) {
		return;
	}

	switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_INFO, "Channel leaving conference, cause: %s\n",
					  switch_channel_cause2str(switch_channel_get_cause(channel)));

	/* if it's an outbound channel, store the release cause in the conference struct, we might need it */
	if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
		member->conference->bridge_hangup_cause = switch_channel_get_cause(channel);
	}
}