From 0158e7b848fe8a39ac9a6c9e057f76fb53962f41 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Jan 2009 15:32:10 +0000 Subject: [PATCH] add linger event_socket command to make outbound socket notify channel disconnect and wait for you to terminate git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11255 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/esl/testserver.c | 31 ++++++++-- .../mod_event_socket/mod_event_socket.c | 57 ++++++++++++++++--- 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/libs/esl/testserver.c b/libs/esl/testserver.c index c3e24f4ce0..3e1a8a519b 100644 --- a/libs/esl/testserver.c +++ b/libs/esl/testserver.c @@ -5,7 +5,10 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in addr) { esl_handle_t handle = {{0}}; - + int done = 0; + esl_status_t status; + time_t exp = 0; + if (fork()) { close(client_sock); return; @@ -13,17 +16,37 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc esl_attach_handle(&handle, client_sock, addr); - printf("Connected! %d\n", handle.sock); + 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, "SESSION_HEARTBEAT CHANNEL_ANSWER CHANNEL_ORIGINATE CHANNEL_PROGRESS CHANNEL_HANGUP " "CHANNEL_BRIDGE CHANNEL_UNBRIDGE CHANNEL_OUTGOING CHANNEL_EXECUTE CHANNEL_EXECUTE_COMPLETE DTMF CUSTOM conference::maintenance"); + esl_send_recv(&handle, "linger"); + esl_execute(&handle, "answer", NULL, NULL); esl_execute(&handle, "conference", "3000@default", NULL); - while(esl_recv(&handle) == ESL_SUCCESS); - + while((status = esl_recv_timed(&handle, 1000)) != ESL_FAIL) { + if (done) { + if (time(NULL) >= exp) { + 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 (!strcmp(dispo, "linger")) { + done = 1; + esl_log(ESL_LOG_INFO, "Waiting 5 seconds for any remaining events.\n"); + exp = time(NULL) + 5; + } + } + } + } + + esl_log(ESL_LOG_INFO, "Disconnected! %d\n", handle.sock); esl_disconnect(&handle); } diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index c586161ba2..f5953e0968 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -49,7 +49,9 @@ typedef enum { LFLAG_SESSION = (1 << 6), LFLAG_ASYNC = (1 << 7), LFLAG_STATEFUL = (1 << 8), - LFLAG_OUTBOUND = (1 << 9) + LFLAG_OUTBOUND = (1 << 9), + LFLAG_LINGER = (1 << 10), + LFLAG_HANDLE_DISCO = (1 << 11) } event_flag_t; typedef enum { @@ -1045,22 +1047,21 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, if (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } - + + /* if (channel && !switch_channel_ready(channel)) { status = SWITCH_STATUS_FALSE; break; } + */ clen -= (int) mlen; p += mlen; } - + switch_event_add_body(*event, "%s", body); free(body); } - - - } } } @@ -1158,9 +1159,32 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, } } - if (channel && !switch_channel_ready(channel)) { - status = SWITCH_STATUS_FALSE; - break; + if (channel && !switch_channel_ready(channel) && !switch_test_flag(listener, LFLAG_HANDLE_DISCO)) { + switch_set_flag_locked(listener, LFLAG_HANDLE_DISCO); + if (switch_test_flag(listener, LFLAG_LINGER)) { + char message[128] = ""; + int mlen; + switch_size_t len; + char disco_buf[512] = ""; + + switch_snprintf(message, sizeof(message), + "Channel %s has disconnected, lingering by request from remote.\n", switch_channel_get_name(channel)); + mlen = strlen(message); + + switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\n" + "Controlled-Session-UUID: %s\n" + "Content-Disposition: linger\n" + "Content-Length: %d\n\n", + switch_core_session_get_uuid(listener->session), mlen); + + len = strlen(disco_buf); + switch_socket_send(listener->sock, disco_buf, &len); + len = mlen; + switch_socket_send(listener->sock, message, &len); + } else { + status = SWITCH_STATUS_FALSE; + break; + } } if (do_sleep) { @@ -1580,6 +1604,20 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even } else { switch_snprintf(reply, reply_len, "-ERR invalid log level"); } + } else if (!strncasecmp(cmd, "linger", 6)) { + if (listener->session) { + switch_set_flag_locked(listener, LFLAG_LINGER); + switch_snprintf(reply, reply_len, "+OK will linger"); + } else { + switch_snprintf(reply, reply_len, "-ERR not controlling a session"); + } + } else if (!strncasecmp(cmd, "nolinger", 6)) { + if (listener->session) { + switch_clear_flag_locked(listener, LFLAG_LINGER); + switch_snprintf(reply, reply_len, "+OK will not linger"); + } else { + switch_snprintf(reply, reply_len, "-ERR not controlling a session"); + } } else if (!strncasecmp(cmd, "nolog", 5)) { flush_listener(listener, SWITCH_TRUE, SWITCH_FALSE); if (switch_test_flag(listener, LFLAG_LOG)) { @@ -1926,6 +1964,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) if (listener->session) { switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\n" "Controlled-Session-UUID: %s\n" + "Content-Disposition: disconnect\n" "Content-Length: %d\n\n", switch_core_session_get_uuid(listener->session), mlen); } else {