freeswitch之esl开发

esl全称Event Socket Library,通过它可以与freeswitch进行交互,执行app和api以及接收事件,esl 支持多种语言java、c\c++、golang,php等等。

esl开发支持inbound和outbound模式。

outbound模式,是FS在单个channel中创建并连接到外部tcp server服务,随着会话的结束而断开socket连接。适合控制单个会话的呼叫和语音控制;而Inbound的连接由客户端主动向FS发起连接,更适合接收所有的事件,进行自动呼叫服务。

开发注意事项:

1、outbound模式中为了避免接收不到挂机信号,可以设置linger超时时间来延时FS挂断socket连接。

2、接收事件采用队列模型把原始事件对象先入列,然后开线程处理线程中的事件对象,以避免丢掉事件。

outbound例子:

#include 
#include 
#include 

typedef struct{
	esl_handle_t *handle;
	int running;
}esl_callback_t;

static void *event_thread(esl_thread_t *me, void *obj)
{ 
    int done = 0;
	time_t exp = 0;
	esl_status_t status;
	esl_callback_t *callback = (esl_callback_t *)obj;
	esl_handle_t *handle = callback->handle;
	
	while((status = esl_recv_timed(handle, 1000)) != ESL_FAIL) {
		if (done) {
			if (time(NULL) >= exp) {
				esl_log(ESL_LOG_INFO, "10 seconds timeout.\n");
				callback->running = 0;
				break;
			}
		} else if (status == ESL_SUCCESS) {
			const char *type = esl_event_get_header(handle->last_event, "content-type");
			if (type && !strcasecmp(type, "text/disconnect-notice")) {
				const char *dispo = esl_event_get_header(handle->last_event, "content-disposition");
				esl_log(ESL_LOG_INFO, "Got a disconnection notice dispostion: [%s]\n", dispo ? dispo : "");
				if (dispo && !strcmp(dispo, "linger")) {
					done = 1;
					esl_log(ESL_LOG_INFO, "Waiting 10 seconds for any remaining events.\n");
					exp = time(NULL) + 10;
				}
			}
		}
	}
}


static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr, void *user_data)
{
	esl_handle_t handle = {{0}};
	esl_callback_t callback = {0};
	

	esl_attach_handle(&handle, client_sock, addr);
	handle.event_lock = 1;

	esl_log(ESL_LOG_INFO, "Connected! %d\n", handle.sock);

	esl_filter(&handle, "unique-id", esl_event_get_header(handle.info_event, "caller-unique-id"));
	esl_events(&handle, ESL_EVENT_TYPE_PLAIN, "CHANNEL_ANSWER CHANNEL_HANGUP CHANNEL_HANGUP_COMPLETE DTMF");

	esl_send_recv(&handle, "linger");
	
	callback.handle = &handle;
	callback.running = 1;
	
	esl_thread_create_detached(event_thread, &callback);

	esl_execute(&handle, "answer", NULL, NULL);
	esl_execute(&handle, "playback", "/home/test.wav", NULL);
	esl_execute(&handle, "sleep", "1000", NULL);
	esl_execute(&handle, "hangup", NULL, NULL);
	
    while(handle.connected && callback.running){
		usleep(10000);
	}
	
	esl_log(ESL_LOG_INFO, "Disconnected! %d\n", handle.sock);
	esl_disconnect(&handle);
}

int main(void)
{
	esl_global_set_default_logger(7);
	esl_listen_threaded("localhost", 8040, mycallback, NULL, 100000);
	
	return 0;
}

inbound例子:

#include 
#include 
#include 


int main(void)
{
	esl_handle_t handle = {{0}};

	esl_connect(&handle, "localhost", 8021, NULL, "ClueCon");

	esl_send_recv(&handle, "api status\n\n");

	if (handle.last_sr_event && handle.last_sr_event->body) {
		printf("%s\n", handle.last_sr_event->body);
	} else {
		// this is unlikely to happen with api or bgapi (which is hardcoded above) but prefix but may be true for other commands
		printf("%s\n", handle.last_sr_reply);
	}

	esl_disconnect(&handle);
	
	return 0;
}

欢迎加入Freeswitch QQ群640880657一起研究讨论。

你可能感兴趣的:(freeswitch)