diff --git a/Makefile.am b/Makefile.am index df1ee2e0d0..8d35068c35 100644 --- a/Makefile.am +++ b/Makefile.am @@ -251,7 +251,8 @@ libfreeswitch_la_SOURCES = \ libs/miniupnpc/upnperrors.c \ libs/libnatpmp/natpmp.c \ libs/libnatpmp/getgateway.c\ - libs/spandsp/src/plc.c + libs/spandsp/src/plc.c \ + libs/spandsp/src/bit_operations.c if ENABLE_CPP libfreeswitch_la_SOURCES += src/switch_cpp.cpp diff --git a/build/modules.conf.in b/build/modules.conf.in index 69d90a8dd4..2be000f6b3 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -35,6 +35,7 @@ applications/mod_valet_parking #applications/mod_snapshot #applications/mod_snipe_hunt #applications/mod_callcenter +#applications/mod_fsk codecs/mod_g723_1 codecs/mod_amr #codecs/mod_amrwb diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 51c62f2059..b7100bd304 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -56,6 +56,7 @@ + diff --git a/libs/.gitignore b/libs/.gitignore index cc42ba4fa4..b31646500e 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -1001,6 +1001,7 @@ /unimrcp/build/acmacros/lt~obsolete.m4 /*.tar.gz /celt-0.7.1/ +/celt-0.10.0/ /flite-1.3.99/ /freeradius-client-1.1.6/ /iksemel/test/tst-dom diff --git a/libs/freetdm/bootstrap b/libs/freetdm/bootstrap index 8ca4856832..247d396da5 100755 --- a/libs/freetdm/bootstrap +++ b/libs/freetdm/bootstrap @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh autoheader libtoolize --force --copy aclocal diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index f50d26c290..778c5f403f 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -4177,6 +4177,19 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load) freetdm_endpoint_interface->state_handler = &freetdm_state_handlers; SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ft_function, FT_SYNTAX); + switch_console_set_complete("add ftdm start"); + switch_console_set_complete("add ftdm stop"); + switch_console_set_complete("add ftdm retart"); + switch_console_set_complete("add ftdm dump"); + switch_console_set_complete("add ftdm sigstatus get"); + switch_console_set_complete("add ftdm sigstatus set"); + switch_console_set_complete("add ftdm trace"); + switch_console_set_complete("add ftdm notrace"); + switch_console_set_complete("add ftdm q931_pcap"); + switch_console_set_complete("add ftdm gains"); + switch_console_set_complete("add ftdm dtmf on"); + switch_console_set_complete("add ftdm dtmf off"); + SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "disable_dtmf", "Disable DTMF Detection", "Disable DTMF Detection", disable_dtmf_function, "", SAF_NONE); diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index cbaff7be54..211dcd0f6e 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -634,6 +634,10 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span) ftdm_mutex_lock(span->mutex); /* stop the signaling */ + + /* This is a forced stopped */ + ftdm_clear_flag(span, FTDM_SPAN_NON_STOPPABLE); + ftdm_span_stop(span); /* destroy the channels */ @@ -739,6 +743,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span) ftdm_status_t status = FTDM_SUCCESS; ftdm_mutex_lock(span->mutex); + + if (ftdm_test_flag(span, FTDM_SPAN_NON_STOPPABLE)) { + status = FTDM_NOTIMPL; + goto done; + } if (!ftdm_test_flag(span, FTDM_SPAN_STARTED)) { status = FTDM_EINVAL; @@ -2288,7 +2297,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1); break; case FTDM_CHANNEL_INDICATE_PROCEED: - if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) { + if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE) || + ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) { ftdm_ack_indication(ftdmchan, indication, status); goto done; } @@ -2929,23 +2939,27 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co case FTDM_COMMAND_ENABLE_DTMF_DETECT: { /* if they don't have thier own, use ours */ - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { - teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n"); - GOTO_STATUS(done, FTDM_SUCCESS); + if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { + teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n"); + GOTO_STATUS(done, FTDM_SUCCESS); + } } } break; case FTDM_COMMAND_DISABLE_DTMF_DETECT: { - if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { - teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n"); - GOTO_STATUS(done, FTDM_SUCCESS); + if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) { + if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { + teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); + ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n"); + GOTO_STATUS(done, FTDM_SUCCESS); + } } } break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 01b2890bf1..f1e0bf45ce 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -1094,6 +1094,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE); ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES); + ftdm_set_flag(span, FTDM_SPAN_NON_STOPPABLE); if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || span->trunk_type == FTDM_TRUNK_BRI) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 912d061963..2b43e9cea5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -133,13 +133,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) get_redir_num(ftdmchan, &conEvnt->redirNmb); get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad); get_prog_ind_ie(ftdmchan, &conEvnt->progInd); - get_facility_ie(ftdmchan, &conEvnt->facilityStr); + get_facility_ie(ftdmchan, &conEvnt->facilityStr); if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) { get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr); } - ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); if (conEvnt->bearCap[0].eh.pres) { @@ -147,10 +146,17 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); } - if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) { if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) { - snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]); + uint8_t encoding = (conEvnt->ni2OctStr.str.val[2] >> 5); + if (encoding == 0 || encoding == 1) { + /* BCD even or BCD odd */ + uint8_t value = (conEvnt->ni2OctStr.str.val[3] & 0x0F)*10 + ((conEvnt->ni2OctStr.str.val[3] >> 4) & 0x0F); + snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", value); + } else if (encoding == 2) { + /* IA 5 */ + snprintf(ftdmchan->caller_data.aniII, 5, "%c", conEvnt->ni2OctStr.str.val[3]); + } } } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 1591fb2a0e..9b4b7872c4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -39,7 +39,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) ConEvnt conEvnt; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; - ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_ORIG_NISDN}; + ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID}; ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n"); diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index d79835733b..3bc986d7f6 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -186,6 +186,9 @@ typedef enum { /* If this flag is set, the signalling module supports jumping directly to state up, without going through PROGRESS/PROGRESS_MEDIA */ FTDM_SPAN_USE_SKIP_STATES = (1 << 12), + /* If this flag is set, then this span cannot be stopped individually, it can only be stopped + on freetdm unload */ + FTDM_SPAN_NON_STOPPABLE = (1 << 13), } ftdm_span_flag_t; /*! \brief Channel supported features */ diff --git a/libs/xmlrpc-c/lib/abyss/src/socket_win.c b/libs/xmlrpc-c/lib/abyss/src/socket_win.c index 92b2b99cfb..d3f683a439 100644 --- a/libs/xmlrpc-c/lib/abyss/src/socket_win.c +++ b/libs/xmlrpc-c/lib/abyss/src/socket_win.c @@ -9,8 +9,7 @@ #include #include #include -#include -#include +#include #include "xmlrpc_config.h" #include "xmlrpc-c/util_int.h" @@ -249,6 +248,7 @@ struct socketWin { SOCKET winsock; bool userSuppliedWinsock; /* 'socket' was supplied by the user; it belongs to him */ + HANDLE interruptEvent; }; static @@ -322,6 +322,8 @@ channelDestroy(TChannel * const channelP) { if (!socketWinP->userSuppliedWinsock) closesocket(socketWinP->winsock); + CloseHandle(socketWinP->interruptEvent); + free(socketWinP); } @@ -430,9 +432,9 @@ channelWait(TChannel * const channelP, timedOut = TRUE; break; case -1: /* socket error */ - if (errno != EINTR) + if (WSAGetLastError() != WSAEINTR) failed = TRUE; - break; + break; default: if (FD_ISSET(socketWinP->winsock, &rfds)) readRdy = TRUE; @@ -460,7 +462,9 @@ channelInterrupt(TChannel * const channelP) { now or in the future. Actually, this is just a no-op because we don't yet know how to - accomplish that. + accomplish that. (But we could probably do it the same way + chanSwitchInterrupt() works -- no one has needed it enough yet to do that + work). -----------------------------------------------------------------------------*/ } @@ -484,7 +488,7 @@ ChannelWinGetPeerName(TChannel * const channelP, if (rc != 0) { int const lastError = WSAGetLastError(); - xmlrpc_asprintf(errorP, "getpeername() failed. WSAERROR = %d (%s)", + xmlrpc_asprintf(errorP, "getpeername() failed. WSA error = %d (%s)", lastError, getWSAError(lastError)); } else { if (addrlen != sizeof(sockAddr)) @@ -581,7 +585,8 @@ makeChannelFromWinsock(SOCKET const winsock, socketWinP->winsock = winsock; socketWinP->userSuppliedWinsock = TRUE; - + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + ChannelCreate(&channelVtbl, socketWinP, &channelP); if (channelP == NULL) @@ -591,8 +596,10 @@ makeChannelFromWinsock(SOCKET const winsock, *channelPP = channelP; *errorP = NULL; } - if (*errorP) + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); free(socketWinP); + } } } @@ -632,7 +639,7 @@ ChannelWinCreateWinsock(SOCKET const fd, socklen_t peerAddrLen; int rc; - peerAddrLen = sizeof(peerAddrLen); + peerAddrLen = sizeof(peerAddr); rc = getpeername(fd, &peerAddr, &peerAddrLen); @@ -676,6 +683,8 @@ chanSwitchDestroy(TChanSwitch * const chanSwitchP) { if (!socketWinP->userSuppliedWinsock) closesocket(socketWinP->winsock); + CloseHandle(socketWinP->interruptEvent); + free(socketWinP); } @@ -711,6 +720,49 @@ chanSwitchListen(TChanSwitch * const chanSwitchP, +static void +createChannelForAccept(int const acceptedWinsock, + struct sockaddr const peerAddr, + TChannel ** const channelPP, + void ** const channelInfoPP, + const char ** const errorP) { + + struct abyss_win_chaninfo * channelInfoP; + makeChannelInfo(&channelInfoP, peerAddr, sizeof(peerAddr), errorP); + if (!*errorP) { + struct socketWin * acceptedSocketP; + + MALLOCVAR(acceptedSocketP); + + if (!acceptedSocketP) + xmlrpc_asprintf(errorP, "Unable to allocate memory"); + else { + TChannel * channelP; + + acceptedSocketP->winsock = acceptedWinsock; + acceptedSocketP->userSuppliedWinsock = FALSE; + acceptedSocketP->interruptEvent = + CreateEvent(NULL, FALSE, FALSE, NULL); + + ChannelCreate(&channelVtbl, acceptedSocketP, &channelP); + if (!channelP) + xmlrpc_asprintf(errorP, + "Failed to create TChannel object."); + else { + *errorP = NULL; + *channelPP = channelP; + *channelInfoPP = channelInfoP; + } + if (*errorP) { + CloseHandle(acceptedSocketP->interruptEvent); + free(acceptedSocketP); + } + } + } +} + + + static SwitchAcceptImpl chanSwitchAccept; static void @@ -728,7 +780,7 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP, *channelPP == NULL. -----------------------------------------------------------------------------*/ struct socketWin * const listenSocketP = chanSwitchP->implP; - + HANDLE acceptEvent = WSACreateEvent(); bool interrupted; TChannel * channelP; @@ -736,46 +788,44 @@ chanSwitchAccept(TChanSwitch * const chanSwitchP, channelP = NULL; /* No connection yet */ *errorP = NULL; /* No error yet */ + WSAEventSelect(listenSocketP->winsock, acceptEvent, + FD_ACCEPT | FD_CLOSE | FD_READ); + while (!channelP && !*errorP && !interrupted) { + HANDLE interrupts[2] = {acceptEvent, listenSocketP->interruptEvent}; + int rc; struct sockaddr peerAddr; socklen_t size = sizeof(peerAddr); - int rc; + + rc = WaitForMultipleObjects(2, interrupts, FALSE, INFINITE); + if (WAIT_OBJECT_0 + 1 == rc) { + interrupted = TRUE; + continue; + }; rc = accept(listenSocketP->winsock, &peerAddr, &size); if (rc >= 0) { int const acceptedWinsock = rc; - struct socketWin * acceptedSocketP; - MALLOCVAR(acceptedSocketP); + createChannelForAccept(acceptedWinsock, peerAddr, + &channelP, channelInfoPP, errorP); - if (!acceptedSocketP) - xmlrpc_asprintf(errorP, "Unable to allocate memory"); - else { - acceptedSocketP->winsock = acceptedWinsock; - acceptedSocketP->userSuppliedWinsock = FALSE; - - *channelInfoPP = NULL; - - ChannelCreate(&channelVtbl, acceptedSocketP, &channelP); - if (!channelP) - xmlrpc_asprintf(errorP, - "Failed to create TChannel object."); - else - *errorP = NULL; - - if (*errorP) - free(acceptedSocketP); - } if (*errorP) closesocket(acceptedWinsock); - } else if (errno == EINTR) - interrupted = TRUE; - else - xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)", - errno, strerror(errno)); + } else { + int const lastError = WSAGetLastError(); + + if (lastError == WSAEINTR) + interrupted = TRUE; + else + xmlrpc_asprintf(errorP, + "accept() failed, WSA error = %d (%s)", + lastError, getWSAError(lastError)); + } } *channelPP = channelP; + CloseHandle(acceptEvent); } @@ -787,15 +837,10 @@ chanSwitchInterrupt(TChanSwitch * const chanSwitchP) { /*---------------------------------------------------------------------------- Interrupt any waiting that a thread might be doing in chanSwitchAccept() now or in the future. - - Actually, this is just a no-op because we don't yet know how to - accomplish that. -----------------------------------------------------------------------------*/ - struct socketWin * const socketWinP = chanSwitchP->implP; - - if (!socketWinP->userSuppliedWinsock) - closesocket(socketWinP->winsock); + struct socketWin * const listenSocketP = chanSwitchP->implP; + SetEvent(listenSocketP->interruptEvent); } @@ -889,6 +934,7 @@ ChanSwitchWinCreate(uint16_t const portNumber, } else { socketWinP->winsock = winsock; socketWinP->userSuppliedWinsock = FALSE; + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); setSocketOptions(socketWinP->winsock, errorP); if (!*errorP) { @@ -899,8 +945,10 @@ ChanSwitchWinCreate(uint16_t const portNumber, chanSwitchPP); } - if (*errorP) + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); closesocket(winsock); + } } if (*errorP) free(socketWinP); @@ -929,7 +977,8 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock, socketWinP->winsock = winsock; socketWinP->userSuppliedWinsock = TRUE; - + socketWinP->interruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + ChanSwitchCreate(&chanSwitchVtbl, socketWinP, &chanSwitchP); if (chanSwitchP == NULL) @@ -939,8 +988,10 @@ ChanSwitchWinCreateWinsock(SOCKET const winsock, *chanSwitchPP = chanSwitchP; *errorP = NULL; } - if (*errorP) + if (*errorP) { + CloseHandle(socketWinP->interruptEvent); free(socketWinP); + } } } } diff --git a/src/include/switch_core.h b/src/include/switch_core.h index ff131acb17..29e8b43526 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -116,7 +116,6 @@ struct switch_core_session; struct switch_core_runtime; struct switch_core_port_allocator; - /*! \defgroup core1 Core Library \ingroup FREESWITCH @@ -713,6 +712,7 @@ SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *sessio SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine); SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session); +SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data); /*! \brief Retrieve the unique identifier from the core diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 1cf01c54bc..114e594c0c 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -711,6 +711,14 @@ struct switch_api_interface { #define PROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_rdlock(_it->parent->rwlock); switch_thread_rwlock_rdlock(_it->rwlock); _it->refs++; _it->parent->refs++; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "+++++++++++LOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs); #define UNPROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_unlock(_it->rwlock); switch_thread_rwlock_unlock(_it->parent->rwlock); _it->refs--; _it->parent->refs--; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "---------UNLOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs); +#include "switch_frame.h" + +struct switch_slin_data { + switch_core_session_t *session; + switch_frame_t write_frame; + switch_codec_t codec; + char frame_data[SWITCH_RECOMMENDED_BUFFER_SIZE]; +}; SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_odbc.h b/src/include/switch_odbc.h index f76384003a..103fe0f0d7 100644 --- a/src/include/switch_odbc.h +++ b/src/include/switch_odbc.h @@ -34,6 +34,8 @@ #include +#define DEFAULT_ODBC_RETRIES 120 + SWITCH_BEGIN_EXTERN_C struct switch_odbc_handle; typedef void *switch_odbc_statement_handle_t; @@ -50,6 +52,7 @@ typedef enum { } switch_odbc_status_t; SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, const char *username, const char *password); +SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries); SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle); SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle); SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 01f890d51c..9a5e09db7c 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -632,9 +632,13 @@ typedef enum { This flag will never send any. Sheesh.... */ + RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6) - - + /* + Guess Who? ... Yep, Sonus (and who know's who else) likes to interweave DTMF with the audio stream making it take + 2X as long as it should and sending an incorrect duration making the DTMF very delayed. + This flag will treat every dtmf as if it were 50ms and queue it on recipt of the leading packet rather than at the end. + */ } switch_rtp_bug_flag_t; @@ -1817,6 +1821,8 @@ typedef struct switch_loadable_module_function_table { typedef int (*switch_modulename_callback_func_t) (void *user_data, const char *module_name); +typedef struct switch_slin_data switch_slin_data_t; + #define SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags) \ static const char modname[] = #name ; \ SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \ diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 4602dd2bc5..41417255bb 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1485,6 +1485,8 @@ SWITCH_STANDARD_APP(ivr_application_function) } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to find menu\n"); } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No menus configured\n"); } switch_xml_free(cxml); } else { diff --git a/src/mod/applications/mod_fsk/Makefile b/src/mod/applications/mod_fsk/Makefile new file mode 100644 index 0000000000..620f3f751c --- /dev/null +++ b/src/mod/applications/mod_fsk/Makefile @@ -0,0 +1,6 @@ +BASE=../../../.. + +LOCAL_SOURCES=fsk.c uart.c fsk_callerid.c +LOCAL_OBJS=fsk.o uart.o fsk_callerid.o +include $(BASE)/build/modmake.rules + diff --git a/src/mod/applications/mod_fsk/fsk.c b/src/mod/applications/mod_fsk/fsk.c new file mode 100644 index 0000000000..773b0deaae --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk.c @@ -0,0 +1,351 @@ + +/* + * bell202.c + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This module contains a Bell-202 1200-baud FSK decoder, suitable for + * use in a library. The general style of the library calls is modeled + * after the POSIX pthread_*() functions. + * + * 2005 03 20 R. Krten created +*/ + +#include +#include +#include +#include +#include + +#include "fsk.h" +#include "uart.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +fsk_modem_definition_t fsk_modem_definitions[] = +{ + { /* FSK_V23_FORWARD_MODE1 */ 1700, 1300, 600 }, + { /* FSK_V23_FORWARD_MODE2 */ 2100, 1300, 1200 }, + { /* FSK_V23_BACKWARD */ 450, 390, 75 }, + { /* FSK_BELL202 */ 2200, 1200, 1200 }, +}; + +/* + * dsp_fsk_attr_init + * + * Initializes the attributes structure; this must be done before the + * attributes structure is used. +*/ + +void dsp_fsk_attr_init (dsp_fsk_attr_t *attr) +{ + memset(attr, 0, sizeof(*attr)); +} + +/* + * dsp_fsk_attr_get_bithandler + * dsp_fsk_attr_set_bithandler + * dsp_fsk_attr_get_bytehandler + * dsp_fsk_attr_set_bytehandler + * dsp_fsk_attr_getsamplerate + * dsp_fsk_attr_setsamplerate + * + * These functions get and set their respective elements from the + * attributes structure. If an error code is returned, it is just + * zero == ok, -1 == fail. +*/ + +bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attr, void **bithandler_arg) +{ + *bithandler_arg = attr->bithandler_arg; + return attr->bithandler; +} + +void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attr, bithandler_func_t bithandler, void *bithandler_arg) +{ + attr->bithandler = bithandler; + attr->bithandler_arg = bithandler_arg; +} + +bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attr, void **bytehandler_arg) +{ + *bytehandler_arg = attr->bytehandler_arg; + return attr->bytehandler; +} + +void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg) +{ + attr->bytehandler = bytehandler; + attr->bytehandler_arg = bytehandler_arg; +} + +int dsp_fsk_attr_get_samplerate (dsp_fsk_attr_t *attr) +{ + return attr->sample_rate; +} + +int dsp_fsk_attr_set_samplerate (dsp_fsk_attr_t *attr, int samplerate) +{ + if (samplerate <= 0) { + return -1; + } + attr->sample_rate = samplerate; + return 0; +} + +/* + * dsp_fsk_create + * + * Creates a handle for subsequent use. The handle is created to contain + * a context data structure for use by the sample handler function. The + * function expects an initialized attributes structure, and returns the + * handle or a NULL if there were errors. + * + * Once created, the handle can be used until it is destroyed. +*/ + +dsp_fsk_handle_t *dsp_fsk_create(dsp_fsk_attr_t *attr) +{ + int i; + double phi_mark, phi_space; + dsp_fsk_handle_t *handle; + + handle = malloc(sizeof(*handle)); + if (!handle) { + return NULL; + } + + memset(handle, 0, sizeof(*handle)); + + /* fill the attributes member */ + memcpy(&handle->attr, attr, sizeof(*attr)); + + /* see if we can do downsampling. We only really need 6 samples to "match" */ + if (attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark > 6) { + handle->downsampling_count = attr->sample_rate / fsk_modem_definitions[FSK_BELL202].freq_mark / 6; + } else { + handle->downsampling_count = 1; + } + handle->current_downsample = 1; + + /* calculate the correlate size (number of samples required for slowest wave) */ + handle->corrsize = attr->sample_rate / handle->downsampling_count / fsk_modem_definitions[FSK_BELL202].freq_mark; + + /* allocate the correlation sin/cos arrays and initialize */ + for (i = 0; i < 4; i++) { + handle->correlates[i] = malloc(sizeof(double) * handle->corrsize); + if (handle->correlates[i] == NULL) { + /* some failed, back out memory allocations */ + dsp_fsk_destroy(&handle); + return NULL; + } + } + + /* now initialize them */ + phi_mark = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_mark); + phi_space = 2. * M_PI / ((double) attr->sample_rate / (double) handle->downsampling_count / (double) fsk_modem_definitions[FSK_BELL202].freq_space); + + for (i = 0; i < handle->corrsize; i++) { + handle->correlates[0][i] = sin(phi_mark * (double) i); + handle->correlates[1][i] = cos(phi_mark * (double) i); + handle->correlates[2][i] = sin(phi_space * (double) i); + handle->correlates[3][i] = cos(phi_space * (double) i); + } + + /* initialize the ring buffer */ + handle->buffer = malloc(sizeof(double) * handle->corrsize); + if (!handle->buffer) { /* failed; back out memory allocations */ + dsp_fsk_destroy(&handle); + return NULL; + } + memset(handle->buffer, 0, sizeof(double) * handle->corrsize); + handle->ringstart = 0; + + /* initalize intra-cell position */ + handle->cellpos = 0; + handle->celladj = fsk_modem_definitions[FSK_BELL202].baud_rate / (double) attr->sample_rate * (double) handle->downsampling_count; + + /* if they have provided a byte handler, add a UART to the processing chain */ + if (handle->attr.bytehandler) { + dsp_uart_attr_t uart_attr; + dsp_uart_handle_t *uart_handle; + + dsp_uart_attr_init(&uart_attr); + dsp_uart_attr_set_bytehandler(&uart_attr, handle->attr.bytehandler, handle->attr.bytehandler_arg); + uart_handle = dsp_uart_create(&uart_attr); + if (uart_handle == NULL) { + dsp_fsk_destroy(&handle); + return NULL; + } + handle->attr.bithandler = dsp_uart_bit_handler; + handle->attr.bithandler_arg = uart_handle; + } + + return handle; +} + +/* + * dsp_fsk_destroy + * + * Destroys a handle, releasing any associated memory. Sets handle pointer to NULL + * so A destroyed handle can not be used for anything after the destroy. +*/ + +void dsp_fsk_destroy(dsp_fsk_handle_t **handle) +{ + int i; + + /* if empty handle, just return */ + if (*handle == NULL) { + return; + } + + for (i = 0; i < 4; i++) { + if ((*handle)->correlates[i] != NULL) { + free((*handle)->correlates[i]); + (*handle)->correlates[i] = NULL; + } + } + + if ((*handle)->buffer != NULL) { + free((*handle)->buffer); + (*handle)->buffer = NULL; + } + + if ((*handle)->attr.bytehandler) { + dsp_uart_handle_t** dhandle = (void *)(&(*handle)->attr.bithandler_arg); + dsp_uart_destroy(dhandle); + } + + free(*handle); + *handle = NULL; +} + +/* + * dsp_fsk_sample + * + * This is the main processing entry point. The function accepts a normalized + * sample (i.e., one whose range is between -1 and +1). The function performs + * the Bell-202 FSK modem decode processing, and, if it detects a valid bit, + * will call the bithandler associated with the attributes structure. + * + * For the Bell-202 standard, a logical zero (space) is 2200 Hz, and a logical + * one (mark) is 1200 Hz. +*/ + +void +dsp_fsk_sample (dsp_fsk_handle_t *handle, double normalized_sample) +{ + double val; + double factors[4]; + int i, j; + + /* if we can avoid processing samples, do so */ + if (handle->downsampling_count != 1) { + if (handle->current_downsample < handle->downsampling_count) { + handle->current_downsample++; + return; /* throw this sample out */ + } + handle->current_downsample = 1; + } + + /* store sample in buffer */ + handle->buffer[handle->ringstart++] = normalized_sample; + if (handle->ringstart >= handle->corrsize) { + handle->ringstart = 0; + } + + /* do the correlation calculation */ + factors[0] = factors[1] = factors[2] = factors[3] = 0; /* clear out intermediate sums */ + j = handle->ringstart; + for (i = 0; i < handle->corrsize; i++) { + if (j >= handle->corrsize) { + j = 0; + } + val = handle->buffer[j]; + factors[0] += handle->correlates[0][i] * val; + factors[1] += handle->correlates[1][i] * val; + factors[2] += handle->correlates[2][i] * val; + factors[3] += handle->correlates[3][i] * val; + j++; + } + + /* store the bit (bit value is comparison of the two sets of correlate factors) */ + handle->previous_bit = handle->current_bit; + handle->current_bit = (factors[0] * factors[0] + factors[1] * factors[1] > factors[2] * factors[2] + factors[3] * factors[3]); + + /* if there's a transition, we can synchronize the cell position */ + if (handle->previous_bit != handle->current_bit) { + handle->cellpos = 0.5; /* adjust cell position to be in the middle of the cell */ + } + handle->cellpos += handle->celladj; /* walk the cell along */ + + if (handle->cellpos > 1.0) { + handle->cellpos -= 1.0; + + switch (handle->state) { + case FSK_STATE_DATA: + { + + (*handle->attr.bithandler) (handle->attr.bithandler_arg, handle->current_bit); + } + break; + case FSK_STATE_CHANSEIZE: + { + + if (handle->last_bit != handle->current_bit) { + handle->conscutive_state_bits++; + } else { + handle->conscutive_state_bits = 0; + } + + if (handle->conscutive_state_bits > 15) { + handle->state = FSK_STATE_CARRIERSIG; + handle->conscutive_state_bits = 0; + } + } + break; + case FSK_STATE_CARRIERSIG: + { + if (handle->current_bit) { + handle->conscutive_state_bits++; + } else { + handle->conscutive_state_bits = 0; + } + + if (handle->conscutive_state_bits > 15) { + handle->state = FSK_STATE_DATA; + handle->conscutive_state_bits = 0; + } + } + break; + } + + handle->last_bit = handle->current_bit; + } +} + diff --git a/src/mod/applications/mod_fsk/fsk.h b/src/mod/applications/mod_fsk/fsk.h new file mode 100644 index 0000000000..b098444d03 --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk.h @@ -0,0 +1,113 @@ +/* + * bell202.h + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This module contains the manifest constants and declarations for + * the Bell-202 1200 baud FSK modem. + * + * 2005 03 20 R. Krten created +*/ + +#ifndef __FSK_H__ +#define __FSK_H__ +#include "uart.h" + +typedef struct { + int freq_space; /* Frequency of the 0 bit */ + int freq_mark; /* Frequency of the 1 bit */ + int baud_rate; /* baud rate for the modem */ +} fsk_modem_definition_t; + +/* Must be kept in sync with fsk_modem_definitions array in fsk.c */ +/* V.23 definitions: http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-V.23 */ +typedef enum { + FSK_V23_FORWARD_MODE1 = 0, /* Maximum 600 bps for long haul */ + FSK_V23_FORWARD_MODE2, /* Standard 1200 bps V.23 */ + FSK_V23_BACKWARD, /* 75 bps return path for V.23 */ + FSK_BELL202 /* Bell 202 half-duplex 1200 bps */ +} fsk_modem_types_t; + +typedef enum { + FSK_STATE_CHANSEIZE = 0, + FSK_STATE_CARRIERSIG, + FSK_STATE_DATA +} fsk_state_t; + +typedef struct dsp_fsk_attr_s +{ + int sample_rate; /* sample rate in HZ */ + bithandler_func_t bithandler; /* bit handler */ + void *bithandler_arg; /* arbitrary ID passed to bithandler as first argument */ + bytehandler_func_t bytehandler; /* byte handler */ + void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */ +} dsp_fsk_attr_t; + +typedef struct +{ + fsk_state_t state; + dsp_fsk_attr_t attr; /* attributes structure */ + double *correlates[4]; /* one for each of sin/cos for mark/space */ + int corrsize; /* correlate size (also number of samples in ring buffer) */ + double *buffer; /* sample ring buffer */ + int ringstart; /* ring buffer start offset */ + double cellpos; /* bit cell position */ + double celladj; /* bit cell adjustment for each sample */ + int previous_bit; /* previous bit (for detecting a transition to sync-up cell position) */ + int current_bit; /* current bit */ + int last_bit; + int downsampling_count; /* number of samples to skip */ + int current_downsample; /* current skip count */ + int conscutive_state_bits; /* number of bits in a row that matches the pattern for the current state */ +} dsp_fsk_handle_t; + +/* + * Function prototypes + * + * General calling order is: + * a) create the attributes structure (dsp_fsk_attr_init) + * b) initialize fields in the attributes structure (dsp_fsk_attr_set_*) + * c) create a Bell-202 handle (dsp_fsk_create) + * d) feed samples through the handler (dsp_fsk_sample) +*/ + +void dsp_fsk_attr_init(dsp_fsk_attr_t *attributes); + +bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attributes, void **bithandler_arg); +void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attributes, bithandler_func_t bithandler, void *bithandler_arg); +bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attributes, void **bytehandler_arg); +void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg); +int dsp_fsk_attr_get_samplerate(dsp_fsk_attr_t *attributes); +int dsp_fsk_attr_set_samplerate(dsp_fsk_attr_t *attributes, int samplerate); + +dsp_fsk_handle_t * dsp_fsk_create(dsp_fsk_attr_t *attributes); +void dsp_fsk_destroy(dsp_fsk_handle_t **handle); + +void dsp_fsk_sample(dsp_fsk_handle_t *handle, double normalized_sample); + +extern fsk_modem_definition_t fsk_modem_definitions[]; + +#endif + diff --git a/src/mod/applications/mod_fsk/fsk_callerid.c b/src/mod/applications/mod_fsk/fsk_callerid.c new file mode 100644 index 0000000000..2146f663c5 --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk_callerid.c @@ -0,0 +1,398 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * mod_fsk -- FSK data transfer + * + */ + +#include "switch.h" +#include "fsk_callerid.h" + +void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss) +{ + memset(bsp, 0, sizeof(*bsp)); + bsp->data = data; + bsp->datalen = datalen; + bsp->endian = endian; + bsp->ss = ss; + + if (endian < 0) { + bsp->top = bsp->bit_index = 7; + bsp->bot = 0; + } else { + bsp->top = bsp->bit_index = 0; + bsp->bot = 7; + } + +} + +int8_t bitstream_get_bit(bitstream_t *bsp) +{ + int8_t bit = -1; + + + if (bsp->byte_index >= bsp->datalen) { + goto done; + } + + if (bsp->ss) { + if (!bsp->ssv) { + bsp->ssv = 1; + return 0; + } else if (bsp->ssv == 2) { + bsp->byte_index++; + bsp->ssv = 0; + return 1; + } + } + + bit = (bsp->data[bsp->byte_index] >> (bsp->bit_index)) & 1; + + if (bsp->bit_index == bsp->bot) { + bsp->bit_index = bsp->top; + if (bsp->ss) { + bsp->ssv = 2; + goto done; + } + + if (++bsp->byte_index > bsp->datalen) { + bit = -1; + goto done; + } + + } else { + bsp->bit_index = bsp->bit_index + bsp->endian; + } + + + done: + return bit; +} + + + +static void fsk_byte_handler (void *x, int data) +{ + fsk_data_state_t *state = (fsk_data_state_t *) x; + uint8_t byte = (uint8_t)data; + + top: + + if (state->init == 3) { + return; + } + + if (state->dlen) { + goto add_byte; + } + + if (state->bpos == 1) { + state->blen = byte; + + if ((uint32_t)(state->dlen = state->bpos + byte + 2) > state->bufsize) { + state->dlen = state->bufsize; + } + goto top; + } + + add_byte: + + if (state->bpos <= state->dlen) { + state->buf[state->bpos++] = byte; + } else { + state->init = 3; + } +} + +switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen) +{ + memset(state, 0, sizeof(*state)); + state->buf = data; + state->bufsize = datalen; + state->bpos = 2; + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t fsk_data_add_sdmf(fsk_data_state_t *state, const char *date, char *number) +{ + size_t dlen = strlen(date); + size_t nlen = strlen(number); + + state->buf[0] = CID_TYPE_SDMF; + memcpy(&state->buf[state->bpos], date, dlen); + state->bpos += dlen; + memcpy(&state->buf[state->bpos], number, nlen); + state->bpos += nlen; + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen) +{ + state->buf[0] = CID_TYPE_MDMF; + state->buf[state->bpos++] = type; + state->buf[state->bpos++] = (uint8_t)datalen; + memcpy(&state->buf[state->bpos], data, datalen); + state->bpos += datalen; + return SWITCH_STATUS_SUCCESS; +} + + +switch_status_t fsk_data_add_checksum(fsk_data_state_t *state) +{ + uint32_t i; + uint8_t check = 0; + + state->buf[1] = (uint8_t)(state->bpos - 2); + + for (i = 0; i < state->bpos; i++) { + check = check + state->buf[i]; + } + + state->checksum = state->buf[state->bpos] = (uint8_t)(256 - check); + state->bpos++; + + state->dlen = state->bpos; + state->blen = state->buf[1]; + + return SWITCH_STATUS_SUCCESS; +} + + +switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len) +{ + + size_t i; + int sum = 0; + + top: + + if (state->checksum != 0 || state->ppos >= state->dlen - 1) { + return SWITCH_STATUS_FALSE; + } + + if (!state->ppos) { + for(i = 0; i < state->bpos; i++) { + sum += state->buf[i]; + } + state->checksum = sum % 256; + state->ppos = 2; + + if (state->buf[0] != CID_TYPE_MDMF && state->buf[0] != CID_TYPE_SDMF) { + state->checksum = -1; + } + goto top; + } + + if (state->buf[0] == CID_TYPE_SDMF) { + /* convert sdmf to mdmf so we don't need 2 parsers */ + if (state->ppos == 2) { + *type = MDMF_DATETIME; + *len = 8; + } else { + if (state->buf[state->ppos] == 'P' || state->buf[state->ppos] == 'O') { + *type = MDMF_NO_NUM; + *len = 1; + } else { + *type = MDMF_PHONE_NUM; + *len = state->blen - 8; + } + } + *data = (char *)&state->buf[state->ppos]; + state->ppos += *len; + return SWITCH_STATUS_SUCCESS; + } else if (state->buf[0] == CID_TYPE_MDMF) { + *type = state->buf[state->ppos++]; + *len = state->buf[state->ppos++]; + *data = (char *)&state->buf[state->ppos]; + state->ppos += *len; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + +switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples) +{ + uint32_t x; + int16_t *sp = data; + + if (state->init == 3) { + return SWITCH_STATUS_FALSE; + } + + for (x = 0; x < samples; x++) { + dsp_fsk_sample (state->fsk1200_handle, (double) *sp++ / 32767.0); + if (state->dlen && state->bpos >= state->dlen) { + state->init = 3; + return SWITCH_STATUS_FALSE; + } + } + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t fsk_demod_destroy(fsk_data_state_t *state) +{ + dsp_fsk_destroy(&state->fsk1200_handle); + memset(state, 0, sizeof(*state)); + return SWITCH_STATUS_SUCCESS; +} + +int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize) +{ + + dsp_fsk_attr_t fsk1200_attr; + + if (state->fsk1200_handle) { + dsp_fsk_destroy(&state->fsk1200_handle); + } + + memset(state, 0, sizeof(*state)); + memset(buf, 0, bufsize); + state->buf = buf; + state->bufsize = bufsize; + + dsp_fsk_attr_init (&fsk1200_attr); + dsp_fsk_attr_set_samplerate (&fsk1200_attr, rate); + dsp_fsk_attr_set_bytehandler (&fsk1200_attr, fsk_byte_handler, state); + state->fsk1200_handle = dsp_fsk_create (&fsk1200_attr); + + if (state->fsk1200_handle == NULL) { + return SWITCH_STATUS_FALSE; + } + + return SWITCH_STATUS_SUCCESS; +} + +size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen) +{ + size_t i; + + for(i = 0 ; i < buflen; i++) { + fsk_trans->bit_accum += fsk_trans->bit_factor; + if (fsk_trans->bit_accum >= FSK_MOD_FACTOR) { + fsk_trans->bit_accum -= (FSK_MOD_FACTOR + fsk_trans->bit_factor); + break; + } + + buf[i] = teletone_dds_state_modulate_sample(&fsk_trans->dds, bit); + } + + return i; +} + + +int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits) +{ + uint32_t i = 0; + size_t r = 0; + int8_t bit = 1; + + for (i = 0; i < bits; i++) { + if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { + if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) { + break; + } + } else { + break; + } + } + + return i; +} + + +void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans) +{ + uint32_t i = 0; + size_t r = 0; + int8_t bit = 0; + + for (i = 0; i < fsk_trans->chan_sieze_bits; i++) { + if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { + if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) { + break; + } + } else { + break; + } + bit = !bit; + } + + +} + + +void fsk_modulator_send_data(fsk_modulator_t *fsk_trans) +{ + size_t r = 0; + int8_t bit = 0; + + while((bit = bitstream_get_bit(&fsk_trans->bs)) > -1) { + if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) { + if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) { + break; + } + } else { + break; + } + } +} + + +switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans, + fsk_modem_types_t modem_type, + uint32_t sample_rate, + fsk_data_state_t *fsk_data, + float db_level, + uint32_t carrier_bits_start, + uint32_t carrier_bits_stop, + uint32_t chan_sieze_bits, + fsk_write_sample_t write_sample_callback, + void *user_data) +{ + memset(fsk_trans, 0, sizeof(*fsk_trans)); + fsk_trans->modem_type = modem_type; + teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_space, sample_rate, 0); + teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_mark, sample_rate, 1); + fsk_trans->bit_factor = (uint32_t)((fsk_modem_definitions[fsk_trans->modem_type].baud_rate * FSK_MOD_FACTOR) / (float)sample_rate); + fsk_trans->samples_per_bit = (uint32_t) (sample_rate / fsk_modem_definitions[fsk_trans->modem_type].baud_rate); + fsk_trans->est_bytes = (int32_t)(((fsk_data->dlen * 10) + carrier_bits_start + carrier_bits_stop + chan_sieze_bits) * ((fsk_trans->samples_per_bit + 1) * 2)); + fsk_trans->bit_accum = 0; + fsk_trans->fsk_data = fsk_data; + teletone_dds_state_set_tx_level(&fsk_trans->dds, db_level); + bitstream_init(&fsk_trans->bs, fsk_trans->fsk_data->buf, (uint32_t)fsk_trans->fsk_data->dlen, ENDIAN_BIG, 1); + fsk_trans->carrier_bits_start = carrier_bits_start; + fsk_trans->carrier_bits_stop = carrier_bits_stop; + fsk_trans->chan_sieze_bits = chan_sieze_bits; + fsk_trans->write_sample_callback = write_sample_callback; + fsk_trans->user_data = user_data; + return SWITCH_STATUS_SUCCESS; +} + diff --git a/src/mod/applications/mod_fsk/fsk_callerid.h b/src/mod/applications/mod_fsk/fsk_callerid.h new file mode 100644 index 0000000000..9018201ce5 --- /dev/null +++ b/src/mod/applications/mod_fsk/fsk_callerid.h @@ -0,0 +1,144 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * mod_fsk -- FSK data transfer + * + */ +#ifndef __FSK_CALLER_ID_H +#define __FSK_CALLER_ID_H +SWITCH_BEGIN_EXTERN_C +#include "fsk.h" +#include "uart.h" + +#define FSK_MOD_FACTOR 0x10000 + +typedef enum { + ENDIAN_BIG = 1, + ENDIAN_LITTLE = -1 +} endian_t; + +typedef enum { + CID_TYPE_SDMF = 0x04, + CID_TYPE_MDMF = 0x80 +} cid_type_t; + +typedef enum { + MDMF_DATETIME = 1, + MDMF_PHONE_NUM = 2, + MDMF_DDN = 3, + MDMF_NO_NUM = 4, + MDMF_PHONE_NAME = 7, + MDMF_NO_NAME = 8, + MDMF_ALT_ROUTE = 9, + MDMF_NAME_VALUE = 10, + MDMF_INVALID = 11 +} mdmf_type_t; + +struct bitstream { + uint8_t *data; + uint32_t datalen; + uint32_t byte_index; + uint8_t bit_index; + int8_t endian; + uint8_t top; + uint8_t bot; + uint8_t ss; + uint8_t ssv; +}; + +struct fsk_data_state { + dsp_fsk_handle_t *fsk1200_handle; + uint8_t init; + uint8_t *buf; + size_t bufsize; + size_t blen; + size_t bpos; + size_t dlen; + size_t ppos; + int checksum; +}; + +typedef struct bitstream bitstream_t; +typedef struct fsk_data_state fsk_data_state_t; +typedef switch_status_t (*fsk_write_sample_t)(int16_t *buf, size_t buflen, void *user_data); + +struct fsk_modulator { + teletone_dds_state_t dds; + bitstream_t bs; + uint32_t carrier_bits_start; + uint32_t carrier_bits_stop; + uint32_t chan_sieze_bits; + uint32_t bit_factor; + uint32_t bit_accum; + uint32_t sample_counter; + int32_t samples_per_bit; + int32_t est_bytes; + fsk_modem_types_t modem_type; + fsk_data_state_t *fsk_data; + fsk_write_sample_t write_sample_callback; + void *user_data; + int16_t sample_buffer[64]; +}; + + +typedef int (*fsk_data_decoder_t)(fsk_data_state_t *state); + +typedef void (*logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...); +typedef struct fsk_modulator fsk_modulator_t; + +switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen); +void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss); +int8_t bitstream_get_bit(bitstream_t *bsp); +switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen); +switch_status_t fsk_data_add_checksum(fsk_data_state_t *state); +switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len); +switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples); +switch_status_t fsk_demod_destroy(fsk_data_state_t *state); +int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize); +size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen); +int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits); +void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans); +void fsk_modulator_send_data(fsk_modulator_t *fsk_trans); +switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans, + fsk_modem_types_t modem_type, + uint32_t sample_rate, + fsk_data_state_t *fsk_data, + float db_level, + uint32_t carrier_bits_start, + uint32_t carrier_bits_stop, + uint32_t chan_sieze_bits, + fsk_write_sample_t write_sample_callback, + void *user_data); + + +#define fsk_modulator_send_all(_it) fsk_modulator_generate_chan_sieze(_it); \ + fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_start); \ + fsk_modulator_send_data(_it); \ + fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_stop) + +SWITCH_END_EXTERN_C +#endif diff --git a/src/mod/applications/mod_fsk/mod_fsk.c b/src/mod/applications/mod_fsk/mod_fsk.c new file mode 100644 index 0000000000..9802353075 --- /dev/null +++ b/src/mod/applications/mod_fsk/mod_fsk.c @@ -0,0 +1,486 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * mod_fsk.c -- FSK data transfer + * + */ +#include +#include "fsk_callerid.h" + +/* Prototypes */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fsk_shutdown); +SWITCH_MODULE_RUNTIME_FUNCTION(mod_fsk_runtime); +SWITCH_MODULE_LOAD_FUNCTION(mod_fsk_load); + +/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) + * Defines a switch_loadable_module_function_table_t and a static const char[] modname + */ +SWITCH_MODULE_DEFINITION(mod_fsk, mod_fsk_load, mod_fsk_shutdown, NULL); + +switch_status_t my_write_sample(int16_t *buf, size_t buflen, void *user_data) +{ + switch_buffer_t *buffer = (switch_buffer_t *) user_data; + + switch_buffer_write(buffer, buf, buflen * 2); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t write_fsk_data(uint32_t rate, int32_t db, switch_buffer_t *buffer, switch_event_t *event, const char *prefix) +{ + fsk_modulator_t fsk_trans; + fsk_data_state_t fsk_data = {0}; + uint8_t databuf[1024] = ""; + char time_str[9]; + struct tm tm; + time_t now; + switch_event_header_t *hp; + switch_size_t plen = 0; + + memset(&fsk_trans, 0, sizeof(fsk_trans)); + + time(&now); + localtime_r(&now, &tm); + strftime(time_str, sizeof(time_str), "%m%d%H%M", &tm); + + fsk_data_init(&fsk_data, databuf, sizeof(databuf)); + fsk_data_add_mdmf(&fsk_data, MDMF_DATETIME, (uint8_t *)time_str, strlen(time_str)); + + if (prefix) { + plen = strlen(prefix); + } + + + if (event) { + for (hp = event->headers; hp; hp = hp->next) { + char *packed; + char *name = hp->name; + + if (plen && strncasecmp(name, prefix, plen)) { + continue; + } + + name += plen; + + if (zstr(name)) { + continue; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoding [%s][%s]\n", hp->name, hp->value); + + if (!strcasecmp(name, "phone_num")) { + fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NUM, (uint8_t *)hp->value, strlen(hp->value)); + } else if (!strcasecmp(name, "phone_name")) { + fsk_data_add_mdmf(&fsk_data, MDMF_PHONE_NAME, (uint8_t *)hp->value, strlen(hp->value)); + } else { + packed = switch_mprintf("%q:%q", name, hp->value); + fsk_data_add_mdmf(&fsk_data, MDMF_NAME_VALUE, (uint8_t *)packed, strlen(packed)); + free(packed); + } + } + } + + fsk_data_add_checksum(&fsk_data); + + fsk_modulator_init(&fsk_trans, FSK_BELL202, rate, &fsk_data, db, 180, 5, 300, my_write_sample, buffer); + fsk_modulator_send_all((&fsk_trans)); + + fsk_demod_destroy(&fsk_data); + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_STANDARD_APP(fsk_send_function) { + switch_event_t *event = NULL; + switch_buffer_t *buffer; + switch_slin_data_t sdata = { 0 }; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_frame_t *read_frame; + switch_status_t status; + + + if (data) { + switch_ivr_sleep(session, 1000, SWITCH_TRUE, NULL); + switch_core_session_send_dtmf_string(session, (const char *) data); + switch_ivr_sleep(session, 1500, SWITCH_TRUE, NULL); + } + + if (switch_core_session_set_codec_slin(session, &sdata) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), + SWITCH_LOG_ERROR, "FAILURE\n"); + return; + } + + switch_buffer_create_dynamic(&buffer, 1024, 2048, 0); + + switch_channel_get_variables(channel, &event); + + write_fsk_data(sdata.codec.implementation->actual_samples_per_second, -14, buffer, event, "fsk_"); + + while(switch_channel_ready(channel)) { + status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); + + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + + if ((sdata.write_frame.datalen = switch_buffer_read(buffer, sdata.write_frame.data, + sdata.codec.implementation->decoded_bytes_per_packet)) <= 0) { + break; + } + + + if (sdata.write_frame.datalen < sdata.codec.implementation->decoded_bytes_per_packet) { + memset((char *)sdata.write_frame.data + sdata.write_frame.datalen, 255, + sdata.codec.implementation->decoded_bytes_per_packet - sdata.write_frame.datalen); + sdata.write_frame.datalen = sdata.codec.implementation->decoded_bytes_per_packet; + } + sdata.write_frame.samples = sdata.write_frame.datalen / 2; + switch_core_session_write_frame(sdata.session, &sdata.write_frame, SWITCH_IO_FLAG_NONE, 0); + } + + switch_buffer_destroy(&buffer); + switch_core_codec_destroy(&sdata.codec); + switch_core_session_set_read_codec(session, NULL); + +} + +typedef struct { + switch_core_session_t *session; + fsk_data_state_t fsk_data; + uint8_t fbuf[512]; + int skip; +} switch_fsk_detect_t; + + + + +static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) +{ + switch_fsk_detect_t *pvt = (switch_fsk_detect_t *) user_data; + //switch_frame_t *frame = NULL; + switch_channel_t *channel = switch_core_session_get_channel(pvt->session); + + switch (type) { + case SWITCH_ABC_TYPE_INIT: { + switch_codec_implementation_t read_impl = { 0 }; + switch_core_session_get_read_impl(pvt->session, &read_impl); + + if (fsk_demod_init(&pvt->fsk_data, read_impl.actual_samples_per_second, pvt->fbuf, sizeof(pvt->fbuf))) { + return SWITCH_FALSE; + } + + break; + } + case SWITCH_ABC_TYPE_CLOSE: + { + fsk_demod_destroy(&pvt->fsk_data); + } + break; + + case SWITCH_ABC_TYPE_WRITE_REPLACE: + case SWITCH_ABC_TYPE_READ_REPLACE: + { + switch_frame_t *rframe; + + if (type == SWITCH_ABC_TYPE_READ_REPLACE) { + rframe = switch_core_media_bug_get_read_replace_frame(bug); + } else { + rframe = switch_core_media_bug_get_write_replace_frame(bug); + } + + if (!pvt->skip && fsk_demod_feed(&pvt->fsk_data, rframe->data, rframe->datalen / 2) != SWITCH_STATUS_SUCCESS) { + char str[1024] = ""; + size_t type, mlen; + char *sp; + switch_event_t *event; + const char *app_var; + + switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA); + + while(fsk_data_parse(&pvt->fsk_data, &type, &sp, &mlen) == SWITCH_STATUS_SUCCESS) { + char *varname = NULL, *val, *p; + + switch_copy_string(str, sp, mlen+1); + *(str+mlen) = '\0'; + switch_clean_string(str); + //printf("TYPE %u LEN %u VAL [%s]\n", (unsigned)type, (unsigned)mlen, str); + + val = str; + + switch(type) { + case MDMF_DATETIME: + varname = "fsk_datetime"; + break; + case MDMF_PHONE_NAME: + varname = "fsk_phone_name"; + break; + case MDMF_PHONE_NUM: + varname = "fsk_phone_num"; + break; + case MDMF_NAME_VALUE: + varname = switch_core_session_sprintf(pvt->session, "fsk_%s", val); + if ((p = strchr(varname, ':'))) { + *p++ = '\0'; + val = p; + } + break; + default: + break; + } + + if (varname && val) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", + switch_channel_get_name(channel), varname, val); + switch_channel_set_variable(channel, varname, val); + if (event) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, varname, val); + } + } + } + + if (event) { + if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) { + switch_event_destroy(&event); + } + } + + if ((app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) { + char *app_arg; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", + switch_channel_get_name(channel), app_var); + if ((app_arg = strchr(app_var, ' '))) { + *app_arg++ = '\0'; + } + switch_core_session_execute_application(pvt->session, app_var, app_arg); + } + + pvt->skip = 10; + } + + memset(rframe->data, 255, rframe->datalen); + + if (type == SWITCH_ABC_TYPE_READ_REPLACE) { + switch_core_media_bug_set_read_replace_frame(bug, rframe); + } else { + switch_core_media_bug_set_write_replace_frame(bug, rframe); + } + + if (pvt->skip && !--pvt->skip) { + return SWITCH_FALSE; + } + + } + break; + case SWITCH_ABC_TYPE_WRITE: + default: + break; + } + + return SWITCH_TRUE; +} + +switch_status_t stop_fsk_detect_session(switch_core_session_t *session) +{ + switch_media_bug_t *bug; + switch_channel_t *channel = switch_core_session_get_channel(session); + + if ((bug = switch_channel_get_private(channel, "fsk"))) { + switch_channel_set_private(channel, "fsk", NULL); + switch_core_media_bug_remove(session, &bug); + return SWITCH_STATUS_SUCCESS; + } + return SWITCH_STATUS_FALSE; +} + +switch_status_t fsk_detect_session(switch_core_session_t *session, const char *flags) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_media_bug_t *bug; + switch_status_t status; + switch_fsk_detect_t *pvt = { 0 }; + switch_codec_implementation_t read_impl = { 0 }; + int bflags = SMBF_READ_REPLACE; + + if (strchr(flags, 'w')) { + bflags = SMBF_WRITE_REPLACE; + } + + switch_core_session_get_read_impl(session, &read_impl); + + if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) { + return SWITCH_STATUS_MEMERR; + } + + pvt->session = session; + + + if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + + if ((status = switch_core_media_bug_add(session, "fsk_detect", NULL, + fsk_detect_callback, pvt, 0, bflags | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) { + return status; + } + + switch_channel_set_private(channel, "fsk", bug); + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_STANDARD_APP(fsk_recv_function) +{ + fsk_detect_session(session, data); +} + +SWITCH_STANDARD_APP(fsk_display_function) +{ + /* expected to be called via 'execute_on_fsk' -- passes display update over FSK */ + + const char *cid_name, *cid_num; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_core_session_message_t *msg; + switch_core_session_t *psession, *usession = NULL; + char *flags = (char *) data; + + cid_name = switch_channel_get_variable(channel, "fsk_phone_name"); + cid_num = switch_channel_get_variable(channel, "fsk_phone_num"); + + if (zstr(cid_name)) { + cid_name = cid_num; + } + + if (zstr(cid_num)) { + return; + } + + if (strchr(flags, 'b')) { + if (switch_core_session_get_partner(session, &psession) == SWITCH_STATUS_SUCCESS) { + usession = psession; + } + } + + if (!usession) { + usession = session; + } + + msg = switch_core_session_alloc(usession, sizeof(*msg)); + MESSAGE_STAMP_FFL(msg); + msg->message_id = SWITCH_MESSAGE_INDICATE_DISPLAY; + msg->string_array_arg[0] = switch_core_session_strdup(usession, cid_name); + msg->string_array_arg[1] = switch_core_session_strdup(usession, cid_num); + msg->from = __FILE__; + switch_core_session_queue_message(usession, msg); + + if (psession) { + switch_core_session_rwunlock(psession); + psession = NULL; + } +} + +SWITCH_STANDARD_APP(fsk_simplify_function) +{ + /* expected to be called via 'execute_on_fsk' -- redirects call to point-to-point and eliminates legs in the middle */ + switch_channel_t *channel = switch_core_session_get_channel(session); + const char *sip_uri, *fsk_simplify_profile, *fsk_simplify_context; + char *bridgeto; + + if (!(sip_uri = switch_channel_get_variable(channel, "fsk_uri"))) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s Missing URI field!\n", switch_channel_get_name(channel)); + } + + if (!(fsk_simplify_profile = switch_channel_get_variable(channel, "fsk_simplify_profile"))) { + fsk_simplify_profile = "internal"; + } + + fsk_simplify_context = switch_channel_get_variable(channel, "fsk_simplify_context"); + + if (!zstr(sip_uri)) { + switch_core_session_t *psession; + switch_channel_t *pchannel; + + bridgeto = switch_core_session_sprintf(session, "bridge:sofia/%s/sip:%s", fsk_simplify_profile, sip_uri); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s transfering to [%s]\n", + switch_channel_get_name(channel), bridgeto); + + + if (switch_core_session_get_partner(session, &psession) == SWITCH_STATUS_SUCCESS) { + pchannel = switch_core_session_get_channel(psession); + switch_channel_set_flag(pchannel, CF_REDIRECT); + switch_channel_set_flag(pchannel, CF_TRANSFER); + } + + switch_ivr_session_transfer(session, bridgeto, "inline", fsk_simplify_context); + + if (psession) { + switch_ivr_session_transfer(psession, "sleep:5000", "inline", NULL); + switch_core_session_rwunlock(psession); + } + } +} + +/* Macro expands to: switch_status_t mod_fsk_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ +SWITCH_MODULE_LOAD_FUNCTION(mod_fsk_load) +{ + switch_application_interface_t *app_interface; + + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + SWITCH_ADD_APP(app_interface, "fsk_send", "fsk_send", NULL, fsk_send_function, NULL, SAF_NONE); + SWITCH_ADD_APP(app_interface, "fsk_recv", "fsk_recv", NULL, fsk_recv_function, NULL, SAF_NONE); + SWITCH_ADD_APP(app_interface, "fsk_simplify", "fsk_simplify", NULL, fsk_simplify_function, NULL, SAF_NONE); + SWITCH_ADD_APP(app_interface, "fsk_display", "fsk_display", NULL, fsk_display_function, NULL, SAF_NONE); + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* + Called when the system shuts down + Macro expands to: switch_status_t mod_fsk_shutdown() */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fsk_shutdown) +{ + /* Cleanup dynamically allocated config settings */ + + return SWITCH_STATUS_SUCCESS; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 + */ diff --git a/src/mod/applications/mod_fsk/uart.c b/src/mod/applications/mod_fsk/uart.c new file mode 100644 index 0000000000..5e0dd85350 --- /dev/null +++ b/src/mod/applications/mod_fsk/uart.c @@ -0,0 +1,124 @@ + +/* + * uart.c + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This module contains a simple 8-bit UART, which performs a callback + * with the decoded byte value. + * + * 2005 06 11 R. Krten created +*/ + +#include +#include +#include +#include + +#include "uart.h" + +/* + * dsp_uart_attr_init + * + * Initializes the attributes structure; this must be done before the + * attributes structure is used. +*/ + +void dsp_uart_attr_init (dsp_uart_attr_t *attr) +{ + memset (attr, 0, sizeof (*attr)); +} + +/* + * dsp_uart_attr_get_bytehandler + * dsp_uart_attr_set_bytehandler + * + * These functions get and set their respective elements from the + * attributes structure. If an error code is returned, it is just + * zero == ok, -1 == fail. +*/ + +bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attr, void **bytehandler_arg) +{ + *bytehandler_arg = attr->bytehandler_arg; + return attr->bytehandler; +} + +void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attr, bytehandler_func_t bytehandler, void *bytehandler_arg) +{ + attr->bytehandler = bytehandler; + attr->bytehandler_arg = bytehandler_arg; +} + +dsp_uart_handle_t *dsp_uart_create(dsp_uart_attr_t *attr) +{ + dsp_uart_handle_t *handle; + + handle = malloc(sizeof (*handle)); + if (handle) { + memset(handle, 0, sizeof (*handle)); + + /* fill the attributes member */ + memcpy(&handle->attr, attr, sizeof (*attr)); + } + return handle; +} + +void dsp_uart_destroy(dsp_uart_handle_t **handle) +{ + if (*handle) { + free(*handle); + *handle = NULL; + } +} + + +void dsp_uart_bit_handler(void *x, int bit) +{ + dsp_uart_handle_t *handle = (dsp_uart_handle_t *) x; + + if (!handle->have_start) { + if (bit) { + return; /* waiting for start bit (0) */ + } + handle->have_start = 1; + handle->data = 0; + handle->nbits = 0; + return; + } + + handle->data >>= 1; + handle->data |= 0x80 * !!bit; + handle->nbits++; + + if (handle->nbits == 8) { + handle->attr.bytehandler(handle->attr.bytehandler_arg, handle->data); + handle->nbits = 0; + handle->data = 0; + handle->have_start = 0; + } +/* might consider handling errors in the future... */ +} + diff --git a/src/mod/applications/mod_fsk/uart.h b/src/mod/applications/mod_fsk/uart.h new file mode 100644 index 0000000000..89c3a13abc --- /dev/null +++ b/src/mod/applications/mod_fsk/uart.h @@ -0,0 +1,76 @@ +/* + * uart.h + * + * Copyright (c) 2005 Robert Krten. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This module contains the manifest constants and declarations for + * the UART module. + * + * 2005 06 19 R. Krten created +*/ + +#ifndef __UART_H__ +#define __UART_H__ + +typedef void (*bytehandler_func_t) (void *, int); +typedef void (*bithandler_func_t) (void *, int); + + +typedef struct dsp_uart_attr_s +{ + bytehandler_func_t bytehandler; /* byte handler */ + void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */ +} dsp_uart_attr_t; + +typedef struct +{ + dsp_uart_attr_t attr; + int have_start; /* wait for start bit to show up */ + int data; /* data buffer */ + int nbits; /* number of bits accumulated so far */ +} dsp_uart_handle_t; + +/* + * Function prototypes + * + * General calling order is: + * a) create the attributes structure (dsp_uart_attr_init) + * b) initialize fields in the attributes structure (dsp_uart_attr_set_*) + * c) create a Bell-202 handle (dsp_uart_create) + * d) feed bits through dsp_uart_bit_handler +*/ + +void dsp_uart_attr_init(dsp_uart_attr_t *attributes); + +bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attributes, void **bytehandler_arg); +void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg); + +dsp_uart_handle_t * dsp_uart_create(dsp_uart_attr_t *attributes); +void dsp_uart_destroy(dsp_uart_handle_t **handle); + +void dsp_uart_bit_handler(void *handle, int bit); + +#endif + diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 69dd217ca2..1799e5c7dc 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1973,12 +1973,22 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_FAIL_MACRO, NULL, NULL, NULL)); } else { + switch_event_t *params; + TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_SELECTED_MACRO, input, NULL, NULL)); sql = switch_mprintf("update voicemail_prefs set greeting_path='%s' where username='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(sql); + + switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "change-greeting"); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Greeting-Path", file_path); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name); + switch_channel_event_set_data(channel, params); + switch_event_fire(¶ms); } switch_safe_free(file_path); } else if (!strcmp(input, profile->record_greeting_key)) { @@ -1989,6 +1999,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p if (num < 1 || num > VM_MAX_GREETINGS) { TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_FAIL_MACRO, NULL, NULL, NULL)); } else { + switch_event_t *params; file_path = switch_mprintf("%s%sgreeting_%d.%s", dir_path, SWITCH_PATH_SEPARATOR, num, profile->file_ext); TRY_CODE(create_file(session, profile, VM_RECORD_GREETING_MACRO, file_path, &message_len, SWITCH_TRUE, NULL, NULL)); sql = @@ -1997,6 +2008,14 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(sql); switch_safe_free(file_path); + + switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "record-greeting"); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Greeting-Path", file_path); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name); + switch_channel_event_set_data(channel, params); + switch_event_fire(¶ms); } } else if (!strcmp(input, profile->change_pass_key)) { @@ -2027,12 +2046,21 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p switch_event_fire(¶ms); } else if (!strcmp(input, profile->record_name_key)) { + switch_event_t *params; file_path = switch_mprintf("%s%srecorded_name.%s", dir_path, SWITCH_PATH_SEPARATOR, profile->file_ext); TRY_CODE(create_file(session, profile, VM_RECORD_NAME_MACRO, file_path, &message_len, SWITCH_FALSE, NULL, NULL)); sql = switch_mprintf("update voicemail_prefs set name_path='%s' where username='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(file_path); switch_safe_free(sql); + + switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "record-name"); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Name-Path", file_path); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name); + switch_channel_event_set_data(channel, params); + switch_event_fire(¶ms); } continue; } @@ -2337,6 +2365,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile, const char *filename; switch_xml_t x_param, x_params; char *vm_email = NULL; + char *vm_email_from = NULL; char *vm_notify_email = NULL; char *email_addr = NULL; char *vm_timezone = NULL; @@ -2401,6 +2430,8 @@ static switch_status_t deliver_vm(vm_profile_t *profile, vm_email = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "vm-notify-mailto")) { vm_notify_email = switch_core_strdup(pool, val); + } else if (!strcasecmp(var, "vm-mailfrom")) { + vm_email_from = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "email-addr")) { email_addr = switch_core_strdup(pool, val); } else if (!strcasecmp(var, "vm-email-all-messages") && (send_main = switch_true(val))) { @@ -2544,7 +2575,9 @@ static switch_status_t deliver_vm(vm_profile_t *profile, switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "voicemail_message_len", duration_str); - if (zstr(profile->email_from)) { + if (!zstr(vm_email_from)) { + from = switch_core_strdup(pool, vm_email_from); + } else if (zstr(profile->email_from)) { from = switch_core_sprintf(pool, "%s@%s", myid, domain_name); } else { from = switch_event_expand_headers(params, profile->email_from); diff --git a/src/mod/codecs/mod_ilbc/mod_ilbc.c b/src/mod/codecs/mod_ilbc/mod_ilbc.c index 4d52ba9944..23ca642c22 100644 --- a/src/mod/codecs/mod_ilbc/mod_ilbc.c +++ b/src/mod/codecs/mod_ilbc/mod_ilbc.c @@ -163,7 +163,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ilbc_load) "mode=30", /* default fmtp to send (can be overridden by the init function) */ 8000, /* samples transferred per second */ 8000, /* actual samples transferred per second */ - 13300, /* bits transferred per second */ + 13330, /* bits transferred per second */ 30000, /* number of microseconds per frame */ ILBC_BLOCK_LEN_30MS, /* number of samples per frame */ ILBC_BLOCK_LEN_30MS * 2, /* number of bytes per frame decompressed */ diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index df267967fa..b6ce97dac6 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -403,6 +403,7 @@ struct sofia_gateway { char *register_from; char *register_contact; char *extension; + char *real_extension; char *register_to; char *register_proxy; char *register_sticky_proxy; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 2643ceb17f..904f3ecb46 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -161,6 +161,15 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip, swit char *full; if (sip) { + if (sip->sip_route) { + if ((full = sip_header_as_string(profile->home, (void *) sip->sip_route))) { + const char *v = switch_channel_get_variable(channel, "sip_full_route"); + if (!v) { + switch_channel_set_variable(channel, "sip_full_route", full); + } + su_free(profile->home, full); + } + } if (sip->sip_via) { if ((full = sip_header_as_string(profile->home, (void *) sip->sip_via))) { const char *v = switch_channel_get_variable(channel, "sip_full_via"); @@ -2056,10 +2065,6 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) from_user = username; } - if (zstr(extension)) { - extension = username; - } - if (zstr(proxy)) { proxy = realm; } @@ -2151,8 +2156,13 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag) sipip = profile->sipip; } - gateway->extension = switch_core_strdup(gateway->pool, extension); + if (zstr(extension)) { + extension = username; + } else { + gateway->real_extension = switch_core_strdup(gateway->pool, extension); + } + gateway->extension = switch_core_strdup(gateway->pool, extension); if (!strncasecmp(proxy, "sip:", 4)) { gateway->register_proxy = switch_core_strdup(gateway->pool, proxy); @@ -6222,6 +6232,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ char acl_token[512] = ""; sofia_transport_t transport; const char *gw_name = NULL; + const char *gw_param_name = NULL; char *call_info_str = NULL; nua_handle_t *bnh = NULL; char sip_acl_authed_by[512] = ""; @@ -6854,7 +6865,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (sip->sip_request->rq_url->url_params) { - gw_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw="); + gw_param_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw="); } if (strstr(destination_number, "gw+")) { @@ -6869,19 +6880,35 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } } - if (gw_name) { - sofia_gateway_t *gateway; - if (gw_name && (gateway = sofia_reg_find_gateway(gw_name))) { + if (gw_name || gw_param_name) { + sofia_gateway_t *gateway = NULL; + char *extension = NULL; + + if (gw_name && ((gateway = sofia_reg_find_gateway(gw_name)))) { + gw_param_name = NULL; + extension = gateway->extension; + } + + if (!gateway && gw_param_name) { + gateway = sofia_reg_find_gateway(gw_param_name); + extension = gateway->real_extension; + } + + if (gateway) { context = switch_core_session_strdup(session, gateway->register_context); switch_channel_set_variable(channel, "sip_gateway", gateway->name); - if (gateway->extension) { - if (!strcasecmp(gateway->extension, "auto_to_user")) { + if (!zstr(extension)) { + if (!strcasecmp(extension, "auto_to_user")) { destination_number = sip->sip_to->a_url->url_user; + } else if (!strcasecmp(extension, "auto")) { + if (gw_name) { + destination_number = sip->sip_to->a_url->url_user; + } } else { - destination_number = switch_core_session_strdup(session, gateway->extension); + destination_number = switch_core_session_strdup(session, extension); } - } else { + } else if (!gw_param_name) { destination_number = sip->sip_to->a_url->url_user; } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 715b70f59d..a529844059 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3550,13 +3550,53 @@ void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const cha } if (match) { - if (ptime > 0) { - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate, - ptime); - } else { - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate); + int codec_ms = ptime; + uint32_t map_bit_rate = 0; + char ptstr[20] = ""; + char ratestr[20] = ""; + char bitstr[20] = ""; + switch_codec_fmtp_t codec_fmtp = { 0 }; + + if (!codec_ms) { + codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt); } - already_did[imp->ianacode] = 1; + + map_bit_rate = switch_known_bitrate(map->rm_pt); + + if (!ptime && !strcasecmp(map->rm_encoding, "g723")) { + ptime = codec_ms = 30; + } + + if (zstr(map->rm_fmtp)) { + if (!strcasecmp(map->rm_encoding, "ilbc")) { + ptime = codec_ms = 30; + map_bit_rate = 13330; + } + } else { + if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) { + if (codec_fmtp.bits_per_second) { + map_bit_rate = codec_fmtp.bits_per_second; + } + if (codec_fmtp.microseconds_per_packet) { + codec_ms = (codec_fmtp.microseconds_per_packet / 1000); + } + } + } + + if (map->rm_rate) { + switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate); + } + + if (codec_ms) { + switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms); + } + + if (map_bit_rate) { + switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate); + } + + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr); + break; } } @@ -4378,6 +4418,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s if (zstr(map->rm_fmtp)) { if (!strcasecmp(map->rm_encoding, "ilbc")) { ptime = codec_ms = 30; + map_bit_rate = 13330; } } else { if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) { @@ -4389,8 +4430,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } } } - - for (i = first; i < last && i < tech_pvt->num_codecs; i++) { const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; @@ -4401,7 +4440,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n", - rm_encoding, map->rm_pt, (int) map->rm_rate, ptime, map_bit_rate, + rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate, imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate); if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) { match = (map->rm_pt == imp->ianacode) ? 1 : 0; @@ -6149,6 +6188,14 @@ void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str) if (switch_stristr("~NEVER_SEND_MARKER", str)) { *flag_pole &= ~RTP_BUG_NEVER_SEND_MARKER; } + + if (switch_stristr("IGNORE_DTMF_DURATION", str)) { + *flag_pole |= RTP_BUG_IGNORE_DTMF_DURATION; + } + + if (switch_stristr("~IGNORE_DTMF_DURATION", str)) { + *flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION; + } } char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 0b7d0f33fa..288191807c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1078,7 +1078,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (exptime && v_event && *v_event) { char *exp_var; char *allow_multireg = NULL; - int force_connectile = 0; + int auto_connectile = 0; allow_multireg = switch_event_get_header(*v_event, "sip-allow-multiple-registrations"); if (allow_multireg && switch_false(allow_multireg)) { @@ -1097,11 +1097,26 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (profile->rport_level == 3 && sip->sip_user_agent && sip->sip_user_agent->g_string && !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7)) { - force_connectile = 1; + if (sip && sip->sip_via) { + const char *host = sip->sip_via->v_host; + const char *c_port = sip->sip_via->v_port; + int port = 0; + + if (c_port) port = atoi(c_port); + if (!port) port = 5060; + + if (host && strcmp(network_ip, host)) { + auto_connectile = 1; + } else if (port != network_port) { + auto_connectile = 1; + } + } else { + auto_connectile = 1; + } } - if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || force_connectile) { - if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || force_connectile) { + if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact")) || auto_connectile) { + if ((!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction-2.0")) || auto_connectile) { char *path_encoded; size_t path_encoded_len; char my_contact_str[1024]; diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index f5e9e31f72..9ebd6ff9df 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -1331,6 +1331,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *)("temp_hold_music"); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_EXPORT_VARS_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -7112,6 +7122,20 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_set_codec_slin(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_slin_data_t *arg2 = (switch_slin_data_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_slin_data_t *)jarg2; + result = (switch_status_t)switch_core_session_set_codec_slin(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_core_get_uuid() { char * jresult ; char *result = 0 ; @@ -10392,6 +10416,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_execute_sql_callback(void * ja } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_affected_rows(void * jarg1) { + int jresult ; + switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; + int result; + + arg1 = (switch_cache_db_handle_t *)jarg1; + result = (int)switch_cache_db_affected_rows(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_cache_db_status(void * jarg1) { switch_stream_handle_t *arg1 = (switch_stream_handle_t *) 0 ; @@ -11972,6 +12008,30 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_digit_string(char * jarg1) { } +SWIGEXPORT char SWIGSTDCALL CSharp_switch_itodtmf(char jarg1) { + char jresult ; + char arg1 ; + char result; + + arg1 = (char)jarg1; + result = (char)switch_itodtmf(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmftoi(char * jarg1) { + int jresult ; + char *arg1 = (char *) 0 ; + int result; + + arg1 = (char *)jarg1; + result = (int)switch_dtmftoi(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_known_bitrate(unsigned char jarg1) { unsigned long jresult ; switch_payload_t arg1 ; @@ -22102,6 +22162,119 @@ SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_api_interface(void * jarg1) { } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_session_set(void * jarg1, void * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_core_session_t *arg2 = (switch_core_session_t *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (switch_core_session_t *)jarg2; + if (arg1) (arg1)->session = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_session_get(void * jarg1) { + void * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_core_session_t *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (switch_core_session_t *) ((arg1)->session); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_write_frame_set(void * jarg1, void * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_frame_t *arg2 = (switch_frame_t *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (switch_frame_t *)jarg2; + if (arg1) (arg1)->write_frame = *arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_write_frame_get(void * jarg1) { + void * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_frame_t *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (switch_frame_t *)& ((arg1)->write_frame); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_codec_set(void * jarg1, void * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_codec_t *arg2 = (switch_codec_t *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (switch_codec_t *)jarg2; + if (arg1) (arg1)->codec = *arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_slin_data_codec_get(void * jarg1) { + void * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + switch_codec_t *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (switch_codec_t *)& ((arg1)->codec); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_slin_data_frame_data_set(void * jarg1, char * jarg2) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + char *arg2 ; + + arg1 = (switch_slin_data *)jarg1; + arg2 = (char *)jarg2; + { + if(arg2) { + strncpy((char*)arg1->frame_data, (const char *)arg2, 4096-1); + arg1->frame_data[4096-1] = 0; + } else { + arg1->frame_data[0] = 0; + } + } +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_slin_data_frame_data_get(void * jarg1) { + char * jresult ; + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + char *result = 0 ; + + arg1 = (switch_slin_data *)jarg1; + result = (char *)(char *) ((arg1)->frame_data); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_slin_data() { + void * jresult ; + switch_slin_data *result = 0 ; + + result = (switch_slin_data *)new switch_slin_data(); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_delete_switch_slin_data(void * jarg1) { + switch_slin_data *arg1 = (switch_slin_data *) 0 ; + + arg1 = (switch_slin_data *)jarg1; + delete arg1; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_timetable_profile_created_set(void * jarg1, void * jarg2) { switch_channel_timetable *arg1 = (switch_channel_timetable *) 0 ; switch_time_t arg2 ; @@ -22834,6 +23007,30 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void * } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music_partner(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -23079,6 +23276,20 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap(void * jarg1 } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap_partner(void * jarg1, int jarg2) { + unsigned long jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_channel_cap_t arg2 ; + uint32_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (switch_channel_cap_t)jarg2; + result = (uint32_t)switch_channel_test_cap_partner(arg1,arg2); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_flag_partner(void * jarg1, int jarg2) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -28362,6 +28573,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_pause_jitter_buffer(void * jarg1, int jarg2) { + int jresult ; + switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; + switch_bool_t arg2 ; + switch_status_t result; + + arg1 = (switch_rtp_t *)jarg1; + arg2 = (switch_bool_t)jarg2; + result = (switch_status_t)switch_rtp_pause_jitter_buffer(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_flag(void * jarg1, unsigned long jarg2) { switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; switch_rtp_flag_t arg2 ; @@ -33252,6 +33477,24 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_CoreSession_voice_name_get(void * jarg1) { } +SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_insertFile(void * jarg1, char * jarg2, char * jarg3, int jarg4) { + int jresult ; + CoreSession *arg1 = (CoreSession *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + int arg4 ; + int result; + + arg1 = (CoreSession *)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (int)jarg4; + result = (int)(arg1)->insertFile((char const *)arg2,(char const *)arg3,arg4); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Answer(void * jarg1) { int jresult ; CoreSession *arg1 = (CoreSession *) 0 ; diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index d05f4f1213..aa2a84f3f6 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -1422,6 +1422,17 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *) "temp_hold_music"; + + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_EXPORT_VARS_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -12304,6 +12315,30 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_is_digit_string(char * jarg1) { } +SWIGEXPORT char SWIGSTDCALL CSharp_switch_itodtmf(char jarg1) { + char jresult ; + char arg1 ; + char result; + + arg1 = (char)jarg1; + result = (char)switch_itodtmf(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmftoi(char * jarg1) { + int jresult ; + char *arg1 = (char *) 0 ; + int result; + + arg1 = (char *)jarg1; + result = (int)switch_dtmftoi(arg1); + jresult = result; + return jresult; +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_known_bitrate(unsigned char jarg1) { unsigned long jresult ; switch_payload_t arg1 ; @@ -23501,6 +23536,30 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void * } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_hold_music_partner(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_hold_music_partner(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -23746,6 +23805,20 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap(void * jarg1 } +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_channel_test_cap_partner(void * jarg1, int jarg2) { + unsigned long jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_channel_cap_t arg2 ; + uint32_t result; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (switch_channel_cap_t)jarg2; + result = (uint32_t)switch_channel_test_cap_partner(arg1,arg2); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_set_flag_partner(void * jarg1, int jarg2) { int jresult ; switch_channel_t *arg1 = (switch_channel_t *) 0 ; @@ -29077,6 +29150,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_deactivate_jitter_buffer(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_pause_jitter_buffer(void * jarg1, int jarg2) { + int jresult ; + switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; + switch_bool_t arg2 ; + switch_status_t result; + + arg1 = (switch_rtp_t *)jarg1; + arg2 = (switch_bool_t)jarg2; + result = (switch_status_t)switch_rtp_pause_jitter_buffer(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_flag(void * jarg1, unsigned long jarg2) { switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; switch_rtp_flag_t arg2 ; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index b792fb0ac8..059fb89a1c 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -224,6 +224,11 @@ public class CoreSession : IDisposable { } } + public int insertFile(string file, string insert_file, int sample_point) { + int ret = freeswitchPINVOKE.CoreSession_insertFile(swigCPtr, file, insert_file, sample_point); + return ret; + } + public int Answer() { int ret = freeswitchPINVOKE.CoreSession_Answer(swigCPtr); return ret; @@ -1362,6 +1367,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session session, switch_slin_data data) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_slin_data.getCPtr(data)); + return ret; + } + public static string switch_core_get_uuid() { string ret = freeswitchPINVOKE.switch_core_get_uuid(); return ret; @@ -2338,6 +2348,11 @@ public class freeswitch { return ret; } + public static int switch_cache_db_affected_rows(switch_cache_db_handle_t dbh) { + int ret = freeswitchPINVOKE.switch_cache_db_affected_rows(switch_cache_db_handle_t.getCPtr(dbh)); + return ret; + } + public static void switch_cache_db_status(switch_stream_handle stream) { freeswitchPINVOKE.switch_cache_db_status(switch_stream_handle.getCPtr(stream)); } @@ -2732,6 +2747,16 @@ public class freeswitch { return ret; } + public static char switch_itodtmf(char i) { + char ret = freeswitchPINVOKE.switch_itodtmf(i); + return ret; + } + + public static int switch_dtmftoi(string s) { + int ret = freeswitchPINVOKE.switch_dtmftoi(s); + return ret; + } + public static uint switch_known_bitrate(byte payload) { uint ret = freeswitchPINVOKE.switch_known_bitrate(payload); return ret; @@ -3281,6 +3306,16 @@ public class freeswitch { return ret; } + public static string switch_channel_get_hold_music(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + + public static string switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check); return ret; @@ -3369,6 +3404,11 @@ public class freeswitch { return ret; } + public static uint switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel channel, switch_channel_cap_t cap) { + uint ret = freeswitchPINVOKE.switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)cap); + return ret; + } + public static switch_bool_t switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) { switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag); return ret; @@ -4664,6 +4704,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, switch_bool_t pause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)pause); + return ret; + } + public static void switch_rtp_set_flag(SWIGTYPE_p_switch_rtp rtp_session, uint flags) { freeswitchPINVOKE.switch_rtp_set_flag(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), flags); } @@ -5418,6 +5463,7 @@ public class freeswitch { public static readonly string SWITCH_PROXY_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_PROXY_MEDIA_VARIABLE_get(); public static readonly string SWITCH_ENDPOINT_DISPOSITION_VARIABLE = freeswitchPINVOKE.SWITCH_ENDPOINT_DISPOSITION_VARIABLE_get(); public static readonly string SWITCH_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_HOLD_MUSIC_VARIABLE_get(); + public static readonly string SWITCH_TEMP_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); public static readonly string SWITCH_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_BRIDGE_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_BRIDGE_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_R_SDP_VARIABLE = freeswitchPINVOKE.SWITCH_R_SDP_VARIABLE_get(); @@ -6010,6 +6056,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get")] public static extern string SWITCH_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get")] + public static extern string SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_EXPORT_VARS_VARIABLE_get")] public static extern string SWITCH_EXPORT_VARS_VARIABLE_get(); @@ -7474,6 +7523,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_dmachine")] public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_codec_slin")] + public static extern int switch_core_session_set_codec_slin(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_uuid")] public static extern string switch_core_get_uuid(); @@ -8218,6 +8270,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_execute_sql_callback")] public static extern int switch_cache_db_execute_sql_callback(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4, ref string jarg5); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_affected_rows")] + public static extern int switch_cache_db_affected_rows(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_status")] public static extern void switch_cache_db_status(HandleRef jarg1); @@ -8590,6 +8645,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_is_digit_string")] public static extern int switch_is_digit_string(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_itodtmf")] + public static extern char switch_itodtmf(char jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmftoi")] + public static extern int switch_dtmftoi(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_known_bitrate")] public static extern uint switch_known_bitrate(byte jarg1); @@ -11149,6 +11210,36 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_api_interface")] public static extern void delete_switch_api_interface(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_set")] + public static extern void switch_slin_data_session_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_session_get")] + public static extern IntPtr switch_slin_data_session_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_set")] + public static extern void switch_slin_data_write_frame_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_write_frame_get")] + public static extern IntPtr switch_slin_data_write_frame_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_set")] + public static extern void switch_slin_data_codec_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_codec_get")] + public static extern IntPtr switch_slin_data_codec_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_set")] + public static extern void switch_slin_data_frame_data_set(HandleRef jarg1, string jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_slin_data_frame_data_get")] + public static extern string switch_slin_data_frame_data_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_slin_data")] + public static extern IntPtr new_switch_slin_data(); + + [DllImport("mod_managed", EntryPoint="CSharp_delete_switch_slin_data")] + public static extern void delete_switch_slin_data(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_timetable_profile_created_set")] public static extern void switch_channel_timetable_profile_created_set(HandleRef jarg1, HandleRef jarg2); @@ -11311,6 +11402,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_partner")] public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music")] + public static extern string switch_channel_get_hold_music(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")] + public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")] public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5); @@ -11368,6 +11465,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap")] public static extern uint switch_channel_test_cap(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap_partner")] + public static extern uint switch_channel_test_cap_partner(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_flag_partner")] public static extern int switch_channel_set_flag_partner(HandleRef jarg1, int jarg2); @@ -12481,6 +12581,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")] public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_pause_jitter_buffer")] + public static extern int switch_rtp_pause_jitter_buffer(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")] public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2); @@ -13672,6 +13775,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_voice_name_get")] public static extern string CoreSession_voice_name_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_insertFile")] + public static extern int CoreSession_insertFile(HandleRef jarg1, string jarg2, string jarg3, int jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_Answer")] public static extern int CoreSession_Answer(HandleRef jarg1); @@ -21515,6 +21621,8 @@ public enum switch_channel_cap_t { CC_MEDIA_ACK = 1, CC_BYPASS_MEDIA, CC_PROXY_MEDIA, + CC_JITTERBUFFER, + CC_FS_RTP, CC_FLAG_MAX } @@ -29531,6 +29639,98 @@ public enum switch_signal_t { namespace FreeSWITCH.Native { +using System; +using System.Runtime.InteropServices; + +public class switch_slin_data : IDisposable { + private HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal switch_slin_data(IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new HandleRef(this, cPtr); + } + + internal static HandleRef getCPtr(switch_slin_data obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } + + ~switch_slin_data() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if (swigCPtr.Handle != IntPtr.Zero) { + if (swigCMemOwn) { + swigCMemOwn = false; + freeswitchPINVOKE.delete_switch_slin_data(swigCPtr); + } + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + GC.SuppressFinalize(this); + } + } + + public SWIGTYPE_p_switch_core_session session { + set { + freeswitchPINVOKE.switch_slin_data_session_set(swigCPtr, SWIGTYPE_p_switch_core_session.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_session_get(swigCPtr); + SWIGTYPE_p_switch_core_session ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_core_session(cPtr, false); + return ret; + } + } + + public switch_frame write_frame { + set { + freeswitchPINVOKE.switch_slin_data_write_frame_set(swigCPtr, switch_frame.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_write_frame_get(swigCPtr); + switch_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_frame(cPtr, false); + return ret; + } + } + + public switch_codec codec { + set { + freeswitchPINVOKE.switch_slin_data_codec_set(swigCPtr, switch_codec.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_slin_data_codec_get(swigCPtr); + switch_codec ret = (cPtr == IntPtr.Zero) ? null : new switch_codec(cPtr, false); + return ret; + } + } + + public string frame_data { + set { + freeswitchPINVOKE.switch_slin_data_frame_data_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.switch_slin_data_frame_data_get(swigCPtr); + return ret; + } + } + + public switch_slin_data() : this(freeswitchPINVOKE.new_switch_slin_data(), true) { + } + +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + [System.Flags] public enum switch_speech_flag_enum_t { SWITCH_SPEECH_FLAG_NONE = 0, SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0), diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 849a6f62a4..5a2188ac83 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -2732,6 +2732,16 @@ public class freeswitch { return ret; } + public static char switch_itodtmf(char i) { + char ret = freeswitchPINVOKE.switch_itodtmf(i); + return ret; + } + + public static int switch_dtmftoi(string s) { + int ret = freeswitchPINVOKE.switch_dtmftoi(s); + return ret; + } + public static uint switch_known_bitrate(byte payload) { uint ret = freeswitchPINVOKE.switch_known_bitrate(payload); return ret; @@ -3281,6 +3291,16 @@ public class freeswitch { return ret; } + public static string switch_channel_get_hold_music(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + + public static string switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_hold_music_partner(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string val, string export_varname, switch_bool_t var_check) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, val, export_varname, (int)var_check); return ret; @@ -3369,6 +3389,11 @@ public class freeswitch { return ret; } + public static uint switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel channel, switch_channel_cap_t cap) { + uint ret = freeswitchPINVOKE.switch_channel_test_cap_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)cap); + return ret; + } + public static switch_bool_t switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel channel, switch_channel_flag_t flag) { switch_bool_t ret = (switch_bool_t)freeswitchPINVOKE.switch_channel_set_flag_partner(SWIGTYPE_p_switch_channel.getCPtr(channel), (int)flag); return ret; @@ -4664,6 +4689,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session, switch_bool_t pause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_rtp_pause_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), (int)pause); + return ret; + } + public static void switch_rtp_set_flag(SWIGTYPE_p_switch_rtp rtp_session, uint flags) { freeswitchPINVOKE.switch_rtp_set_flag(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), flags); } @@ -5418,6 +5448,7 @@ public class freeswitch { public static readonly string SWITCH_PROXY_MEDIA_VARIABLE = freeswitchPINVOKE.SWITCH_PROXY_MEDIA_VARIABLE_get(); public static readonly string SWITCH_ENDPOINT_DISPOSITION_VARIABLE = freeswitchPINVOKE.SWITCH_ENDPOINT_DISPOSITION_VARIABLE_get(); public static readonly string SWITCH_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_HOLD_MUSIC_VARIABLE_get(); + public static readonly string SWITCH_TEMP_HOLD_MUSIC_VARIABLE = freeswitchPINVOKE.SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); public static readonly string SWITCH_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_BRIDGE_EXPORT_VARS_VARIABLE = freeswitchPINVOKE.SWITCH_BRIDGE_EXPORT_VARS_VARIABLE_get(); public static readonly string SWITCH_R_SDP_VARIABLE = freeswitchPINVOKE.SWITCH_R_SDP_VARIABLE_get(); @@ -6006,6 +6037,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_HOLD_MUSIC_VARIABLE_get")] public static extern string SWITCH_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get")] + public static extern string SWITCH_TEMP_HOLD_MUSIC_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_EXPORT_VARS_VARIABLE_get")] public static extern string SWITCH_EXPORT_VARS_VARIABLE_get(); @@ -8589,6 +8623,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_is_digit_string")] public static extern int switch_is_digit_string(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_itodtmf")] + public static extern char switch_itodtmf(char jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmftoi")] + public static extern int switch_dtmftoi(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_known_bitrate")] public static extern uint switch_known_bitrate(byte jarg1); @@ -11310,6 +11350,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_partner")] public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music")] + public static extern string switch_channel_get_hold_music(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_hold_music_partner")] + public static extern string switch_channel_get_hold_music_partner(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")] public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5); @@ -11367,6 +11413,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap")] public static extern uint switch_channel_test_cap(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_test_cap_partner")] + public static extern uint switch_channel_test_cap_partner(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_set_flag_partner")] public static extern int switch_channel_set_flag_partner(HandleRef jarg1, int jarg2); @@ -12480,6 +12529,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_deactivate_jitter_buffer")] public static extern int switch_rtp_deactivate_jitter_buffer(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_pause_jitter_buffer")] + public static extern int switch_rtp_pause_jitter_buffer(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")] public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2); @@ -21477,6 +21529,8 @@ public enum switch_channel_cap_t { CC_MEDIA_ACK = 1, CC_BYPASS_MEDIA, CC_PROXY_MEDIA, + CC_JITTERBUFFER, + CC_FS_RTP, CC_FLAG_MAX } diff --git a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c index be06b148cd..468190d887 100644 --- a/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c +++ b/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c @@ -744,6 +744,7 @@ abyss_bool handler_hook(TSession * r) if (dateValue) { ResponseAddField(r, "Date", dateValue); + free(dateValue); } } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 9319abc535..4836aae73f 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -58,6 +58,39 @@ SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *sess session->soft_lock = 0; } +SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data) + +{ + switch_codec_implementation_t read_impl = { 0 }; + int interval; + + switch_core_session_get_read_impl(session, &read_impl); + interval = read_impl.microseconds_per_packet / 1000; + data->session = session; + + if (switch_core_codec_init(&data->codec, + "L16", + NULL, + read_impl.actual_samples_per_second, + interval, + 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), + SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %dms\n", read_impl.actual_samples_per_second, interval); + + memset(&data->write_frame, 0, sizeof(data->write_frame)); + + data->write_frame.codec = &data->codec; + data->write_frame.data = data->frame_data; + data->write_frame.buflen = sizeof(data->frame_data); + data->write_frame.datalen = 0; + switch_core_session_set_read_codec(session, &data->codec); + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + + #ifdef SWITCH_DEBUG_RWLOCKS SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line) #else diff --git a/src/switch_odbc.c b/src/switch_odbc.c index 48ba62ce03..a7c2153304 100644 --- a/src/switch_odbc.c +++ b/src/switch_odbc.c @@ -57,6 +57,7 @@ struct switch_odbc_handle { char odbc_driver[256]; BOOL is_firebird; int affected_rows; + int num_retries; }; #endif @@ -90,6 +91,7 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c new_handle->env = SQL_NULL_HANDLE; new_handle->state = SWITCH_ODBC_STATE_INIT; new_handle->affected_rows = 0; + new_handle->num_retries = DEFAULT_ODBC_RETRIES; return new_handle; @@ -104,6 +106,15 @@ SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, c return NULL; } +SWITCH_DECLARE(void) switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries) +{ +#ifdef SWITCH_HAVE_ODBC + if (handle) { + handle->num_retries = num_retries; + } +#endif +} + SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle) { #ifdef SWITCH_HAVE_ODBC @@ -133,6 +144,53 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_h #ifdef SWITCH_HAVE_ODBC +static switch_odbc_status_t init_odbc_handles(switch_odbc_handle_t *handle, switch_bool_t do_reinit) +{ + int result; + + if (!handle) { + return SWITCH_ODBC_FAIL; + } + + /* if handle is already initialized, and we're supposed to reinit - free old handle first */ + if (do_reinit == SWITCH_TRUE && handle->env != SQL_NULL_HANDLE) { + SQLFreeHandle(SQL_HANDLE_DBC, handle->con); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + handle->env = SQL_NULL_HANDLE; + } + + if (handle->env == SQL_NULL_HANDLE) { + result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env); + + if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n"); + handle->env = SQL_NULL_HANDLE; /* Reset handle value, just in case */ + return SWITCH_ODBC_FAIL; + } + + result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); + + if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n"); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */ + return SWITCH_ODBC_FAIL; + } + + result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con); + + if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */ + return SWITCH_ODBC_FAIL; + } + SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0); + } + + return SWITCH_ODBC_SUCCESS; +} + static int db_is_up(switch_odbc_handle_t *handle) { int ret = 0; @@ -143,12 +201,18 @@ static int db_is_up(switch_odbc_handle_t *handle) switch_odbc_status_t recon = 0; char *err_str = NULL; SQLCHAR sql[255] = ""; - int max_tries = 120; + int max_tries = DEFAULT_ODBC_RETRIES; int code = 0; SQLRETURN rc; SQLSMALLINT nresultcols; + if (handle) { + max_tries = handle->num_retries; + if (max_tries < 1) + max_tries = DEFAULT_ODBC_RETRIES; + } + top: if (!handle) { @@ -199,6 +263,13 @@ static int db_is_up(switch_odbc_handle_t *handle) error: err_str = switch_odbc_handle_get_error(handle, stmt); + + /* Make sure to free the handle before we try to reconnect */ + if (stmt) { + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; + } + recon = switch_odbc_handle_connect(handle); max_tries--; @@ -228,11 +299,6 @@ static int db_is_up(switch_odbc_handle_t *handle) goto done; } - if (stmt) { - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - stmt = NULL; - } - switch_safe_free(err_str); switch_yield(1000000); goto top; @@ -274,31 +340,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand SQLSMALLINT valueLength = 0; int i = 0; - if (handle->env == SQL_NULL_HANDLE) { - result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env); + init_odbc_handles(handle, SWITCH_FALSE); /* Init ODBC handles, if they are already initialized, don't do it again */ - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n"); - return SWITCH_ODBC_FAIL; - } - - result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); - - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SetEnv\n"); - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); - return SWITCH_ODBC_FAIL; - } - - result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con); - - if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result); - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); - return SWITCH_ODBC_FAIL; - } - SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0); - } if (handle->state == SWITCH_ODBC_STATE_CONNECTED) { switch_odbc_handle_disconnect(handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn); @@ -325,7 +368,9 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_hand SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, 100, &mlen); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d %s\n", result, (int) err, msg); } - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + + /* Deallocate handles again, more chanses to succeed when reconnecting */ + init_odbc_handles(handle, SWITCH_TRUE); /* Reinit ODBC handles */ return SWITCH_ODBC_FAIL; } @@ -554,6 +599,7 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c } SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; /* Make sure we don't try to free this handle again */ if (!err_cnt) { return SWITCH_ODBC_SUCCESS; @@ -593,8 +639,10 @@ SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep) if (handle) { switch_odbc_handle_disconnect(handle); - SQLFreeHandle(SQL_HANDLE_DBC, handle->con); - SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + if (handle->env != SQL_NULL_HANDLE) { + SQLFreeHandle(SQL_HANDLE_DBC, handle->con); + SQLFreeHandle(SQL_HANDLE_ENV, handle->env); + } switch_safe_free(handle->dsn); switch_safe_free(handle->username); switch_safe_free(handle->password); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 41d5fc98dd..038e1d981b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -126,6 +126,7 @@ struct switch_rtp_rfc2833_data { uint16_t in_digit_seq; uint32_t in_digit_ts; uint32_t in_digit_sanity; + uint32_t in_interleaved; uint32_t timestamp_dtmf; uint16_t last_duration; uint32_t flip; @@ -133,6 +134,7 @@ struct switch_rtp_rfc2833_data { char last_digit; switch_queue_t *dtmf_inqueue; switch_mutex_t *dtmf_mutex; + uint8_t in_digit_queued; }; struct switch_rtp { @@ -2479,7 +2481,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } } - if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && (rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) { + if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && + (rtp_session->dtmf_data.out_digit_dur == 0 || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO))) { return_cng_frame(); } } @@ -2819,7 +2822,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } #ifdef DEBUG_2833 if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) { - printf("sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); } #endif @@ -2869,7 +2872,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } } #ifdef DEBUG_2833 - printf("packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned) + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned) packet[1], (unsigned) packet[2], (unsigned) packet[3]); #endif @@ -2878,16 +2881,28 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ rtp_session->dtmf_data.in_digit_seq = in_digit_seq; #ifdef DEBUG_2833 - printf("read: %c %u %u %u %u %d %d %s\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n", key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : ""); #endif + + if (!rtp_session->dtmf_data.in_digit_queued && (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && + rtp_session->dtmf_data.in_digit_ts) { + switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0) }; +#ifdef DEBUG_2833 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); +#endif + switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); + rtp_session->dtmf_data.in_digit_queued = 1; + } + /* only set sanity if we do NOT ignore the packet */ if (rtp_session->dtmf_data.in_digit_ts) { rtp_session->dtmf_data.in_digit_sanity = 2000; } - if (rtp_session->dtmf_data.last_duration > duration && rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) { + if (rtp_session->dtmf_data.last_duration > duration && + rtp_session->dtmf_data.last_duration > 0xFC17 && ts == rtp_session->dtmf_data.in_digit_ts) { rtp_session->dtmf_data.flip++; } @@ -2902,18 +2917,26 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF; rtp_session->dtmf_data.flip = 0; #ifdef DEBUG_2833 - printf("you're welcome!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n"); #endif } #ifdef DEBUG_2833 - printf("done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration); #endif - switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); + + if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) { +#ifdef DEBUG_2833 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); +#endif + switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); + } + rtp_session->dtmf_data.last_digit = rtp_session->dtmf_data.first_digit; rtp_session->dtmf_data.in_digit_ts = 0; rtp_session->dtmf_data.in_digit_sanity = 0; + rtp_session->dtmf_data.in_digit_queued = 0; do_cng = 1; } else { if (!switch_rtp_ready(rtp_session)) { @@ -2932,7 +2955,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ rtp_session->dtmf_data.last_duration = duration; } else { #ifdef DEBUG_2833 - printf("drop: %c %u %u %u %u %d %d\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n", key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end); #endif switch_cond_next(); @@ -2941,10 +2964,27 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } if (rtp_session->dtmf_data.in_digit_ts) { + + } + + + if (bytes && rtp_session->dtmf_data.in_digit_ts) { if (!switch_rtp_ready(rtp_session)) { goto end; } - return_cng_frame(); + + if (!rtp_session->dtmf_data.in_interleaved && rtp_session->recv_msg.header.pt != rtp_session->recv_te) { + /* Drat, they are sending audio still as well as DTMF ok fine..... *sigh* */ + rtp_session->dtmf_data.in_interleaved = 1; + } + + if (rtp_session->dtmf_data.in_interleaved || (rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION)) { + if (rtp_session->recv_msg.header.pt == rtp_session->recv_te) { + goto recvfrom; + } + } else { + return_cng_frame(); + } } timer_check: @@ -3254,7 +3294,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp } frame->datalen = bytes; - return SWITCH_STATUS_SUCCESS; } @@ -3540,7 +3579,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session, #ifdef RTP_DEBUG_WRITE_DELTA { int delta = (int) (now - rtp_session->send_time) / 1000; - printf("WRITE %d delta %d\n", (int) bytes, delta); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WRITE %d delta %d\n", (int) bytes, delta); } #endif rtp_session->send_time = now;