diff --git a/build/sounds_version.txt b/build/sounds_version.txt index 0214d1555f..fca8d25c59 100644 --- a/build/sounds_version.txt +++ b/build/sounds_version.txt @@ -1,3 +1,3 @@ -en-us-callie 1.0.18 +en-us-callie 1.0.22 ru-RU-elena 1.0.13 diff --git a/conf/vanilla/dialplan/default.xml b/conf/vanilla/dialplan/default.xml index 82189d6633..7f5002152f 100644 --- a/conf/vanilla/dialplan/default.xml +++ b/conf/vanilla/dialplan/default.xml @@ -141,6 +141,18 @@ + + + + + + + + + diff --git a/configure.in b/configure.in index 737de28d50..6b46446e83 100644 --- a/configure.in +++ b/configure.in @@ -577,7 +577,7 @@ AX_HAVE_CPU_SET AC_CHECK_LIB(rt, clock_gettime, [AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if you have clock_gettime()])]) AC_CHECK_LIB(rt, clock_getres, [AC_DEFINE(HAVE_CLOCK_GETRES, 1, [Define if you have clock_getres()])]) AC_CHECK_LIB(rt, clock_nanosleep, [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define if you have clock_nanosleep()])]) -AC_CHECK_LIB(pthread, pthread_setschedprio, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPRIO, 1, [Define if you have pthread_setschedprio()])]) +AC_CHECK_LIB(pthread, pthread_setschedparam, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPARAM, 1, [Define if you have pthread_setschedparam()])]) AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket)) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 5307b25573..ad32b90895 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -15,7 +15,6 @@ avoid_mods=( applications/mod_rad_auth applications/mod_skel asr_tts/mod_cepstral - asr_tts/mod_flite codecs/mod_com_g729 codecs/mod_ilbc codecs/mod_sangoma_codec diff --git a/debian/rules b/debian/rules index cd7934e439..959a9e5254 100755 --- a/debian/rules +++ b/debian/rules @@ -6,7 +6,7 @@ FS_CC?=gcc FS_CXX?=g++ -FS_CFLAGS?=-ggdb3 -O2 +FS_CFLAGS?=-ggdb3 -O2 -fPIC FS_CPPFLAGS?= FS_CXXFLAGS?=$(FS_CFLAGS) export PATH?=/usr/lib/ccache:/usr/sbin:/usr/bin:/sbin:/bin diff --git a/docs/ChangeLog b/docs/ChangeLog index d73e3630af..f5e330d00e 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -1,3 +1,11 @@ +freeswitch (1.2.5) + mod_lua: Enable mod_lua to use native pgsql dbh support (r:2cea7f0f) + mod_sofia: Add att_xfer_destination_number variable to indicate the original destination number of the attended transfer leg on REFER for semi-attended transfer scenarios. (r:893cd7be) + sounds: Bump Callie sounds ver to 1.0.22 (r:41e00c78) +freeswitch (1.2.4) + core: Add Postgres core db support (r:0c1180d5) + mod_cdr_mongodb: update MongoDB driver to v0.6 (r:10093b44) + mod_dingaling: do lookup in dingaling when an address is specified as host:foo.bar.com like sofia does (r:fbfe830a) freeswitch (1.2.3) core: add hold_events variable with start and stop times for each hold (r:9a193a9c) core: update json lib in core and ESL and re-apply old patches (r:5a956890) diff --git a/libs/apr/.update b/libs/apr/.update index a55ae9a4f4..c106d5b06f 100644 --- a/libs/apr/.update +++ b/libs/apr/.update @@ -1 +1 @@ -Tue Oct 23 13:13:30 EDT 2012 +Wed Nov 7 10:37:54 CST 2012 diff --git a/libs/apr/configure.in b/libs/apr/configure.in index 412ee7e937..354fa772ba 100644 --- a/libs/apr/configure.in +++ b/libs/apr/configure.in @@ -1620,7 +1620,7 @@ APR_CHECK_DEFINE_FILES(POLLIN, poll.h sys/poll.h) if test "$threads" = "1"; then APR_CHECK_DEFINE(PTHREAD_PROCESS_SHARED, pthread.h) AC_CHECK_FUNCS(pthread_mutexattr_setpshared) - AC_CHECK_LIB(pthread, pthread_setschedprio, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPRIO, 1, [Define if you have pthread_setschedprio()])]) + AC_CHECK_LIB(pthread, pthread_setschedparam, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPARAM, 1, [Define if you have pthread_setschedparam()])]) # Some systems have setpshared and define PROCESS_SHARED, but don't # really support PROCESS_SHARED locks. So, we must validate that we diff --git a/libs/apr/threadproc/unix/thread.c b/libs/apr/threadproc/unix/thread.c index 391e5368c8..8859e79ac7 100644 --- a/libs/apr/threadproc/unix/thread.c +++ b/libs/apr/threadproc/unix/thread.c @@ -146,6 +146,7 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, { apr_status_t stat; pthread_attr_t *temp; + pthread_t tt; (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); @@ -173,15 +174,21 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, return stat; } - if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { + if ((stat = pthread_create(&tt, temp, dummy_worker, (*new))) == 0) { -#ifdef HAVE_PTHREAD_SETSCHEDPRIO +#ifdef HAVE_PTHREAD_SETSCHEDPARAM if (attr && attr->priority) { - pthread_t *thread = (*new)->td; - pthread_setschedprio(*thread, attr->priority); + int policy; + struct sched_param param = { 0 }; + + pthread_getschedparam(tt, &policy, ¶m); + param.sched_priority = attr->priority; + pthread_setschedparam(tt, policy, ¶m); } #endif + *(*new)->td = tt; + return APR_SUCCESS; } else { diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index 3972e7a7b4..59da3d0ab9 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -918,6 +918,7 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char * struct addrinfo hints = { 0 }, *result; struct sockaddr_in *sockaddr_in; struct sockaddr_in6 *sockaddr_in6; + socklen_t socklen; #ifndef WIN32 int fd_flags = 0; #else @@ -951,10 +952,12 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char * case AF_INET: sockaddr_in = (struct sockaddr_in*)&(handle->sockaddr); sockaddr_in->sin_port = htons(port); + socklen = sizeof(struct sockaddr_in); break; case AF_INET6: sockaddr_in6 = (struct sockaddr_in6*)&(handle->sockaddr); sockaddr_in6->sin6_port = htons(port); + socklen = sizeof(struct sockaddr_in6); break; default: strncpy(handle->err, "Host resolves to unsupported address family", sizeof(handle->err)); @@ -985,7 +988,7 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char * #endif } - rval = connect(handle->sock, (struct sockaddr*)&handle->sockaddr, sizeof(handle->sockaddr)); + rval = connect(handle->sock, (struct sockaddr*)&handle->sockaddr, socklen); if (timeout) { int r; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 2f1a5ff9ed..0e22b0f350 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -942,7 +942,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan) ftdm_channel_t *chtmp = chan; if (call) { - pri_destroycall(isdn_data->spri.pri, call); + /* pri call destroy is done by libpri itself (on release_ack) */ chan_priv->call = NULL; } @@ -953,6 +953,9 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan) lpwrap_stop_timer(&isdn_data->spri, &chan_priv->t316); chan_priv->t316_timeout_cnt = 0; + /* Unset remote hangup */ + chan_priv->peerhangup = 0; + if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n", ftdm_channel_get_span_id(chan), @@ -1206,12 +1209,21 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan) { if (call) { ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); - pri_hangup(isdn_data->spri.pri, call, caller_data->hangup_cause); -// pri_destroycall(isdn_data->spri.pri, call); -// chan_priv->call = NULL; + + if (chan_priv->peerhangup) { + /* Call is inbound and hangup has been initiated by peer */ + if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) { + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + } else if (caller_data->hangup_cause == PRI_CAUSE_NO_USER_RESPONSE) { + /* Can happen when we have a DL link expire or some timer expired */ + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + } else if (caller_data->hangup_cause == PRI_CAUSE_DESTINATION_OUT_OF_ORDER) { + /* Can happen when we have a DL link expire or some timer expired */ + ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + } + } } - ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); } break; @@ -1368,6 +1380,7 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even { ftdm_span_t *span = spri->span; ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->hangup.channel); + ftdm_libpri_b_chan_t *chan_priv = chan->call_data; if (!chan) { ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d but it's not in use?\n", ftdm_span_get_id(spri->span), pevent->hangup.channel); @@ -1386,8 +1399,6 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even ftdm_log(FTDM_LOG_DEBUG, "-- Hangup REQ on channel %d:%d\n", ftdm_span_get_id(spri->span), pevent->hangup.channel); - pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause); - chan->caller_data.hangup_cause = pevent->hangup.cause; switch (ftdm_channel_get_state(chan)) { @@ -1400,19 +1411,27 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even } break; - case LPWRAP_PRI_EVENT_HANGUP_ACK: /* */ + case LPWRAP_PRI_EVENT_HANGUP_ACK: /* RELEASE_COMPLETE */ ftdm_log(FTDM_LOG_DEBUG, "-- Hangup ACK on channel %d:%d\n", ftdm_span_get_id(spri->span), pevent->hangup.channel); - pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause); - - ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + switch (ftdm_channel_get_state(chan)) { + case FTDM_CHANNEL_STATE_RESTART: + /* ACK caused by DL FAILURE in DISC REQ */ + ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN); + break; + default: + ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + break; + } break; case LPWRAP_PRI_EVENT_HANGUP: /* "RELEASE/RELEASE_COMPLETE/other" */ ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", ftdm_span_get_id(spri->span), pevent->hangup.channel); + chan_priv->peerhangup = 1; + switch (ftdm_channel_get_state(chan)) { case FTDM_CHANNEL_STATE_DIALING: case FTDM_CHANNEL_STATE_RINGING: @@ -1424,9 +1443,19 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING); break; case FTDM_CHANNEL_STATE_HANGUP: + /* this will send "RELEASE_COMPLETE", eventually */ + pri_hangup(spri->pri, pevent->hangup.call, chan->caller_data.hangup_cause); chan->caller_data.hangup_cause = pevent->hangup.cause; ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); break; + case FTDM_CHANNEL_STATE_RESTART: + /* + * We got an hungup doing a restart, normally beacause link has been lost during + * a call and the T309 timer has expired. So destroy it :) (DL_RELEASE_IND) + */ + pri_destroycall(spri->pri, pevent->hangup.call); + ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN); + break; // case FTDM_CHANNEL_STATE_TERMINATING: // ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP); // break; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h index 26db8d3155..852f5caaca 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h @@ -131,6 +131,7 @@ struct ftdm_libpri_b_chan { q931_call *call; /*!< libpri opaque call handle */ uint32_t flags; /*!< channel flags */ uint32_t t316_timeout_cnt; /*!< T316 timeout counter */ + int peerhangup; /*!< hangup requested from libpri (RELEASE/RELEASE_ACK/DL_RELEASE/TIMERS EXPIRY) */ }; typedef struct ftdm_libpri_b_chan ftdm_libpri_b_chan_t; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c index c9f0576951..44518a4496 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c @@ -169,6 +169,10 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t * if (spri->pri) { pri_set_debug(spri->pri, debug); +#ifdef HAVE_LIBPRI_BRI + /* "follow Q.931 Section 5.3.2 call hangup better" */ + pri_hangup_fix_enable(spri->pri, 1); +#endif #ifdef HAVE_LIBPRI_AOC pri_aoc_events_enable(spri->pri, 1); #endif diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 363dcee7c5..c088c1453f 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -102,6 +102,7 @@ struct ioctl_codes { ioctlcmd SETTXBITS; ioctlcmd GETRXBITS; ioctlcmd SETPOLARITY; + ioctlcmd TONEDETECT; }; /** @@ -139,7 +140,8 @@ static struct ioctl_codes zt_ioctl_codes = { .GETCONFMUTE = ZT_GETCONFMUTE, .ECHOTRAIN = ZT_ECHOTRAIN, .SETTXBITS = ZT_SETTXBITS, - .GETRXBITS = ZT_GETRXBITS + .GETRXBITS = ZT_GETRXBITS, + .TONEDETECT = ZT_TONEDETECT, }; /** @@ -178,7 +180,8 @@ static struct ioctl_codes dahdi_ioctl_codes = { .ECHOTRAIN = DAHDI_ECHOTRAIN, .SETTXBITS = DAHDI_SETTXBITS, .GETRXBITS = DAHDI_GETRXBITS, - .SETPOLARITY = DAHDI_SETPOLARITY + .SETPOLARITY = DAHDI_SETPOLARITY, + .TONEDETECT = DAHDI_TONEDETECT, }; #define ZT_INVALID_SOCKET -1 @@ -271,6 +274,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f { unsigned configured = 0, x; zt_params_t ztp; + zt_tone_mode_t mode = 0; memset(&ztp, 0, sizeof(ztp)); @@ -361,7 +365,7 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f cc.sigtype = ZT_SIG_CAS; cc.idlebits = cas_bits; if (ioctl(CONTROL_FD, codes.CHANCONFIG, &cc)) { - ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd, strerror(errno)); + ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s as FreeTDM device %d:%d fd:%d err:%s\n", chanpath, ftdmchan->span_id, ftdmchan->chan_id, sockfd, strerror(errno)); close(sockfd); continue; } @@ -436,12 +440,23 @@ static unsigned zt_open_range(ftdm_span_t *span, unsigned start, unsigned end, f continue; } + mode = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE; + if (ioctl(sockfd, codes.TONEDETECT, &mode)) { + ftdm_log(FTDM_LOG_DEBUG, "HW DTMF not available on FreeTDM device %d:%d fd:%d\n", ftdmchan->span_id, ftdmchan->chan_id, sockfd); + } else { + ftdm_log(FTDM_LOG_DEBUG, "HW DTMF available on FreeTDM device %d:%d fd:%d\n", ftdmchan->span_id, ftdmchan->chan_id, sockfd); + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT); + mode = 0; + ioctl(sockfd, codes.TONEDETECT, &mode); + } + if (!ftdm_strlen_zero(name)) { ftdm_copy_string(ftdmchan->chan_name, name, sizeof(ftdmchan->chan_name)); } if (!ftdm_strlen_zero(number)) { ftdm_copy_string(ftdmchan->chan_number, number, sizeof(ftdmchan->chan_number)); } + configured++; } else { ftdm_log(FTDM_LOG_ERROR, "failure configuring device %s\n", chanpath); @@ -666,7 +681,6 @@ static FIO_OPEN_FUNCTION(zt_open) } } } - } return FTDM_SUCCESS; } @@ -858,6 +872,24 @@ static FIO_COMMAND_FUNCTION(zt_command) err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode); } break; + case FTDM_COMMAND_SET_RX_QUEUE_SIZE: + case FTDM_COMMAND_SET_TX_QUEUE_SIZE: + /* little white lie ... eventually we can implement this, in the meantime, not worth the effort + and this is only used by some sig modules such as ftmod_r2 to behave bettter under load */ + err = 0; + break; + case FTDM_COMMAND_ENABLE_DTMF_DETECT: + { + zt_tone_mode_t mode = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE; + err = ioctl(ftdmchan->sockfd, codes.TONEDETECT, &mode); + } + break; + case FTDM_COMMAND_DISABLE_DTMF_DETECT: + { + zt_tone_mode_t mode = 0; + err = ioctl(ftdmchan->sockfd, codes.TONEDETECT, &mode); + } + break; default: err = FTDM_NOTIMPL; break; @@ -949,7 +981,7 @@ pollagain: pfds[0].fd = ftdmchan->sockfd; pfds[0].events = inflags; result = poll(pfds, 1, to); - *flags = 0; + *flags = FTDM_NO_FLAGS; if (result < 0 && errno == EINTR) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "DAHDI wait got interrupted, trying again\n"); @@ -965,8 +997,6 @@ pollagain: inflags = pfds[0].revents; } - *flags = FTDM_NO_FLAGS; - if (result < 0){ snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Poll failed"); ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to poll DAHDI device: %s\n", strerror(errno)); @@ -1042,6 +1072,23 @@ FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event) return k ? FTDM_SUCCESS : FTDM_FAIL; } +static __inline__ int handle_dtmf_event(ftdm_channel_t *fchan, zt_event_t zt_event_id) +{ + if ((zt_event_id & ZT_EVENT_DTMFUP)) { + int digit = (zt_event_id & (~ZT_EVENT_DTMFUP)); + char tmp_dtmf[2] = { digit, 0 }; + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "DTMF UP [%d]\n", digit); + ftdm_channel_queue_dtmf(fchan, tmp_dtmf); + return 0; + } else if ((zt_event_id & ZT_EVENT_DTMFDOWN)) { + int digit = (zt_event_id & (~ZT_EVENT_DTMFDOWN)); + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "DTMF DOWN [%d]\n", digit); + return 0; + } else { + return -1; + } +} + /** * \brief Process an event from a ftdmchan and set the proper OOB event_id. The channel must be locked. * \param fchan Channel to retrieve event from @@ -1151,8 +1198,12 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan, break; default: { - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Unhandled event %d\n", zt_event_id); - *event_id = FTDM_OOB_INVALID; + if (handle_dtmf_event(fchan, zt_event_id)) { + ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Unhandled event %d\n", zt_event_id); + *event_id = FTDM_OOB_INVALID; + } else { + *event_id = FTDM_OOB_NOOP; + } } break; } @@ -1308,8 +1359,12 @@ tryagain: ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event after ELAST on write: %s\n", strerror(errno)); return FTDM_FAIL; } - /* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */ - ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dropping event %d to be able to write data\n", zt_event_id); + + if (handle_dtmf_event(ftdmchan, zt_event_id)) { + /* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */ + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dropping event %d to be able to write data\n", zt_event_id); + } + goto tryagain; } @@ -1325,7 +1380,6 @@ static FIO_CHANNEL_DESTROY_FUNCTION(zt_channel_destroy) { close(ftdmchan->sockfd); ftdmchan->sockfd = ZT_INVALID_SOCKET; - return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h index c9bb171b55..9d680668d2 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.h @@ -195,7 +195,9 @@ typedef enum { ZT_EVENT_TIMER_EXPIRED = 15, ZT_EVENT_TIMER_PING = 16, ZT_EVENT_POLARITY = 17, - ZT_EVENT_RINGBEGIN = 18 + ZT_EVENT_RINGBEGIN = 18, + ZT_EVENT_DTMFDOWN = (1 << 17), + ZT_EVENT_DTMFUP = (1 << 18), } zt_event_t; typedef enum { @@ -258,6 +260,12 @@ ZT_BBIT = 4, ZT_ABIT = 8 } zt_cas_bit_t; +typedef enum { +/* Tone Detection */ +ZT_TONEDETECT_ON = (1 << 0), /* Detect tones */ +ZT_TONEDETECT_MUTE = (1 << 1) /* Mute audio in received channel */ +} zt_tone_mode_t; + /* Defines */ #define ZT_MAX_BLOCKSIZE 8192 @@ -312,6 +320,11 @@ ZT_ABIT = 8 #define ZT_SETTXBITS _IOW (ZT_CODE, 43, int) #define ZT_GETRXBITS _IOR (ZT_CODE, 45, int) +/* + * Enable tone detection -- implemented by low level driver + */ +#define ZT_TONEDETECT _IOW(ZT_CODE, 91, int) + #define DAHDI_GET_BLOCKSIZE _IOR (DAHDI_CODE, 1, int) /* Get Transfer Block Size. */ #define DAHDI_SET_BLOCKSIZE _IOW (DAHDI_CODE, 1, int) /* Set Transfer Block Size. */ #define DAHDI_FLUSH _IOW (DAHDI_CODE, 3, int) /* Flush Buffer(s) and stop I/O */ @@ -361,6 +374,11 @@ ZT_ABIT = 8 #define DAHDI_SETPOLARITY _IOW (DAHDI_CODE, 92, int) /* Polarity setting for FXO lines */ +/* + * Enable tone detection -- implemented by low level driver + */ +#define DAHDI_TONEDETECT _IOW(DAHDI_CODE, 91, int) + #endif /* For Emacs: diff --git a/libs/libedit/src/unvis.c b/libs/libedit/src/unvis.c index 5b22184c9c..3d71f6f227 100644 --- a/libs/libedit/src/unvis.c +++ b/libs/libedit/src/unvis.c @@ -45,7 +45,7 @@ __RCSID("$NetBSD: unvis.c,v 1.28 2005/09/13 01:44:09 christos Exp $"); #include #include -#if defined(__weak_reference) && !defined(__FreeBSD__) +#if defined(__weak_reference) && !defined(__FreeBSD__) && !defined(__NetBSD__) __weak_alias(strunvis,_strunvis) #endif diff --git a/libs/libedit/src/vi.c b/libs/libedit/src/vi.c index bb408d329c..f09ba6c1ce 100644 --- a/libs/libedit/src/vi.c +++ b/libs/libedit/src/vi.c @@ -915,14 +915,14 @@ vi_comment_out(EditLine *el, int c) * NB: posix implies that we should enter insert mode, however * this is against historical precedent... */ -#if defined(__weak_reference) && !defined(__FreeBSD__) +#if defined(__weak_reference) && !defined(__FreeBSD__) && !defined(__NetBSD__) extern char *get_alias_text(const char *) __weak_reference(get_alias_text); #endif protected el_action_t /*ARGSUSED*/ vi_alias(EditLine *el, int c) { -#if defined(__weak_reference) && !defined(__FreeBSD__) +#if defined(__weak_reference) && !defined(__FreeBSD__) && !defined(__NetBSD__) char alias_name[3]; char *alias_text; diff --git a/libs/libedit/src/vis.c b/libs/libedit/src/vis.c index b37f7141e3..673caa9a15 100644 --- a/libs/libedit/src/vis.c +++ b/libs/libedit/src/vis.c @@ -88,7 +88,7 @@ __RCSID("$NetBSD: vis.c,v 1.35 2006/08/28 20:42:12 christos Exp $"); #include #include -#if defined(__weak_reference) && !defined(__FreeBSD__) +#if defined(__weak_reference) && !defined(__FreeBSD__) && !defined(__NetBSD__) __weak_alias(strsvis,_strsvis) __weak_alias(strsvisx,_strsvisx) __weak_alias(strvis,_strvis) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 09f61c0ed4..b50d284902 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Fri Nov 2 13:36:06 CDT 2012 +Tue Nov 13 15:22:19 CST 2012 diff --git a/libs/sofia-sip/configure.ac b/libs/sofia-sip/configure.ac index 1bce33e178..f882bc76b4 100644 --- a/libs/sofia-sip/configure.ac +++ b/libs/sofia-sip/configure.ac @@ -254,7 +254,7 @@ if test x"$have_check" = "xyes"; then fi AC_CHECK_HEADERS([fnmatch.h]) -AC_CHECK_LIB(pthread, pthread_setschedprio, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPRIO, 1, [Define if you have pthread_setschedprio()])]) +AC_CHECK_LIB(pthread, pthread_setschedparam, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPARAM, 1, [Define if you have pthread_setschedparam()])]) dnl dl is currently used only in testing diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 709e678d86..c9bbea2d6b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -9211,7 +9211,7 @@ int outgoing_recv(nta_outgoing_t *_orq, if (orq->orq_destroyed && 200 <= status && status < 300) { if (orq->orq_uas && su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) != 0) { /* Orphan 200 Ok to INVITE. ACK and BYE it */ - SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE\n" VA_NONE)); + SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE %p\n", (void *)orq)); return nta_msg_ackbye(sa, msg); } return -1; /* Proxy statelessly (RFC3261 section 16.11) */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c index 3316d535c3..9b862415a3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -1245,6 +1245,7 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) int status = 200; char const *phrase = "OK", *reason = NULL; char const *invite_branch; + char const *pl_s = NULL; assert(cr->cr_orq); assert(cr->cr_method == sip_method_invite); @@ -1256,6 +1257,11 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) goto error; } + tl_gets(tags, + SIPTAG_PAYLOAD_STR_REF(pl_s), + TAG_END()); + + assert(ds->ds_leg); msg = nta_outgoing_getrequest(cr->cr_orq); @@ -1305,7 +1311,7 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) while (sip->sip_supported) sip_header_remove(msg, sip, (sip_header_t*)sip->sip_supported); - if (ss == NULL || ss->ss_state > nua_callstate_ready) + if (ss == NULL || ss->ss_state > nua_callstate_ready || pl_s) ; else if (cr->cr_offer_recv && !cr->cr_answer_sent) { if (nh->nh_soa == NULL) { diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su.c b/libs/sofia-sip/libsofia-sip-ua/su/su.c index 8067fdec60..c99d32f24d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su.c @@ -510,13 +510,20 @@ issize_t su_vsend(su_socket_t s, su_sockaddr_t const *su, socklen_t sulen) { struct msghdr hdr[1] = {{0}}; + int rv; hdr->msg_name = (void *)su; hdr->msg_namelen = sulen; hdr->msg_iov = (struct iovec *)iov; hdr->msg_iovlen = iovlen; - return sendmsg(s, hdr, flags); + do { + if ((rv = sendmsg(s, hdr, flags)) == -1) { + if (errno == EAGAIN) usleep(1000); + } + } while (rv == -1 && (errno == EAGAIN || errno == EINTR)); + + return rv; } issize_t su_vrecv(su_socket_t s, su_iovec_t iov[], isize_t iovlen, int flags, @@ -531,7 +538,9 @@ issize_t su_vrecv(su_socket_t s, su_iovec_t iov[], isize_t iovlen, int flags, hdr->msg_iov = (struct iovec *)iov; hdr->msg_iovlen = iovlen; - retval = recvmsg(s, hdr, flags); + do { + retval = recvmsg(s, hdr, flags); + } while (retval == -1 && errno == EINTR); if (su && sulen) *sulen = hdr->msg_namelen; diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c index 5eb391f38d..d20eb709bd 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c @@ -268,9 +268,13 @@ int su_pthreaded_port_start(su_port_create_f *create, pthread_mutex_lock(arg.mutex); if (pthread_create(&tid, &attr, su_pthread_port_clone_main, &arg) == 0) { +#ifdef HAVE_PTHREAD_SETSCHEDPARAM + int policy; + struct sched_param param; -#ifdef HAVE_PTHREAD_SETSCHEDPRIO - pthread_setschedprio(tid, 99); + pthread_getschedparam(tid, &policy, ¶m); + param.sched_priority = 99; + pthread_setschedparam(tid, policy, ¶m); #endif pthread_cond_wait(arg.cv, arg.mutex); diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index 1fede6ed79..9b70a7a73b 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.h @@ -212,6 +212,9 @@ struct t30_state_s /*! \brief TRUE once the far end FAX entity has been detected. */ int far_end_detected; + + /*! \brief TRUE once the end of procedure condition has been detected. */ + int end_of_procedure_detected; /*! \brief TRUE if a local T.30 interrupt is pending. */ int local_interrupt_pending; diff --git a/libs/spandsp/src/spandsp/telephony.h b/libs/spandsp/src/spandsp/telephony.h index 7a09bbe044..132cce9bf8 100644 --- a/libs/spandsp/src/spandsp/telephony.h +++ b/libs/spandsp/src/spandsp/telephony.h @@ -88,6 +88,16 @@ typedef int (*span_tx_handler_t)(void *s, int16_t amp[], int max_len); #define FP_Q_2_14(x) ((int16_t) (16384.0*x + ((x >= 0.0) ? 0.5 : -0.5))) #define FP_Q_1_15(x) ((int16_t) (32768.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_9_7_32(x) ((int32_t) (128.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_8_8_32(x) ((int32_t) (256.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_7_9_32(x) ((int32_t) (512.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_6_10_32(x) ((int32_t) (1024.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_5_11_32(x) ((int32_t) (2048.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_4_12_32(x) ((int32_t) (4096.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_3_13_32(x) ((int32_t) (8192.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_2_14_32(x) ((int32_t) (16384.0*x + ((x >= 0.0) ? 0.5 : -0.5))) +#define FP_Q_1_15_32(x) ((int32_t) (32768.0*x + ((x >= 0.0) ? 0.5 : -0.5))) + #define FP_Q_9_23(x) ((int32_t) (65536.0*128.0*x + ((x >= 0.0) ? 0.5 : -0.5))) #define FP_Q_8_24(x) ((int32_t) (65536.0*256.0*x + ((x >= 0.0) ? 0.5 : -0.5))) #define FP_Q_7_25(x) ((int32_t) (65536.0*512.0*x + ((x >= 0.0) ? 0.5 : -0.5))) diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index a12d357f76..7772459aba 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -132,19 +132,19 @@ enum static const char *phase_names[] = { - "T30_PHASE_IDLE", - "T30_PHASE_A_CED", - "T30_PHASE_A_CNG", - "T30_PHASE_B_RX", - "T30_PHASE_B_TX", - "T30_PHASE_C_NON_ECM_RX", - "T30_PHASE_C_NON_ECM_TX", - "T30_PHASE_C_ECM_RX", - "T30_PHASE_C_ECM_TX", - "T30_PHASE_D_RX", - "T30_PHASE_D_TX", - "T30_PHASE_E", - "T30_PHASE_CALL_FINISHED" + "IDLE", + "A_CED", + "A_CNG", + "B_RX", + "B_TX", + "C_NON_ECM_RX", + "C_NON_ECM_TX", + "C_ECM_RX", + "C_ECM_TX", + "D_RX", + "D_TX", + "E", + "CALL_FINISHED" }; /* These state names are modelled after places in the T.30 flow charts. */ @@ -184,6 +184,43 @@ enum T30_STATE_CALL_FINISHED }; +static const char *state_names[] = +{ + "NONE", + "ANSWERING", + "B", + "C", + "D", + "D_TCF", + "D_POST_TCF", + "F_TCF", + "F_CFR", + "F_FTT", + "F_DOC_NON_ECM", + "F_POST_DOC_NON_ECM", + "F_DOC_ECM", + "F_POST_DOC_ECM", + "F_POST_RCP_MCF", + "F_POST_RCP_PPR", + "F_POST_RCP_RNR", + "R", + "T", + "I", + "II", + "II_Q", + "III_Q_MCF", + "III_Q_RTP", + "III_Q_RTN", + "IV", + "IV_PPS_NULL", + "IV_PPS_Q", + "IV_PPS_RNR", + "IV_CTC", + "IV_EOR", + "IV_EOR_RNR", + "CALL_FINISHED" +}; + enum { T30_MIN_SCAN_20MS = 0, @@ -1309,7 +1346,7 @@ static int build_dcs(t30_state_t *s) int i; int bad; int row_squashing_ratio; - + /* Make a DCS frame based on local issues and the latest received DIS/DTC frame. Negotiate the result based on what both parties can do. */ s->dcs_frame[0] = ADDRESS_FIELD; @@ -2017,7 +2054,7 @@ static int start_receiving_document(t30_state_t *s) static void unexpected_non_final_frame(t30_state_t *s, const uint8_t *msg, int len) { - span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %s\n", t30_frametype(msg[2]), state_names[s->state]); if (s->current_status == T30_ERR_OK) t30_set_status(s, T30_ERR_UNEXPECTED); } @@ -2025,7 +2062,7 @@ static void unexpected_non_final_frame(t30_state_t *s, const uint8_t *msg, int l static void unexpected_final_frame(t30_state_t *s, const uint8_t *msg, int len) { - span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %d\n", t30_frametype(msg[2]), s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame in state %s\n", t30_frametype(msg[2]), state_names[s->state]); if (s->current_status == T30_ERR_OK) t30_set_status(s, T30_ERR_UNEXPECTED); send_dcn(s); @@ -2473,17 +2510,15 @@ static int send_response_to_pps(t30_state_t *s) { set_state(s, T30_STATE_F_POST_RCP_MCF); send_simple_frame(s, T30_MCF); + return TRUE; } - else - { - /* We need to send the PPR frame we have created, to try to fill in the missing/bad data. */ - set_state(s, T30_STATE_F_POST_RCP_PPR); - s->ecm_frame_map[0] = ADDRESS_FIELD; - s->ecm_frame_map[1] = CONTROL_FIELD_FINAL_FRAME; - s->ecm_frame_map[2] = (uint8_t) (T30_PPR | s->dis_received); - send_frame(s, s->ecm_frame_map, 3 + 32); - } - return 0; + /* We need to send the PPR frame we have created, to try to fill in the missing/bad data. */ + set_state(s, T30_STATE_F_POST_RCP_PPR); + s->ecm_frame_map[0] = ADDRESS_FIELD; + s->ecm_frame_map[1] = CONTROL_FIELD_FINAL_FRAME; + s->ecm_frame_map[2] = (uint8_t) (T30_PPR | s->dis_received); + send_frame(s, s->ecm_frame_map, 3 + 32); + return FALSE; } /*- End of function --------------------------------------------------------*/ @@ -2685,7 +2720,17 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len) } else { - send_response_to_pps(s); + if (send_response_to_pps(s)) + { + switch (s->last_pps_fcf2) + { + case T30_PRI_EOP: + case T30_EOP: + span_log(&s->logging, SPAN_LOG_FLOW, "End of procedure detected\n"); + s->end_of_procedure_detected = TRUE; + break; + } + } } break; default: @@ -3364,6 +3409,8 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, } /* Fall through */ case T30_EOP: + span_log(&s->logging, SPAN_LOG_FLOW, "End of procedure detected\n"); + s->end_of_procedure_detected = TRUE; s->next_rx_step = fcf; queue_phase(s, T30_PHASE_D_TX); switch (copy_quality(s)) @@ -3397,7 +3444,6 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg, send_simple_frame(s, T30_RTN); break; } - break; case T30_DCN: t30_set_status(s, T30_ERR_RX_DCNFAX); @@ -3565,7 +3611,17 @@ static void process_state_f_post_rcp_rnr(t30_state_t *s, const uint8_t *msg, int else { /* Now we send the deferred response */ - send_response_to_pps(s); + if (send_response_to_pps(s)) + { + switch (s->last_pps_fcf2) + { + case T30_PRI_EOP: + case T30_EOP: + span_log(&s->logging, SPAN_LOG_FLOW, "End of procedure detected\n"); + s->end_of_procedure_detected = TRUE; + break; + } + } } break; case T30_CRP: @@ -4656,7 +4712,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len) /* The following handles context sensitive message types, which should occur at the end of message sequences. They should, therefore have the final frame flag set. */ - span_log(&s->logging, SPAN_LOG_FLOW, "Rx final frame in state %d\n", s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "Rx final frame in state %s\n", state_names[s->state]); switch (s->state) { @@ -4891,7 +4947,7 @@ static void set_state(t30_state_t *s, int state) { if (s->state != state) { - span_log(&s->logging, SPAN_LOG_FLOW, "Changing from state %d to %d\n", s->state, state); + span_log(&s->logging, SPAN_LOG_FLOW, "Changing from state %s to %s\n", state_names[s->state], state_names[state]); s->state = state; } s->step = 0; @@ -4982,9 +5038,9 @@ static void repeat_last_command(t30_state_t *s) default: span_log(&s->logging, SPAN_LOG_FLOW, - "Repeat command called with nothing to repeat - phase %s, state %d\n", + "Repeat command called with nothing to repeat - phase %s, state %s\n", phase_names[s->phase], - s->state); + state_names[s->state]); break; } } @@ -5098,7 +5154,7 @@ static void timer_t2_t4_stop(t30_state_t *s) static void timer_t0_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired in state %d\n", s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired in state %s\n", state_names[s->state]); t30_set_status(s, T30_ERR_T0_EXPIRED); /* Just end the call */ disconnect(s); @@ -5107,7 +5163,7 @@ static void timer_t0_expired(t30_state_t *s) static void timer_t1_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T1 expired in state %d\n", s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T1 expired in state %s\n", state_names[s->state]); /* The initial connection establishment has timeout out. In other words, we have been unable to communicate successfully with a remote machine. It is time to abandon the call. */ @@ -5132,7 +5188,7 @@ static void timer_t1_expired(t30_state_t *s) static void timer_t2_expired(t30_state_t *s) { if (s->timer_t2_t4_is != TIMER_IS_T2B) - span_log(&s->logging, SPAN_LOG_FLOW, "T2 expired in phase %s, state %d\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T2 expired in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]); switch (s->state) { case T30_STATE_III_Q_MCF: @@ -5202,7 +5258,7 @@ static void timer_t2_expired(t30_state_t *s) static void timer_t1a_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T1A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T1A expired in phase %s, state %s. An HDLC frame lasted too long.\n", phase_names[s->phase], state_names[s->state]); t30_set_status(s, T30_ERR_HDLC_CARRIER); disconnect(s); } @@ -5210,7 +5266,7 @@ static void timer_t1a_expired(t30_state_t *s) static void timer_t2a_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T2A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T2A expired in phase %s, state %s. An HDLC frame lasted too long.\n", phase_names[s->phase], state_names[s->state]); t30_set_status(s, T30_ERR_HDLC_CARRIER); disconnect(s); } @@ -5218,14 +5274,14 @@ static void timer_t2a_expired(t30_state_t *s) static void timer_t2b_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T2B expired in phase %s, state %d. The line is now quiet.\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T2B expired in phase %s, state %s. The line is now quiet.\n", phase_names[s->phase], state_names[s->state]); timer_t2_expired(s); } /*- End of function --------------------------------------------------------*/ static void timer_t3_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T3 expired in phase %s, state %d\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T3 expired in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]); t30_set_status(s, T30_ERR_T3_EXPIRED); disconnect(s); } @@ -5235,7 +5291,7 @@ static void timer_t4_expired(t30_state_t *s) { /* There was no response (or only a corrupt response) to a command, within the T4 timeout period. */ - span_log(&s->logging, SPAN_LOG_FLOW, "T4 expired in phase %s, state %d\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T4 expired in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]); /* Of course, things might just be a little late, especially if there are T.38 links in the path. There is no point in simply timing out, and resending, if we are currently receiving something from the far end - its a half-duplex @@ -5249,7 +5305,7 @@ static void timer_t4_expired(t30_state_t *s) static void timer_t4a_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T4A expired in phase %s, state %d. An HDLC frame lasted too long.\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T4A expired in phase %s, state %s. An HDLC frame lasted too long.\n", phase_names[s->phase], state_names[s->state]); t30_set_status(s, T30_ERR_HDLC_CARRIER); disconnect(s); } @@ -5257,7 +5313,7 @@ static void timer_t4a_expired(t30_state_t *s) static void timer_t4b_expired(t30_state_t *s) { - span_log(&s->logging, SPAN_LOG_FLOW, "T4B expired in phase %s, state %d. The line is now quiet.\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T4B expired in phase %s, state %s. The line is now quiet.\n", phase_names[s->phase], state_names[s->state]); timer_t4_expired(s); } /*- End of function --------------------------------------------------------*/ @@ -5265,7 +5321,7 @@ static void timer_t4b_expired(t30_state_t *s) static void timer_t5_expired(t30_state_t *s) { /* Give up waiting for the receiver to become ready in error correction mode */ - span_log(&s->logging, SPAN_LOG_FLOW, "T5 expired in phase %s, state %d\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "T5 expired in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]); t30_set_status(s, T30_ERR_TX_T5EXP); } /*- End of function --------------------------------------------------------*/ @@ -5351,7 +5407,7 @@ static void t30_non_ecm_rx_status(void *user_data, int status) int was_trained; s = (t30_state_t *) user_data; - span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM signal status is %s (%d) in state %d\n", signal_status_to_str(status), status, s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM signal status is %s (%d) in state %s\n", signal_status_to_str(status), status, state_names[s->state]); switch (status) { case SIG_STATUS_TRAINING_IN_PROGRESS: @@ -5555,7 +5611,7 @@ SPAN_DECLARE_NONSTD(int) t30_non_ecm_get_bit(void *user_data) bit = 0; break; default: - span_log(&s->logging, SPAN_LOG_WARNING, "t30_non_ecm_get_bit in bad state %d\n", s->state); + span_log(&s->logging, SPAN_LOG_WARNING, "t30_non_ecm_get_bit in bad state %s\n", state_names[s->state]); bit = SIG_STATUS_END_OF_DATA; break; } @@ -5590,7 +5646,7 @@ SPAN_DECLARE(int) t30_non_ecm_get(void *user_data, uint8_t buf[], int max_len) len = 0; break; default: - span_log(&s->logging, SPAN_LOG_WARNING, "t30_non_ecm_get in bad state %d\n", s->state); + span_log(&s->logging, SPAN_LOG_WARNING, "t30_non_ecm_get in bad state %s\n", state_names[s->state]); len = -1; break; } @@ -5604,7 +5660,7 @@ static void t30_hdlc_rx_status(void *user_data, int status) int was_trained; s = (t30_state_t *) user_data; - span_log(&s->logging, SPAN_LOG_FLOW, "HDLC signal status is %s (%d) in state %d\n", signal_status_to_str(status), status, s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "HDLC signal status is %s (%d) in state %s\n", signal_status_to_str(status), status, state_names[s->state]); switch (status) { case SIG_STATUS_TRAINING_IN_PROGRESS: @@ -5798,7 +5854,7 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status) switch (status) { case T30_FRONT_END_SEND_STEP_COMPLETE: - span_log(&s->logging, SPAN_LOG_FLOW, "Send complete in phase %s, state %d\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "Send complete in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]); /* We have finished sending our messages, so move on to the next operation. */ switch (s->state) { @@ -6025,12 +6081,12 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status) disconnect from the far end overlaps something. */ break; default: - span_log(&s->logging, SPAN_LOG_FLOW, "Bad state for send complete in t30_front_end_status - %d\n", s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "Bad state for send complete in t30_front_end_status - %s\n", state_names[s->state]); break; } break; case T30_FRONT_END_RECEIVE_COMPLETE: - span_log(&s->logging, SPAN_LOG_FLOW, "Receive complete in phase %s, state %d\n", phase_names[s->phase], s->state); + span_log(&s->logging, SPAN_LOG_FLOW, "Receive complete in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]); /* Usually receive complete is notified by a carrier down signal. However, in cases like a T.38 packet stream dying in the middle of reception there needs to be a means to stop things. */ @@ -6175,8 +6231,12 @@ SPAN_DECLARE(void) t30_terminate(t30_state_t *s) hussle things along. */ break; default: - /* The call terminated prematurely. */ - t30_set_status(s, T30_ERR_CALLDROPPED); + /* If we have seen a genuine EOP or PRI_EOP, that's good enough. */ + if (!s->end_of_procedure_detected) + { + /* The call terminated prematurely. */ + t30_set_status(s, T30_ERR_CALLDROPPED); + } break; } if (s->phase_e_handler) @@ -6268,6 +6328,7 @@ SPAN_DECLARE(int) t30_restart(t30_state_t *s) s->rtp_events = 0; s->local_interrupt_pending = FALSE; s->far_end_detected = FALSE; + s->end_of_procedure_detected = FALSE; s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0); if (s->calling_party) { diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 2e2f25c706..4fb764fa6f 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -661,7 +661,7 @@ static int make_header(t4_tx_state_t *s) if ((s->header_text = malloc(132 + 1)) == NULL) return -1; } - /* This is very English oriented, but then most FAX machines are. Some + /* This is very English oriented, but then most FAX machines are, too. Some measure of i18n in the time and date, and even the header_info string, is entirely possible, although the font area would need some serious work to properly deal with East Asian script. There is no spec for what the header @@ -733,26 +733,21 @@ static int header_row_read_handler(void *user_data, uint8_t buf[], size_t len) return len; } } - switch (s->tiff.image_type) + row = s->header_row/repeats; + pos = 0; + for (t = s->header_text; *t && pos <= len - 2; t++) { - case T4_IMAGE_TYPE_BILEVEL: - row = s->header_row/repeats; - pos = 0; - for (t = s->header_text; *t && pos <= len - 2; t++) - { - pattern = header_font[(uint8_t) *t][row]; - buf[pos++] = (uint8_t) (pattern >> 8); - buf[pos++] = (uint8_t) (pattern & 0xFF); - } - while (pos < len) - buf[pos++] = 0; - s->header_row++; - if (s->header_row >= 16*repeats) - { - /* End of header. Change to normal image row data. */ - set_row_read_handler(s, s->row_handler, s->row_handler_user_data); - } - break; + pattern = header_font[(uint8_t) *t][row]; + buf[pos++] = (uint8_t) (pattern >> 8); + buf[pos++] = (uint8_t) (pattern & 0xFF); + } + while (pos < len) + buf[pos++] = 0; + s->header_row++; + if (s->header_row >= 16*repeats) + { + /* End of header. Change to normal image row data. */ + set_row_read_handler(s, s->row_handler, s->row_handler_user_data); } return len; } @@ -1113,7 +1108,7 @@ SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s) break; } /* If there is a page header, create that first */ - if (s->header_info && s->header_info[0] && make_header(s) == 0) + if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL && s->header_info && s->header_info[0] && make_header(s) == 0) { s->header_row = 0; set_row_read_handler(s, header_row_read_handler, (void *) s); diff --git a/libs/spandsp/tests/fax_decode.c b/libs/spandsp/tests/fax_decode.c index 722f40681f..ea6da19125 100644 --- a/libs/spandsp/tests/fax_decode.c +++ b/libs/spandsp/tests/fax_decode.c @@ -106,6 +106,7 @@ int image_width = 1728; int octets_per_ecm_frame = 256; int error_correcting_mode = FALSE; int current_fallback = 0; +int end_of_page_detected = FALSE; static void decode_20digit_msg(const uint8_t *pkt, int len) { @@ -232,8 +233,6 @@ static int check_rx_dcs(const uint8_t *msg, int len) if ((current_fallback = find_fallback_entry(dcs_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))) < 0) printf("Remote asked for a modem standard we do not support\n"); error_correcting_mode = ((dcs_frame[6] & DISBIT3) != 0); - - //v17_rx_restart(&v17, fallback_sequence[fallback_entry].bit_rate, FALSE); return 0; } /*- End of function --------------------------------------------------------*/ @@ -298,6 +297,7 @@ static void t4_begin(void) t4_rx_start_page(&t4_rx_state); t4_up = TRUE; + end_of_page_detected = FALSE; for (i = 0; i < 256; i++) ecm_len[i] = -1; @@ -381,7 +381,9 @@ static void v17_put_bit(void *user_data, int bit) if (t4_rx_put_bit(&t4_rx_state, bit)) { t4_end(); - fprintf(stderr, "End of page detected\n"); + if (!end_of_page_detected) + fprintf(stderr, "End of page detected\n"); + end_of_page_detected = TRUE; } } //printf("V.17 Rx bit %d - %d\n", rx_bits++, bit); @@ -417,7 +419,9 @@ static void v29_put_bit(void *user_data, int bit) if (t4_rx_put_bit(&t4_rx_state, bit)) { t4_end(); - fprintf(stderr, "End of page detected\n"); + if (!end_of_page_detected) + fprintf(stderr, "End of page detected\n"); + end_of_page_detected = TRUE; } } //printf("V.29 Rx bit %d - %d\n", rx_bits++, bit); @@ -453,7 +457,9 @@ static void v27ter_put_bit(void *user_data, int bit) if (t4_rx_put_bit(&t4_rx_state, bit)) { t4_end(); - fprintf(stderr, "End of page detected\n"); + if (!end_of_page_detected) + fprintf(stderr, "End of page detected\n"); + end_of_page_detected = TRUE; } } //printf("V.27ter Rx bit %d - %d\n", rx_bits++, bit); diff --git a/libs/spandsp/tests/line_model_monitor.cpp b/libs/spandsp/tests/line_model_monitor.cpp index d2c4f89bc9..8e57fe8a94 100644 --- a/libs/spandsp/tests/line_model_monitor.cpp +++ b/libs/spandsp/tests/line_model_monitor.cpp @@ -216,7 +216,7 @@ int line_model_monitor_line_spectrum_update(const int16_t amp[], int len) #endif } s->in_ptr = 0; -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) fftw_execute(s->p); #else fftw_one(s->p, s->in, s->out); @@ -227,7 +227,7 @@ int line_model_monitor_line_spectrum_update(const int16_t amp[], int len) for (i = 0; i < 512; i++) { s->spec_re_plot[2*i] = i*4000.0/512.0; -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i][0]*s->out[i][0] + s->out[i][1]*s->out[i][1])/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14; #else s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i].re*s->out[i].re + s->out[i].im*s->out[i].im)/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14; @@ -395,7 +395,7 @@ int start_line_model_monitor(int len) s->w->end(); s->w->show(); -#if defined(HAVE_FFTW3_H) +#if defined(HAVE_FFTW3_H) s->p = fftw_plan_dft_1d(1024, s->in, s->out, FFTW_BACKWARD, FFTW_ESTIMATE); for (i = 0; i < 1024; i++) { diff --git a/libs/tiff-4.0.2/tools/tiffgt.c b/libs/tiff-4.0.2/tools/tiffgt.c index de420396c6..4c8e50923f 100644 --- a/libs/tiff-4.0.2/tools/tiffgt.c +++ b/libs/tiff-4.0.2/tools/tiffgt.c @@ -31,11 +31,16 @@ #include #include -#if HAVE_APPLE_OPENGL_FRAMEWORK +#if HAVE_OPENGL_GL_H # include +#endif +#if HAVE_GLUT_GLUT_H # include -#else +#endif +#if HAVE_GL_GL_H # include +#endif +#if HAVE_GL_GLUT_H # include #endif diff --git a/scripts/ci/common.sh b/scripts/ci/common.sh index 059def200e..a1e97c6064 100755 --- a/scripts/ci/common.sh +++ b/scripts/ci/common.sh @@ -103,14 +103,16 @@ set_fs_ver () { -e "s|\(AC_SUBST(SWITCH_VERSION_MINOR, \[\).*\(\])\)|\1$minor\2|" \ -e "s|\(AC_SUBST(SWITCH_VERSION_MICRO, \[\).*\(\])\)|\1$micro\2|" \ -e "s|\(AC_INIT(\[freeswitch\], \[\).*\(\], BUG-REPORT-ADDRESS)\)|\1$ver\2|" \ - -i configure.in + configure.in > configure.in.$$ + mv configure.in.$$ configure.in if [ -n "$rev" ]; then [ -n "$hrev" ] || hrev="$rev" sed -e "s|\(AC_SUBST(SWITCH_VERSION_REVISION, \[\).*\(\])\)|\1$rev\2|" \ -e "s|\(AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, \[\).*\(\])\)|\1$hrev\2|" \ -e "s|#\(AC_SUBST(SWITCH_VERSION_REVISION\)|\1|" \ -e "s|#\(AC_SUBST(SWITCH_VERSION_REVISION_HUMAN\)|\1|" \ - -i configure.in + configure.in > configure.in.$$ + mv configure.in.$$ configure.in fi } diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 40f51ba61a..7bdf1e3dd0 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -285,6 +285,7 @@ struct switch_session_manager { int ready; int running; int busy; + int popping; }; extern struct switch_session_manager session_manager; diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index bddfb0f2d2..cd8cbb47f0 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -643,6 +643,8 @@ SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension( SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension); SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *channel); SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel); +SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel); +SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_core.h b/src/include/switch_core.h index ead85fdf4a..210b676b1e 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -722,6 +722,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_thread_pool_launch(switch_co /*! \brief Signal a session's state machine thread that a state change has occured */ +SWITCH_DECLARE(switch_mutex_t *) switch_core_session_get_mutex(switch_core_session_t *session); SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(_In_ switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_signal_state_change(_In_ switch_core_session_t *session); diff --git a/src/include/switch_pgsql.h b/src/include/switch_pgsql.h index 282172e646..ff4e83f11a 100644 --- a/src/include/switch_pgsql.h +++ b/src/include/switch_pgsql.h @@ -106,11 +106,20 @@ SWITCH_DECLARE(void) switch_pgsql_free_result(switch_pgsql_result_t **result); SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const char* file, const char *func, int line, switch_pgsql_handle_t *handle); #define switch_pgsql_finish_results(handle) switch_pgsql_finish_results_real(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle) -SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err); +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base_detailed(const char *file, const char *func, int line, + switch_pgsql_handle_t *handle, const char *sql, char **err); +#define switch_pgsql_handle_exec_base(handle, sql, err) switch_pgsql_handle_exec_base_detailed(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle, sql, err) SWITCH_DECLARE(switch_pgsql_state_t) switch_pgsql_handle_get_state(switch_pgsql_handle_t *handle); -SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec(switch_pgsql_handle_t *handle, const char *sql, char **err); -SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err); + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_detailed(const char *file, const char *func, int line, + switch_pgsql_handle_t *handle, const char *sql, char **err); +#define switch_pgsql_handle_exec(handle, sql, err) switch_pgsql_handle_exec_detailed(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle, sql, err) + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string_detailed(const char *file, const char *func, int line, + switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err); +#define switch_pgsql_handle_exec_string(handle, sql, resbuf, len, err) switch_pgsql_handle_exec_string_detailed(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle, sql, resbuf, len, err) + SWITCH_DECLARE(switch_bool_t) switch_pgsql_available(void); SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLSetAutoCommitAttr(switch_pgsql_handle_t *handle, switch_bool_t on); SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLEndTran(switch_pgsql_handle_t *handle, switch_bool_t commit); @@ -147,6 +156,8 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_callback_exec_detailed SWITCH_DECLARE(char *) switch_pgsql_handle_get_error(switch_pgsql_handle_t *handle); SWITCH_DECLARE(int) switch_pgsql_handle_affected_rows(switch_pgsql_handle_t *handle); +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_flush(switch_pgsql_handle_t *handle); + SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_types.h b/src/include/switch_types.h index d7d96b5aaf..15993c7993 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1255,6 +1255,7 @@ typedef enum { CF_NO_CDR, CF_EARLY_OK, CF_MEDIA_TRANS, + CF_HOLD_ON_BRIDGE, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 82893aef0d..2e20f3c969 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1389,9 +1389,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_time_t t_agent_answered = 0; switch_time_t t_member_called = atoi(h->member_joined_epoch); switch_event_t *event = NULL; - char agent_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - - switch_uuid_str(agent_uuid_str, sizeof(agent_uuid_str)); switch_mutex_lock(globals.mutex); globals.threads++; @@ -1421,7 +1418,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Type", h->agent_type); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid_str); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-Session-UUID", h->member_session_uuid); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-CID-Name", h->member_cid_name); @@ -1451,7 +1447,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout", "false"); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout_on_execute", "false"); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true"); - switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "origination_uuid", "%s", agent_uuid_str); switch_channel_process_export(member_channel, NULL, ovars, "cc_export_vars"); diff --git a/src/mod/applications/mod_cidlookup/mod_cidlookup.c b/src/mod/applications/mod_cidlookup/mod_cidlookup.c index 3844acb342..411ea376a1 100755 --- a/src/mod/applications/mod_cidlookup/mod_cidlookup.c +++ b/src/mod/applications/mod_cidlookup/mod_cidlookup.c @@ -695,6 +695,8 @@ SWITCH_STANDARD_APP(cidlookup_app_function) } if (cid && channel) { + switch_event_t *event; + switch_channel_set_variable(channel, "original_caller_id_name", switch_core_strdup(pool, profile->caller_id_name)); if (!zstr(cid->src)) { switch_channel_set_variable(channel, "cidlookup_source", cid->src); @@ -703,6 +705,19 @@ SWITCH_STANDARD_APP(cidlookup_app_function) switch_channel_set_variable(channel, "cidlookup_area", cid->area); } profile->caller_id_name = switch_core_strdup(profile->pool, cid->name);; + + + if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) { + const char *uuid = switch_channel_get_partner_uuid(channel); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "RECV"); + + if (uuid) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid); + } + switch_channel_event_set_data(channel, event); + switch_event_fire(&event); + } + } diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index eb9db51e25..78655106a1 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -2037,7 +2037,9 @@ SWITCH_STANDARD_API(status_function) duration.sec, duration.sec == 1 ? "" : "s", duration.ms , duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s", nl); - stream->write_function(stream, "FreeSWITCH is %s%s", switch_core_ready() ? "ready" : "not ready", nl); + stream->write_function(stream, "FreeSWITCH (Version %s) is %s%s", SWITCH_VERSION_FULL_HUMAN, + switch_core_ready() ? "ready" : "not ready", nl); + stream->write_function(stream, "%" SWITCH_SIZE_T_FMT " session(s) since startup%s", switch_core_session_id() - 1, nl); switch_core_session_ctl(SCSC_LAST_SPS, &last_sps); switch_core_session_ctl(SCSC_SPS, &sps); diff --git a/src/mod/applications/mod_db/mod_db.c b/src/mod/applications/mod_db/mod_db.c index fd077b14ff..9c1f9310d1 100644 --- a/src/mod/applications/mod_db/mod_db.c +++ b/src/mod/applications/mod_db/mod_db.c @@ -271,7 +271,7 @@ SWITCH_LIMIT_STATUS(limit_status_db) /* INIT / Config */ -static switch_xml_config_string_options_t limit_config_dsn = { NULL, 0, "^pgsql;|[^:]+:[^:]+:.+" }; +static switch_xml_config_string_options_t limit_config_dsn = { NULL, 0, "^pgsql|^odbc|^sqlite|[^:]+:[^:]+:.+" }; static switch_xml_config_item_t config_settings[] = { SWITCH_CONFIG_ITEM("odbc-dsn", SWITCH_CONFIG_STRING, 0, &globals.odbc_dsn, NULL, &limit_config_dsn, diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index b3ed2a7c1b..eefd4aad4b 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -3584,6 +3584,7 @@ static switch_call_cause_t pickup_outgoing_channel(switch_core_session_t *sessio pickup = outbound_profile->destination_number; + flags |= SOF_NO_LIMITS; if (!(nsession = switch_core_session_request(pickup_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n"); @@ -3921,7 +3922,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, if ((x_params = switch_xml_child(x_user, "params"))) { for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr(x_param, "name"); + const char *pvar = switch_xml_attr_soft(x_param, "name"); const char *val = switch_xml_attr(x_param, "value"); if (!strcasecmp(pvar, "dial-string")) { @@ -4813,10 +4814,6 @@ static switch_bool_t do_mutex(switch_core_session_t *session, const char *key, s struct read_frame_data rf = { 0 }; long to_val = 0; - if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { - return SWITCH_FALSE; - } - switch_mutex_lock(globals.mutex_mutex); used = switch_channel_test_app_flag_key(key, channel, MUTEX_FLAG_WAIT) || switch_channel_test_app_flag_key(key, channel, MUTEX_FLAG_SET); @@ -4876,19 +4873,12 @@ static switch_bool_t do_mutex(switch_core_session_t *session, const char *key, s switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s mutex %s is busy, waiting...\n", switch_channel_get_name(channel), key); - if (!(feedback = switch_channel_get_variable(channel, "mutex_feedback"))) { - if ((var = switch_channel_get_variable(channel, "ringback"))) { - feedback = switch_core_session_sprintf(session, "tone_stream://%s;loops=-1", var); - } else { - feedback = switch_channel_get_hold_music(channel); + if ((feedback = switch_channel_get_variable(channel, "mutex_feedback"))) { + if (!strcasecmp(feedback, "silence")) { + feedback = "silence_stream://-1"; } } - if (zstr(feedback) || !strcasecmp(feedback, "silence")) { - feedback = "silence_stream://-1"; - } - - if ((rf.exten = switch_channel_get_variable(channel, "mutex_orbit_exten"))) { to_val = 60; } @@ -4916,7 +4906,16 @@ static switch_bool_t do_mutex(switch_core_session_t *session, const char *key, s args.user_data = &rf; while(switch_channel_ready(channel) && switch_channel_test_app_flag_key(key, channel, MUTEX_FLAG_WAIT)) { - switch_status_t st = switch_ivr_play_file(session, NULL, feedback, &args); + switch_status_t st; + + if (feedback) { + switch_channel_pre_answer(channel); + st = switch_ivr_play_file(session, NULL, feedback, &args); + } else { + if ((st = switch_ivr_sleep(session, 20, SWITCH_FALSE, NULL)) == SWITCH_STATUS_SUCCESS) { + st = read_frame_callback(session, NULL, &rf); + } + } if (st != SWITCH_STATUS_SUCCESS) { break; @@ -5518,7 +5517,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "flush_dtmf", "flush any queued dtmf", "flush any queued dtmf", flush_dtmf_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "hold", "Send a hold message", "Send a hold message", hold_function, HOLD_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "unhold", "Send a un-hold message", "Send a un-hold message", unhold_function, UNHOLD_SYNTAX, SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "mutex", "block on a call flow only allowing one at a time", "", mutex_function, MUTEX_SYNTAX, SAF_NONE); + SWITCH_ADD_APP(app_interface, "mutex", "block on a call flow only allowing one at a time", "", mutex_function, MUTEX_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "page", "", "", page_function, PAGE_SYNTAX, SAF_NONE); SWITCH_ADD_APP(app_interface, "transfer", "Transfer a channel", TRANSFER_LONG_DESC, transfer_function, " [ ]", SAF_SUPPORT_NOMEDIA); diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c index 55841170a4..5e232d7ad6 100644 --- a/src/mod/applications/mod_lcr/mod_lcr.c +++ b/src/mod/applications/mod_lcr/mod_lcr.c @@ -1318,7 +1318,7 @@ static switch_call_cause_t lcr_outgoing_channel(switch_core_session_t *session, switch_event_t *event = NULL; const char *intrastate = NULL; const char *intralata = NULL; - switch_core_session_t *mysession = NULL; + switch_core_session_t *mysession = NULL, *locked_session = NULL; switch_channel_t *channel = NULL; dest = strdup(outbound_profile->destination_number); @@ -1362,7 +1362,7 @@ static switch_call_cause_t lcr_outgoing_channel(switch_core_session_t *session, } else if (var_event) { char *session_uuid = switch_event_get_header(var_event, "ent_originate_aleg_uuid"); if (session_uuid) { - mysession = switch_core_session_locate(session_uuid); + mysession = locked_session = switch_core_session_locate(session_uuid); } cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name"); cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number"); @@ -1464,8 +1464,8 @@ static switch_call_cause_t lcr_outgoing_channel(switch_core_session_t *session, if (event) { switch_event_destroy(&event); } - if (mysession) { - switch_core_session_rwunlock(mysession); + if (locked_session) { + switch_core_session_rwunlock(locked_session); } lcr_destroy(routes.head); switch_core_destroy_memory_pool(&pool); diff --git a/src/mod/applications/mod_sms/mod_sms.c b/src/mod/applications/mod_sms/mod_sms.c index 34b2971333..15d0de6233 100644 --- a/src/mod/applications/mod_sms/mod_sms.c +++ b/src/mod/applications/mod_sms/mod_sms.c @@ -50,6 +50,9 @@ static void event_handler(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Delivery Failure\n"); DUMP_EVENT(event); + return; + } else if ( check_failure && switch_false(check_failure) ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SMS Delivery Success\n"); return; } @@ -392,7 +395,7 @@ static switch_event_t *chatplan_hunt(switch_event_t *event) static switch_status_t chat_send(switch_event_t *message_event) { - switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_status_t status = SWITCH_STATUS_BREAK; switch_event_t *exten; int forwards = 0; const char *var; @@ -425,19 +428,30 @@ static switch_status_t chat_send(switch_event_t *message_event) for (hp = exten->headers; hp; hp = hp->next) { status = switch_core_execute_chat_app(message_event, hp->name, hp->value); if (!SWITCH_READ_ACCEPTABLE(status)) { + status = SWITCH_STATUS_SUCCESS; break; } } switch_event_destroy(&exten); - status = SWITCH_STATUS_BREAK; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SMS chatplan no actions found\n"); } - return status; } +SWITCH_STANDARD_CHAT_APP(system_function) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Executing command: %s\n", data); + if (switch_system(data, SWITCH_TRUE) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Failed to execute command: %s\n", data); + return SWITCH_STATUS_FALSE; + } + return SWITCH_STATUS_SUCCESS; +} + SWITCH_STANDARD_CHAT_APP(stop_function) { switch_set_flag(message, EF_NO_CHAT_EXEC); @@ -531,6 +545,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sms_load) SWITCH_ADD_CHAT_APP(chat_app_interface, "set", "set a variable", "set a variable", set_function, "", SCAF_NONE); SWITCH_ADD_CHAT_APP(chat_app_interface, "send", "send the message as-is", "send the message as-is", send_function, "", SCAF_NONE); SWITCH_ADD_CHAT_APP(chat_app_interface, "fire", "fire the message", "fire the message", fire_function, "", SCAF_NONE); + SWITCH_ADD_CHAT_APP(chat_app_interface, "system", "execute a system command", "execute a sytem command", system_function, "", SCAF_NONE); /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index f8f233aa87..24a0e497a9 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -2650,6 +2650,45 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } +static switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + mdl_profile_t *profile = NULL; + switch_hash_index_t *hi; + void *val; + const void *vvar; + switch_console_callback_match_t *my_matches = NULL; + switch_status_t status = SWITCH_STATUS_FALSE; + + for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &vvar, NULL, &val); + profile = (mdl_profile_t *) val; + if (!strncmp("dl_logout", line, 9)) { + if (profile->handle) { + switch_console_push_match(&my_matches, profile->name); + } + } else if (!strncmp("dl_login", line, 8)) { + if (!switch_test_flag(profile, TFLAG_IO)) { + char *profile_name = switch_mprintf("profile=%s", profile->name); + switch_console_push_match(&my_matches, profile_name); + free(profile_name); + } + } else if (!strncmp("dl_pres", line, 7)) { + if (profile->user_flags & LDL_FLAG_COMPONENT) { + switch_console_push_match(&my_matches, profile->name); + } + } else { + switch_console_push_match(&my_matches, profile->name); + } + } + + if (my_matches) { + *matches = my_matches; + status = SWITCH_STATUS_SUCCESS; + } + + return status; +} + SWITCH_MODULE_LOAD_FUNCTION(mod_dingaling_load) { switch_chat_interface_t *chat_interface; @@ -2726,6 +2765,15 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dingaling_load) SWITCH_ADD_API(api_interface, "dingaling", "DingaLing Menu", dingaling, DINGALING_SYNTAX); SWITCH_ADD_CHAT(chat_interface, MDL_CHAT_PROTO, chat_send); + switch_console_set_complete("add dl_debug ::[true:false"); + switch_console_set_complete("add dl_pres ::dingaling::list_profiles"); + switch_console_set_complete("add dl_logout ::dingaling::list_profiles"); + switch_console_set_complete("add dl_login ::dingaling::list_profiles"); + switch_console_set_complete("add dl_login login="); + switch_console_set_complete("add dingaling status"); + switch_console_set_complete("add dingaling reload"); + switch_console_add_complete_func("::dingaling::list_profiles", list_profiles); + /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } @@ -3042,7 +3090,7 @@ SWITCH_STANDARD_API(dingaling) SWITCH_STANDARD_API(dl_login) { - char *argv[10] = { 0 }; + char *argv[20] = { 0 }; int argc = 0; char *var, *val, *myarg = NULL; mdl_profile_t *profile = NULL; @@ -3064,12 +3112,6 @@ SWITCH_STANDARD_API(dl_login) argc = switch_separate_string(myarg, ';', argv, (sizeof(argv) / sizeof(argv[0]))); - if (zstr(cmd) || argc != 1) { - stream->write_function(stream, "USAGE: %s\n", LOGIN_SYNTAX); - status = SWITCH_STATUS_SUCCESS; - goto done; - } - if (argv[0] && !strncasecmp(argv[0], "profile=", 8)) { char *profile_name = argv[0] + 8; profile = switch_core_hash_find(globals.profile_hash, profile_name); diff --git a/src/mod/endpoints/mod_gsmopen/FREEBSD_README.txt b/src/mod/endpoints/mod_gsmopen/FREEBSD_README.txt new file mode 100644 index 0000000000..4cbedeae63 --- /dev/null +++ b/src/mod/endpoints/mod_gsmopen/FREEBSD_README.txt @@ -0,0 +1,9 @@ +This patch (updated to be applied today) was sent via Jira by royj@yandex.ru, with Jira issue FS-4338. + +Apply in this way: +# patch -p6 < FREEBSD_patch.diff + +I have not tested it, but it works for him. +Please open another Jira issue if anything wrong. + +-giovanni diff --git a/src/mod/endpoints/mod_gsmopen/FREEBSD_patch.diff b/src/mod/endpoints/mod_gsmopen/FREEBSD_patch.diff new file mode 100644 index 0000000000..cd5613a2d7 --- /dev/null +++ b/src/mod/endpoints/mod_gsmopen/FREEBSD_patch.diff @@ -0,0 +1,171 @@ +diff --git a/src/mod/endpoints/mod_gsmopen/Makefile b/src/mod/endpoints/mod_gsmopen/Makefile +index 18943c8..5324c52 100644 +--- a/src/mod/endpoints/mod_gsmopen/Makefile ++++ b/src/mod/endpoints/mod_gsmopen/Makefile +@@ -1,5 +1,5 @@ + MODNAME=mod_gsmopen +-LOCAL_CFLAGS += -I../../../../libs/spandsp/src -I../../../..//libs/tiff-4.0.2/libtiff -DGSMOPEN_C_VER=\"`git log -1 --format="%h" gsmopen_protocol.cpp`\" -DMODGSMOPEN_C_VER=\"`git log -1 --format="%h" mod_gsmopen.cpp`\" ++LOCAL_CFLAGS += -I/usr/local/include -I../../../../libs/spandsp/src -I../../../..//libs/tiff-4.0.2/libtiff -DGSMOPEN_C_VER=\"`git log -1 --format="%h" gsmopen_protocol.cpp`\" -DMODGSMOPEN_C_VER=\"`git log -1 --format="%h" mod_gsmopen.cpp`\" + LOCAL_LDFLAGS=-L../../../../libs/spandsp/src -lspandsp -lctb-0.16 -lgsmme + LOCAL_OBJS=gsmopen_protocol.o + include ../../../../build/modmake.rules +diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +index 5bdda08..73ef93d 100644 +--- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp ++++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +@@ -2356,7 +2356,7 @@ int ucs2_to_utf8(private_t *tech_pvt, char *ucs2_in, char *utf8_out, size_t outb + iconv_t iconv_format; + int iconv_res; + char *outbuf; +- char *inbuf; ++ //char *inbuf; + size_t inbytesleft; + int c; + char stringa[5]; +@@ -2376,9 +2376,10 @@ int ucs2_to_utf8(private_t *tech_pvt, char *ucs2_in, char *utf8_out, size_t outb + } + + outbuf = utf8_out; +- inbuf = converted; ++ const char *inbuf = converted; + +- iconv_format = iconv_open("UTF8", "UCS-2BE"); ++ //iconv_format = iconv_open("UTF8", "UCS-2BE"); ++ iconv_format = iconv_open("UTF-8", "UCS-2BE"); + //iconv_format = iconv_open("UTF8", "UCS2"); + if (iconv_format == (iconv_t) -1) { + ERRORA("error: %s\n", GSMOPEN_P_LOG, strerror(errno)); +@@ -2417,12 +2418,12 @@ int utf8_to_iso_8859_1(private_t *tech_pvt, char *utf8_in, size_t inbytesleft, c + iconv_t iconv_format; + int iconv_res; + char *outbuf; +- char *inbuf; ++ //char *inbuf; + + outbuf = iso_8859_1_out; +- inbuf = utf8_in; ++ const char *inbuf = utf8_in; + +- iconv_format = iconv_open("ISO_8859-1", "UTF8"); ++ iconv_format = iconv_open("ISO_8859-1", "UTF-8"); + if (iconv_format == (iconv_t) -1) { + ERRORA("error: %s\n", GSMOPEN_P_LOG, strerror(errno)); + return -1; +@@ -2467,7 +2468,7 @@ int iso_8859_1_to_utf8(private_t *tech_pvt, char *iso_8859_1_in, char *utf8_out, + iconv_t iconv_format; + int iconv_res; + char *outbuf; +- char *inbuf; ++ //char *inbuf; + size_t inbytesleft; + //int c; + //char stringa[5]; +@@ -2477,9 +2478,9 @@ int iso_8859_1_to_utf8(private_t *tech_pvt, char *iso_8859_1_in, char *utf8_out, + DEBUGA_GSMOPEN("iso_8859_1_in=%s\n", GSMOPEN_P_LOG, iso_8859_1_in); + + outbuf = utf8_out; +- inbuf = iso_8859_1_in; ++ const char *inbuf = iso_8859_1_in; + +- iconv_format = iconv_open("UTF8", "ISO_8859-1"); ++ iconv_format = iconv_open("UTF-8", "ISO_8859-1"); + if (iconv_format == (iconv_t) -1) { + ERRORA("error: %s\n", GSMOPEN_P_LOG, strerror(errno)); + return -1; +@@ -2514,7 +2515,7 @@ int utf8_to_ucs2(private_t *tech_pvt, char *utf8_in, size_t inbytesleft, char *u + iconv_t iconv_format; + int iconv_res; + char *outbuf; +- char *inbuf; ++ //char *inbuf; + char converted[16000]; + int i; + char stringa[16]; +@@ -2523,9 +2524,9 @@ int utf8_to_ucs2(private_t *tech_pvt, char *utf8_in, size_t inbytesleft, char *u + memset(converted, '\0', sizeof(converted)); + + outbuf = converted; +- inbuf = utf8_in; ++ const char *inbuf = utf8_in; + +- iconv_format = iconv_open("UCS-2BE", "UTF8"); ++ iconv_format = iconv_open("UCS-2BE", "UTF-8"); + if (iconv_format == (iconv_t) -1) { + ERRORA("error: %s\n", GSMOPEN_P_LOG, strerror(errno)); + return -1; +diff --git a/src/mod/endpoints/mod_gsmopen/libctb-0.16/include/ctb-0.16/linux/serport.h b/src/mod/endpoints/mod_gsmopen/libctb-0.16/include/ctb-0.16/linux/serport.h +index d88528b..f8851cc 100644 +--- a/src/mod/endpoints/mod_gsmopen/libctb-0.16/include/ctb-0.16/linux/serport.h ++++ b/src/mod/endpoints/mod_gsmopen/libctb-0.16/include/ctb-0.16/linux/serport.h +@@ -10,7 +10,7 @@ + ///////////////////////////////////////////////////////////////////////////// + + #include "ctb-0.16/serportx.h" +-#include ++//#include + #include + + namespace ctb { +@@ -40,7 +40,7 @@ namespace ctb { + need the errors during a active connection, we must save the actual + error numbers in this separate structurs. + */ +- struct serial_icounter_struct save_info, last_info; ++ //struct serial_icounter_struct save_info, last_info; + + /*! + \brief adaptor member function, to convert the plattform independent +diff --git a/src/mod/endpoints/mod_gsmopen/libctb-0.16/src/linux/serport.cpp b/src/mod/endpoints/mod_gsmopen/libctb-0.16/src/linux/serport.cpp +index a369abc..d190567 100644 +--- a/src/mod/endpoints/mod_gsmopen/libctb-0.16/src/linux/serport.cpp ++++ b/src/mod/endpoints/mod_gsmopen/libctb-0.16/src/linux/serport.cpp +@@ -136,7 +136,7 @@ namespace ctb { + // + int SerialPort::Ioctl(int cmd, void* args) + { +- int count = 0; ++ /* int count = 0; + int err = 0; + struct serial_icounter_struct info; + SerialPort_EINFO einfo; +@@ -184,7 +184,8 @@ namespace ctb { + return -1; + } + last_info = info; +- return 0; ++ return 0;*/ ++ return -1; + }; + + int SerialPort::IsOpen() +@@ -292,9 +293,9 @@ namespace ctb { + // request the actual numbers of breaks, framing, overrun + // and parity errors (because Linux summing all of them during + // system lifetime, not only while serial port is open. +- ioctl(fd,TIOCGICOUNT,&save_info); ++ //ioctl(fd,TIOCGICOUNT,&save_info); + // it's also careless, but we assume, that there was no error +- last_info = save_info; ++ //last_info = save_info; + + // in case of a non-standard rate, the termios struct have to set + // with the B38400 rate, see above! +@@ -359,7 +360,7 @@ namespace ctb { + + int SerialPort::SetBaudrateAny( int baudrate ) + { +- struct serial_struct ser_info; ++ /* struct serial_struct ser_info; + + int result = ioctl( fd, TIOCGSERIAL, &ser_info ); + +@@ -369,7 +370,8 @@ namespace ctb { + + result = ioctl( fd, TIOCSSERIAL, &ser_info ); + +- return result; ++ return result;*/ ++ return -1; + } + + int SerialPort::SetBaudrateStandard( int baudrate ) diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen.h b/src/mod/endpoints/mod_gsmopen/gsmopen.h index b5404ae6a9..af17a9f416 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen.h +++ b/src/mod/endpoints/mod_gsmopen/gsmopen.h @@ -331,7 +331,7 @@ struct private_object { unsigned long ib_failed_calls; unsigned long ob_failed_calls; - char controldevice_name[50]; /*!< \brief name of the serial device controlling the interface, possibly none */ + char controldevice_name[512]; /*!< \brief name of the serial device controlling the interface, possibly none */ int controldevprotocol; /*!< \brief which protocol is used for serial control of this interface */ char controldevprotocolname[50]; /*!< \brief name of the serial device controlling protocol, one of "at" "fbus2" "no_serial" "alsa_voicemodem" */ int controldevfd; /*!< \brief serial controlling file descriptor for this interface */ @@ -469,7 +469,7 @@ struct private_object { int network_creg_not_supported; char creg[128]; - char controldevice_audio_name[50]; + char controldevice_audio_name[512]; int controldev_audio_fd; int controldevice_audio_speed; int controldev_audio_dead; diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp index 5bdda08f81..81d1192307 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp @@ -2189,7 +2189,7 @@ int gsmopen_serial_write_AT_expect1(private_t *tech_pvt, const char *data, const return -1; } - at_result = gsmopen_serial_read_AT(tech_pvt, 1, 100000, seconds, expected_string, expect_crlf); // minimum 1/10th sec timeout + at_result = gsmopen_serial_read_AT(tech_pvt, 1, 500000, seconds, expected_string, expect_crlf); // minimum half a sec timeout UNLOCKA(tech_pvt->controldev_lock); POPPA_UNLOCKA(tech_pvt->controldev_lock); @@ -2700,6 +2700,8 @@ int gsmopen_hangup(private_t *tech_pvt) int gsmopen_call(private_t *tech_pvt, char *rdest, int timeout) { + int result; + //gsmopen_sleep(5000); DEBUGA_GSMOPEN("Calling GSM, rdest is: %s\n", GSMOPEN_P_LOG, rdest); //gsmopen_signaling_write(tech_pvt, "SET AGC OFF"); @@ -2707,11 +2709,11 @@ int gsmopen_call(private_t *tech_pvt, char *rdest, int timeout) //gsmopen_signaling_write(tech_pvt, "SET AEC OFF"); //gsmopen_sleep(10000); - gsmopen_serial_call(tech_pvt, rdest); + result=gsmopen_serial_call(tech_pvt, rdest); //ERRORA("failed to communicate with GSM client, now exit\n", GSMOPEN_P_LOG); //return -1; //} - return 0; + return result; } int gsmopen_senddigit(private_t *tech_pvt, char digit) diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.2010.vcxproj b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.2010.vcxproj index b2895a73d5..2429ca905f 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.2010.vcxproj +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.2010.vcxproj @@ -160,6 +160,9 @@ rpcrt4.lib "..\..\..\..\debug\libtiff.lib" "..\..\..\..\libs\spandsp\src\debug\ + + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} + {26c82fce-e0cf-4d10-a00c-d8e582ffeb53} diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index 62f5cdd20f..1474f77908 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -1054,7 +1054,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_call_cause_t *cancel_cause) { private_t *tech_pvt = NULL; - if ((*new_session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) { + int result; + + if ((*new_session = switch_core_session_request_uuid(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool, switch_event_get_header(var_event, "origination_uuid"))) != 0) { + switch_channel_t *channel = NULL; switch_caller_profile_t *caller_profile; char *rdest; @@ -1171,8 +1174,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_mutex_unlock(tech_pvt->flag_mutex); switch_channel_set_state(channel, CS_INIT); - gsmopen_call(tech_pvt, rdest, 30); + result=gsmopen_call(tech_pvt, rdest, 30); switch_mutex_unlock(globals.mutex); + if(result != 0){ + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } return SWITCH_CAUSE_SUCCESS; } @@ -1217,6 +1223,14 @@ static switch_status_t load_config(int reload_type) } switch_mutex_lock(globals.mutex); + + set_global_dialplan("XML"); + DEBUGA_GSMOPEN("Default globals.dialplan=%s\n", GSMOPEN_P_LOG, globals.dialplan); + set_global_destination("5000"); + DEBUGA_GSMOPEN("Default globals.destination=%s\n", GSMOPEN_P_LOG, globals.destination); + set_global_context("default"); + DEBUGA_GSMOPEN("Default globals.context=%s\n", GSMOPEN_P_LOG, globals.context); + if ((global_settings = switch_xml_child(cfg, "global_settings"))) { for (param = switch_xml_child(global_settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); @@ -1250,16 +1264,16 @@ static switch_status_t load_config(int reload_type) for (myinterface = switch_xml_child(interfaces, "interface"); myinterface; myinterface = myinterface->next) { char *id = (char *) switch_xml_attr(myinterface, "id"); char *name = (char *) switch_xml_attr(myinterface, "name"); - const char *context = "default"; - const char *dialplan = "XML"; - const char *destination = "5000"; + const char *context = globals.context; + const char *dialplan = globals.dialplan; + const char *destination = globals.destination; const char *controldevice_name = "/dev/ttyUSB3"; const char *controldevice_audio_name = "/dev/ttyUSB2"; char *digit_timeout = NULL; char *max_digits = NULL; char *hotline = NULL; char *dial_regex = NULL; - char *hold_music = NULL; + char *hold_music = globals.hold_music; char *fail_dial_regex = NULL; const char *enable_callerid = "true"; diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c index e711622d34..bc2c1a61e9 100644 --- a/src/mod/endpoints/mod_loopback/mod_loopback.c +++ b/src/mod/endpoints/mod_loopback/mod_loopback.c @@ -709,10 +709,26 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch return status; } +static void switch_channel_wait_for_state_or_greater(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state) +{ + + switch_assert(channel); + + for (;;) { + if ((switch_channel_get_state(channel) < CS_HANGUP && + switch_channel_get_state(channel) == switch_channel_get_running_state(channel) && switch_channel_get_running_state(channel) >= want_state) || + (other_channel && switch_channel_down_nosig(other_channel)) || switch_channel_down(channel)) { + break; + } + switch_cond_next(); + } +} + + static switch_status_t find_non_loopback_bridge(switch_core_session_t *session, switch_core_session_t **br_session, const char **br_uuid) { switch_channel_t *channel = switch_core_session_get_channel(session); - const char *a_uuid; + const char *a_uuid = NULL; switch_core_session_t *sp; *br_session = NULL; @@ -722,9 +738,17 @@ static switch_status_t find_non_loopback_bridge(switch_core_session_t *session, while (a_uuid && (sp = switch_core_session_locate(a_uuid))) { if (switch_core_session_check_interface(sp, loopback_endpoint_interface)) { - private_t *tech_pvt = switch_core_session_get_private(sp); + private_t *tech_pvt; + switch_channel_t *spchan = switch_core_session_get_channel(sp); + + switch_channel_wait_for_state_or_greater(spchan, channel, CS_ROUTING); + + tech_pvt = switch_core_session_get_private(sp); + + if (tech_pvt->other_channel) { + a_uuid = switch_channel_get_partner_uuid(tech_pvt->other_channel); + } - a_uuid = switch_channel_get_partner_uuid(tech_pvt->other_channel); switch_core_session_rwunlock(sp); sp = NULL; } else { @@ -783,9 +807,10 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc switch_channel_t *ch_a = NULL, *ch_b = NULL; int good_to_go = 0; + switch_mutex_unlock(tech_pvt->mutex); find_non_loopback_bridge(session, &br_a, &a_uuid); find_non_loopback_bridge(tech_pvt->other_session, &br_b, &b_uuid); - + switch_mutex_lock(tech_pvt->mutex); if (br_a) { diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index c3b5d81681..455e18b1cd 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -191,7 +191,7 @@ static switch_status_t interface_exists(char *the_interface); static switch_status_t channel_on_init(switch_core_session_t *session); static switch_status_t channel_on_hangup(switch_core_session_t *session); -static switch_status_t channel_on_reset(switch_core_session_t *session); +//static switch_status_t channel_on_reset(switch_core_session_t *session); static switch_status_t channel_on_destroy(switch_core_session_t *session); static switch_status_t channel_on_routing(switch_core_session_t *session); static switch_status_t channel_on_exchange_media(switch_core_session_t *session); @@ -645,7 +645,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) } //DEBUGA_SKYPE("debugging_hangup 12\n", SKYPOPEN_P_LOG); - switch_channel_set_state(channel, CS_DESTROY); + //switch_channel_set_state(channel, CS_DESTROY); return SWITCH_STATUS_SUCCESS; } @@ -766,6 +766,7 @@ static switch_status_t channel_on_soft_execute(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } +#if 0 static switch_status_t channel_on_reset(switch_core_session_t *session) { private_t *tech_pvt = NULL; @@ -788,6 +789,7 @@ static switch_status_t channel_on_reset(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } +#endif //0 static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) @@ -1238,7 +1240,7 @@ switch_state_handler_table_t skypopen_state_handlers = { /*.on_soft_execute */ channel_on_soft_execute, /*.on_consume_media */ channel_on_consume_media, /*.on_hibernate */ NULL, - /*.on_reset */ channel_on_reset, + /*.on_reset */ NULL, /*.on_park */ NULL, /*.on_reporting */ NULL, /*.on_destroy */ channel_on_destroy @@ -2729,6 +2731,8 @@ int skypopen_partner_handle_ring(private_t *tech_pvt) if (tech_pvt && tech_pvt->ringing_state == SKYPOPEN_RINGING_INIT) { /* we are not inside an active call */ + switch_channel_t *channel = NULL; + tech_pvt->interface_state = SKYPOPEN_STATE_PRERING; gettimeofday(&tech_pvt->ring_time, NULL); switch_copy_string(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1); @@ -2741,6 +2745,22 @@ int skypopen_partner_handle_ring(private_t *tech_pvt) new_inbound_channel(tech_pvt); + switch_sleep(10000); + + session = switch_core_session_locate(tech_pvt->session_uuid_str); + if (session) { + channel = switch_core_session_get_channel(session); + switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING); + if (channel) { + switch_channel_mark_ring_ready(channel); + DEBUGA_SKYPE("switch_channel_mark_ring_ready(channel);\n", SKYPOPEN_P_LOG); + } else { + ERRORA("no channel\n", SKYPOPEN_P_LOG); + } + switch_core_session_rwunlock(session); + } else { + ERRORA("no session\n", SKYPOPEN_P_LOG); + } } else if (!tech_pvt || !tech_pvt->skype_call_id) { ERRORA("No Call ID?\n", SKYPOPEN_P_LOG); } else { diff --git a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c index 2126955452..84d4cb81ef 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c +++ b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c @@ -522,7 +522,15 @@ int skypopen_signaling_read(private_t *tech_pvt) sprintf(msg_to_skype, "SET CHATMESSAGE %s SEEN", id); skypopen_signaling_write(tech_pvt, msg_to_skype); + } else { + DEBUGA_SKYPE + ("CHATMESSAGE %s is in position %d in the chatmessages array, type=%s, id=%s, chatname=%s, from_handle=%s, from_dispname=%s, body=%s NOT DELETED\n", + SKYPOPEN_P_LOG, id, i, tech_pvt->chatmessages[i].type, tech_pvt->chatmessages[i].id, tech_pvt->chatmessages[i].chatname, + tech_pvt->chatmessages[i].from_handle, tech_pvt->chatmessages[i].from_dispname, tech_pvt->chatmessages[i].body); + memset(&tech_pvt->chatmessages[i], '\0', sizeof(&tech_pvt->chatmessages[i])); + DEBUGA_SKYPE("chatmessage %s HAS BEEN DELETED\n", SKYPOPEN_P_LOG, id); } + } } @@ -631,6 +639,53 @@ int skypopen_signaling_read(private_t *tech_pvt) //skypopen_sleep(10000); } + + if (!strcasecmp(prop, "VM_DURATION") && (!strcasecmp(value, "0"))) { + char msg_to_skype[1024]; + + NOTICA("We called a Skype contact and he started Skype voicemail on our skype_call: %s.\n", SKYPOPEN_P_LOG, id); + + if (!strlen(tech_pvt->session_uuid_str)) { + DEBUGA_SKYPE("no tech_pvt->session_uuid_str\n", SKYPOPEN_P_LOG); + } + if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) { + if (!strlen(tech_pvt->session_uuid_str) || !strlen(tech_pvt->skype_call_id) + || !strcasecmp(tech_pvt->skype_call_id, id)) { + skypopen_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPOPEN_P_LOG, id); + + if (tech_pvt->skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) { + tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; + tech_pvt->interface_state = SKYPOPEN_STATE_UP; + + if (tech_pvt->tcp_cli_thread == NULL) { + DEBUGA_SKYPE("START start_audio_threads\n", SKYPOPEN_P_LOG); + if (start_audio_threads(tech_pvt)) { + WARNINGA("start_audio_threads FAILED\n", SKYPOPEN_P_LOG); + return CALLFLOW_INCOMING_HANGUP; + } + } + //skypopen_sleep(1000); + sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port); + skypopen_signaling_write(tech_pvt, msg_to_skype); + //skypopen_sleep(1000); + sprintf(msg_to_skype, "#output ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, tech_pvt->tcp_srv_port); + skypopen_signaling_write(tech_pvt, msg_to_skype); + } + tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; + if (skypopen_answered(tech_pvt) != SWITCH_STATUS_SUCCESS) { + sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id); + skypopen_signaling_write(tech_pvt, msg_to_skype); + } + } else { + DEBUGA_SKYPE("I'm on %s, skype_call %s is NOT MY call, ignoring\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, id); + } + } else { + tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; + DEBUGA_SKYPE("Back from REMOTEHOLD!\n", SKYPOPEN_P_LOG); + } + } + if (!strcasecmp(prop, "STATUS")) { if (!strcasecmp(value, "RINGING")) { @@ -833,6 +888,8 @@ int skypopen_signaling_read(private_t *tech_pvt) tech_pvt->skype_call_id[0] = '\0'; //skypopen_sleep(1000); return CALLFLOW_INCOMING_HANGUP; + } else if (!strncmp(value, "VM_", 2)) { + DEBUGA_SKYPE ("Our skype_call %s is in Skype voicemail: %s\n", SKYPOPEN_P_LOG, id, value); } else { WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPOPEN_P_LOG, id, value); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index c11d37c42f..deedea0802 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -262,12 +262,14 @@ char *generate_pai_str(private_object_t *tech_pvt) return NULL; } - if (zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_name"))) && + if (zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "initial_callee_id_name"))) && + zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_name"))) && zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_name")))) { callee_name = switch_channel_get_variable(tech_pvt->channel, "callee_id_name"); } - if (zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_number"))) && + if (zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "initial_callee_id_number"))) && + zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_number"))) && zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_number"))) && zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "callee_id_number")))) { @@ -2024,10 +2026,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi nua_ack(tech_pvt->nh, TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), - SOATAG_USER_SDP_STR(msg->string_arg), - SOATAG_REUSE_REJECTED(1), - SOATAG_RTP_SELECT(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), - TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)), + SIPTAG_PAYLOAD_STR(msg->string_arg), + SIPTAG_CONTENT_TYPE_STR("application/sdp"), TAG_END()); sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE); @@ -2456,25 +2456,31 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi case SWITCH_MESSAGE_INDICATE_HOLD: { - sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD); - switch_channel_set_flag(channel, CF_LEG_HOLDING); - sofia_glue_do_invite(session); - if (!zstr(msg->string_arg)) { - char message[256] = ""; - const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent"); - if (ua && switch_stristr("snom", ua)) { - snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", msg->string_arg, tech_pvt->caller_profile->destination_number); - nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), - TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END()); - } else if (ua && switch_stristr("polycom", ua)) { - snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", msg->string_arg, tech_pvt->caller_profile->destination_number); - nua_update(tech_pvt->nh, - NUTAG_SESSION_TIMER(tech_pvt->session_timeout), - NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher), - TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)), - TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)), - TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END()); + if (msg->numeric_arg) { + sofia_glue_toggle_hold(tech_pvt, 1); + } else { + + sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD); + switch_channel_set_flag(channel, CF_LEG_HOLDING); + sofia_glue_do_invite(session); + if (!zstr(msg->string_arg)) { + char message[256] = ""; + const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent"); + + if (ua && switch_stristr("snom", ua)) { + snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", msg->string_arg, tech_pvt->caller_profile->destination_number); + nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END()); + } else if (ua && switch_stristr("polycom", ua)) { + snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", msg->string_arg, tech_pvt->caller_profile->destination_number); + nua_update(tech_pvt->nh, + NUTAG_SESSION_TIMER(tech_pvt->session_timeout), + NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher), + TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)), + TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END()); + } } } } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 864d3a1e6f..5240553caa 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -389,6 +389,7 @@ struct mod_sofia_globals { int tracelevel; char *capture_server; int rewrite_multicasted_fs_path; + int presence_flush; }; extern struct mod_sofia_globals mod_sofia_globals; @@ -694,6 +695,7 @@ struct sofia_profile { int ireg_seconds; sofia_paid_type_t paid_type; uint32_t rtp_digit_delay; + switch_queue_t *event_queue; }; struct private_object { @@ -1013,6 +1015,7 @@ void sofia_glue_execute_sql(sofia_profile_t *profile, char **sqlp, switch_bool_t void sofia_glue_actually_execute_sql(sofia_profile_t *profile, char *sql, switch_mutex_t *mutex); void sofia_glue_actually_execute_sql_trans(sofia_profile_t *profile, char *sql, switch_mutex_t *mutex); void sofia_glue_execute_sql_now(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic); +void sofia_glue_execute_sql_soon(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic); void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot); void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now); void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now); @@ -1206,6 +1209,8 @@ int sofia_recover_callback(switch_core_session_t *session); void sofia_glue_set_name(private_object_t *tech_pvt, const char *channame); private_object_t *sofia_glue_new_pvt(switch_core_session_t *session); switch_status_t sofia_init(void); +void sofia_glue_fire_events(sofia_profile_t *profile); +void sofia_event_fire(sofia_profile_t *profile, switch_event_t **event); /* For Emacs: * Local Variables: diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index ebc8f2aa6b..b4d3e894a3 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1502,6 +1502,10 @@ static void our_sofia_event_callback(nua_event_t event, nua_handle_bind(nh, NULL); } + if (tech_pvt && (tech_pvt->nh == nh)) { + tech_pvt->nh = NULL; + } + nua_handle_destroy(nh); nh = NULL; } @@ -1555,7 +1559,7 @@ void sofia_process_dispatch_event_in_thread(sofia_dispatch_event_t **dep) { sofia_dispatch_event_t *de = *dep; switch_memory_pool_t *pool; - sofia_profile_t *profile = (*dep)->profile; + //sofia_profile_t *profile = (*dep)->profile; switch_thread_data_t *td; switch_core_new_memory_pool(&pool); @@ -1567,45 +1571,10 @@ void sofia_process_dispatch_event_in_thread(sofia_dispatch_event_t **dep) td->func = sofia_msg_thread_run_once; td->obj = de; - switch_mutex_lock(profile->ireg_mutex); switch_thread_pool_launch_thread(&td); - switch_mutex_unlock(profile->ireg_mutex); + } -#if 0 -void sofia_process_dispatch_event_in_thread(sofia_dispatch_event_t **dep) -{ - sofia_dispatch_event_t *de = *dep; - switch_threadattr_t *thd_attr = NULL; - switch_memory_pool_t *pool; - switch_thread_t *thread; - sofia_profile_t *profile = (*dep)->profile; - switch_status_t status; - - switch_core_new_memory_pool(&pool); - - - *dep = NULL; - de->pool = pool; - - switch_mutex_lock(profile->ireg_mutex); - switch_threadattr_create(&thd_attr, de->pool); - switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - status = switch_thread_create(&thread, - thd_attr, - sofia_msg_thread_run_once, - de, - de->pool); - switch_mutex_unlock(profile->ireg_mutex); - - if (status != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot create threads!\n"); - sofia_process_dispatch_event(&de); - } -} -#endif - void sofia_process_dispatch_event(sofia_dispatch_event_t **dep) { sofia_dispatch_event_t *de = *dep; @@ -1988,6 +1957,7 @@ void sofia_event_callback(nua_event_t event, sofia_queue_message(de); end: + //switch_cond_next(); return; } @@ -2129,7 +2099,7 @@ void event_handler(switch_event_t *event) contact_str = fixed_contact_str; } - switch_mutex_lock(profile->ireg_mutex); + sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET); @@ -2146,7 +2116,7 @@ void event_handler(switch_event_t *event) sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Propagating registration for %s@%s->%s\n", from_user, from_host, contact_str); } - switch_mutex_unlock(profile->ireg_mutex); + if (profile) { sofia_glue_release_profile(profile); @@ -2489,6 +2459,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void #ifdef MANUAL_BYE NUTAG_APPL_METHOD("BYE"), #endif + NUTAG_APPL_METHOD("MESSAGE"), NUTAG_SESSION_TIMER(profile->session_timeout), NTATAG_MAX_PROCEEDING(profile->max_proceeding), @@ -2553,11 +2524,13 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void switch_mutex_init(&profile->ireg_mutex, SWITCH_MUTEX_NESTED, profile->pool); switch_mutex_init(&profile->gateway_mutex, SWITCH_MUTEX_NESTED, profile->pool); + switch_queue_create(&profile->event_queue, SOFIA_QUEUE_SIZE, profile->pool); + switch_snprintf(qname, sizeof(qname), "sofia:%s", profile->name); switch_sql_queue_manager_init_name(qname, &profile->qm, - 1, + 2, profile->odbc_dsn ? profile->odbc_dsn : profile->dbname, SWITCH_MAX_TRANS, profile->pre_trans_execute, @@ -4841,7 +4814,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status switch_channel_set_variable(channel, "sip_hangup_disposition", "recv_refuse"); } - if (status >= 500 && sip->sip_reason && sip->sip_reason->re_protocol && (!strcasecmp(sip->sip_reason->re_protocol, "Q.850") + if (status >= 400 && sip->sip_reason && sip->sip_reason->re_protocol && (!strcasecmp(sip->sip_reason->re_protocol, "Q.850") || !strcasecmp(sip->sip_reason->re_protocol, "FreeSWITCH") || !strcasecmp(sip->sip_reason->re_protocol, profile->username)) && sip->sip_reason->re_cause) { tech_pvt->q850_cause = atoi(sip->sip_reason->re_cause); @@ -6758,10 +6731,12 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t if ((a_session = switch_core_session_locate(br_a))) { const char *moh = profile->hold_music; switch_channel_t *a_channel = switch_core_session_get_channel(a_session); + switch_caller_profile_t *prof = switch_channel_get_caller_profile(channel_b); const char *tmp; switch_core_event_hook_add_state_change(a_session, xfer_hanguphook); switch_channel_set_variable(a_channel, "att_xfer_kill_uuid", switch_core_session_get_uuid(b_session)); + switch_channel_set_variable(a_channel, "att_xfer_destination_number", prof->destination_number); if (profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) { switch_channel_set_flag(a_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index bbaa9ae347..37caeba651 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -6373,7 +6373,7 @@ void sofia_glue_execute_sql(sofia_profile_t *profile, char **sqlp, switch_bool_t switch_assert(sqlp && *sqlp); sql = *sqlp; - switch_sql_queue_manager_push(profile->qm, sql, 0, !sql_already_dynamic); + switch_sql_queue_manager_push(profile->qm, sql, 1, !sql_already_dynamic); if (sql_already_dynamic) { *sqlp = NULL; @@ -6395,6 +6395,20 @@ void sofia_glue_execute_sql_now(sofia_profile_t *profile, char **sqlp, switch_bo } } +void sofia_glue_execute_sql_soon(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic) +{ + char *sql; + + switch_assert(sqlp && *sqlp); + sql = *sqlp; + + switch_sql_queue_manager_push(profile->qm, sql, 0, !sql_already_dynamic); + + if (sql_already_dynamic) { + *sqlp = NULL; + } +} + switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line) { @@ -6498,6 +6512,9 @@ switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, switch_cache_db_release_db_handle(&dbh); + + sofia_glue_fire_events(profile); + return ret; } @@ -6529,6 +6546,9 @@ char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex switch_cache_db_release_db_handle(&dbh); + + sofia_glue_fire_events(profile); + return ret; } @@ -7139,6 +7159,23 @@ char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool) return s; } +void sofia_glue_fire_events(sofia_profile_t *profile) +{ + void *pop = NULL; + + while (profile->event_queue && switch_queue_trypop(profile->event_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { + switch_event_t *event = (switch_event_t *) pop; + switch_event_fire(&event); + } + +} + +void sofia_event_fire(sofia_profile_t *profile, switch_event_t **event) +{ + switch_queue_push(profile->event_queue, *event); + *event = NULL; +} + /* For Emacs: * Local Variables: diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 17ab6b6efa..e11d96ff76 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -364,7 +364,9 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) if (!(mstatus > 199 && mstatus < 300)) { status = SWITCH_STATUS_FALSE; } - + + switch_event_add_header(message_event, SWITCH_STACK_BOTTOM, "Delivery-Result-Code", "%d", mstatus); + switch_mutex_lock(profile->flag_mutex); switch_core_hash_delete(profile->chat_hash, uuid_str); switch_mutex_unlock(profile->flag_mutex); @@ -1027,7 +1029,7 @@ static void conference_data_event_handler(switch_event_t *event) switch_safe_free(dup_domain); } -static void actual_sofia_presence_event_handler(switch_event_t *event) +static switch_event_t *actual_sofia_presence_event_handler(switch_event_t *event) { sofia_profile_t *profile = NULL; char *from = switch_event_get_header(event, "from"); @@ -1047,10 +1049,10 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_console_callback_match_t *matches; struct presence_helper helper = { 0 }; int hup = 0; - + switch_event_t *s_event = NULL; if (!mod_sofia_globals.running) { - return; + goto done; } if (zstr(proto) || !strcasecmp(proto, "any")) { @@ -1091,7 +1093,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) if (!mod_sofia_globals.profile_hash) { - return; + goto done; } if (from) { @@ -1171,7 +1173,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } switch_safe_free(sql); - return; + goto done; } if (zstr(event_type)) { @@ -1195,7 +1197,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } } else { switch_safe_free(user); - return; + goto done; } if ((euser = strchr(user, '+'))) { euser++; @@ -1203,7 +1205,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) euser = user; } } else { - return; + goto done; } switch (event->event_id) { @@ -1348,7 +1350,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } if (zstr(call_id)) { - + sql = switch_mprintf("update sip_subscriptions set version=version+1 where hostname='%q' and profile_name='%q' and " "sip_subscriptions.event != 'line-seize' " "and sip_subscriptions.proto='%q' and (event='%q' or event='%q') and sub_to_user='%q' and " @@ -1364,8 +1366,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql); } - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - + sofia_glue_execute_sql_soon(profile, &sql, SWITCH_TRUE); + sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host," @@ -1374,7 +1376,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," "sip_subscriptions.accept,sip_subscriptions.profile_name" ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q'," - "sip_subscriptions.version, '%q',sip_subscriptions.orig_proto,sip_subscriptions.full_to," + "sip_subscriptions.version+1, '%q',sip_subscriptions.orig_proto,sip_subscriptions.full_to," "sip_subscriptions.network_ip, sip_subscriptions.network_port " "from sip_subscriptions " "left join sip_presence on " @@ -1393,6 +1395,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) event_type, alt_event_type, euser, host, profile->sipip, profile->extsipip ? profile->extsipip : "N/A", host); } else { + sql = switch_mprintf("update sip_subscriptions set version=version+1 where sip_subscriptions.event != 'line-seize' and " "hostname='%q' and profile_name = '%q' and sip_subscriptions.call_id='%q'", mod_sofia_globals.hostname, profile->name, call_id); @@ -1402,7 +1405,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql); } - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + sofia_glue_execute_sql_soon(profile, &sql, SWITCH_TRUE); sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host," @@ -1411,7 +1414,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," "sip_subscriptions.accept,sip_subscriptions.profile_name" ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q'," - "sip_subscriptions.version, '%q',sip_subscriptions.orig_proto,sip_subscriptions.full_to," + "sip_subscriptions.version+1, '%q',sip_subscriptions.orig_proto,sip_subscriptions.full_to," "sip_subscriptions.network_ip, sip_subscriptions.network_port " "from sip_subscriptions " "left join sip_presence on " @@ -1459,11 +1462,9 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name); } - +#if 0 if (hup && dh.hits < 1) { /* so many phones get confused when whe hangup we have to reprobe to get them all to reset to absolute states so the lights stay correct */ - switch_event_t *s_event; - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); @@ -1471,10 +1472,10 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", euser, host); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_fire(&s_event); + sofia_event_fire(profile, &s_event); } } - +#endif if (!zstr((char *) helper.stream.data)) { char *this_sql = (char *) helper.stream.data; @@ -1509,11 +1510,24 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_safe_free(sql); switch_safe_free(user); + + return s_event; } static int EVENT_THREAD_RUNNING = 0; static int EVENT_THREAD_STARTED = 0; +static void do_flush(void) +{ + void *pop = NULL; + + while (mod_sofia_globals.presence_queue && switch_queue_trypop(mod_sofia_globals.presence_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { + switch_event_t *event = (switch_event_t *) pop; + switch_event_destroy(&event); + } + +} + void *SWITCH_THREAD_FUNC sofia_presence_event_thread_run(switch_thread_t *thread, void *obj) { void *pop; @@ -1544,6 +1558,15 @@ void *SWITCH_THREAD_FUNC sofia_presence_event_thread_run(switch_thread_t *thread break; } + if (mod_sofia_globals.presence_flush) { + switch_mutex_lock(mod_sofia_globals.mutex); + if (mod_sofia_globals.presence_flush) { + do_flush(); + mod_sofia_globals.presence_flush = 0; + } + switch_mutex_unlock(mod_sofia_globals.mutex); + } + switch(event->event_id) { case SWITCH_EVENT_MESSAGE_WAITING: actual_sofia_presence_mwi_event_handler(event); @@ -1552,7 +1575,11 @@ void *SWITCH_THREAD_FUNC sofia_presence_event_thread_run(switch_thread_t *thread conference_data_event_handler(event); break; default: - actual_sofia_presence_event_handler(event); + do { + switch_event_t *ievent = event; + event = actual_sofia_presence_event_handler(ievent); + switch_event_destroy(&ievent); + } while (event); break; } @@ -1561,10 +1588,7 @@ void *SWITCH_THREAD_FUNC sofia_presence_event_thread_run(switch_thread_t *thread } } - while (switch_queue_trypop(mod_sofia_globals.presence_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { - switch_event_t *event = (switch_event_t *) pop; - switch_event_destroy(&event); - } + do_flush(); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Event Thread Ended\n"); @@ -1606,13 +1630,23 @@ void sofia_presence_event_handler(switch_event_t *event) { switch_event_t *cloned_event; - switch_event_dup(&cloned_event, event); - switch_assert(cloned_event); - switch_queue_push(mod_sofia_globals.presence_queue, cloned_event); - if (!EVENT_THREAD_STARTED) { sofia_presence_event_thread_start(); + switch_yield(500000); } + + switch_event_dup(&cloned_event, event); + switch_assert(cloned_event); + + if (switch_queue_trypush(mod_sofia_globals.presence_queue, cloned_event) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Presence queue overloaded.... Flushing queue\n"); + switch_mutex_lock(mod_sofia_globals.mutex); + mod_sofia_globals.presence_flush = 1; + switch_mutex_unlock(mod_sofia_globals.mutex); + switch_event_destroy(&cloned_event); + } + + } @@ -1640,7 +1674,7 @@ static int sofia_presence_sub_reg_callback(void *pArg, int argc, char **argv, ch } - switch_event_fire(&event); + sofia_event_fire(profile, &event); } return 0; } @@ -1653,7 +1687,7 @@ static int sofia_presence_sub_reg_callback(void *pArg, int argc, char **argv, ch switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "expires", expires); - switch_event_fire(&event); + sofia_event_fire(profile, &event); } return 0; @@ -1777,7 +1811,7 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char } } - switch_event_fire(&event); + sofia_event_fire(profile, &event); } switch_safe_free(free_me); @@ -4320,7 +4354,8 @@ void sofia_presence_handle_sip_i_message(int status, if ((us = sofia_glue_get_unknown_header(sip, "X-FS-Sending-Message")) && !strcmp(us, switch_core_get_uuid())) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Not sending message to ourselves!\n"); - goto end; + nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); + return; } if (sip->sip_content_type && sip->sip_content_type->c_subtype) { diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 3e0e3965fe..79b49c1b6b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -635,7 +635,7 @@ int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", argv[3]); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "expires", argv[6]); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "user-agent", argv[7]); - switch_event_fire(&s_event); + sofia_event_fire(profile, &s_event); } if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { @@ -653,7 +653,7 @@ int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Unregistered"); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_fire(&s_event); + sofia_event_fire(profile, &s_event); } } @@ -859,7 +859,6 @@ void sofia_reg_check_sync(sofia_profile_t *profile) sql = switch_mprintf("delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - sql = switch_mprintf("delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); @@ -2354,6 +2353,8 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, if (zstr(np)) { nonce_cb_t cb = { 0 }; long nc_long = 0; + int sanity = 0; + first = 1; if (nc) { @@ -2367,7 +2368,14 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, cb.nplen = nplen; switch_assert(sql != NULL); - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_nonce_callback, &cb); + + do { + if (sanity) { + switch_yield(100000 * sanity); + } + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_nonce_callback, &cb); + } while(nc_long < 2 && ++sanity < 10 && zstr(np)); + free(sql); //if (!sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, np, nplen)) { diff --git a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c index d4c4d7cf9a..8a2b30d5e9 100644 --- a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c +++ b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c @@ -204,8 +204,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) bson_append_start_object(&cdr, "extension"); - bson_append_string(&cdr, "name", caller_profile->caller_extension->extension_name); - bson_append_string(&cdr, "number", caller_profile->caller_extension->extension_number); + bson_append_string(&cdr, "name", switch_str_nil(caller_profile->caller_extension->extension_name)); + bson_append_string(&cdr, "number", switch_str_nil(caller_profile->caller_extension->extension_number)); if (caller_profile->caller_extension->current_application) { bson_append_string(&cdr, "current_app", caller_profile->caller_extension->current_application->application_name); diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index f970a1c63e..f1dc5874e8 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -175,13 +175,8 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l if (switch_queue_trypush(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) { if (l->lost_logs) { int ll = l->lost_logs; - switch_event_t *event; l->lost_logs = 0; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Lost %d log lines!\n", ll); - if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "info", "lost %d log lines", ll); - switch_event_fire(&event); - } } } else { switch_log_node_free(&dnode); @@ -378,11 +373,6 @@ static void event_handler(switch_event_t *event) int le = l->lost_events; l->lost_events = 0; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(l->session), SWITCH_LOG_CRIT, "Lost %d events!\n", le); - clone = NULL; - if (switch_event_create(&clone, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(clone, SWITCH_STACK_BOTTOM, "info", "lost %d events", le); - switch_event_fire(&clone); - } } } else { if (++l->lost_events > MAX_MISSED) { diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c index 740d8a86cb..6d00f7ab38 100644 --- a/src/mod/formats/mod_shout/mod_shout.c +++ b/src/mod/formats/mod_shout/mod_shout.c @@ -1161,6 +1161,8 @@ static int web_callback(void *pArg, int argc, char **argv, char **columnNames) char title_b4[128] = ""; char title_aft[128 * 3 + 1] = ""; char *mp3, *m3u; + int uri_offset = 1; + const char *uuid = argv[0]; const char *created = argv[1]; const char *cid_name = argv[2]; @@ -1178,8 +1180,10 @@ static int web_callback(void *pArg, int argc, char **argv, char **columnNames) snprintf(title_b4, sizeof(title_b4), "%s <%s>", cid_name, cid_num); switch_url_encode(title_b4, title_aft, sizeof(title_aft)); - mp3 = switch_mprintf("http://%s:%s%s/mp3/%s/%s.mp3", holder->host, holder->port, holder->uri, uuid, cid_num); - m3u = switch_mprintf("http://%s:%s%s/m3u/mp3/%s/%s.mp3.m3u", holder->host, holder->port, holder->uri, uuid, cid_num); + if (!strncmp(holder->uri, "/webapi", 7)) uri_offset = 4; + + mp3 = switch_mprintf("http://%s:%s/%s/mp3/%s/%s.mp3", holder->host, holder->port, holder->uri + uri_offset, uuid, cid_num); + m3u = switch_mprintf("http://%s:%s/%s/m3u/mp3/%s/%s.mp3.m3u", holder->host, holder->port, holder->uri + uri_offset, uuid, cid_num); holder->stream->write_function(holder->stream, "[mp3] ", mp3); holder->stream->write_function(holder->stream, "[m3u]\n", m3u); diff --git a/src/mod/languages/mod_lua/freeswitch_lua.cpp b/src/mod/languages/mod_lua/freeswitch_lua.cpp index 679c9fbee4..811a8a7bd6 100644 --- a/src/mod/languages/mod_lua/freeswitch_lua.cpp +++ b/src/mod/languages/mod_lua/freeswitch_lua.cpp @@ -335,6 +335,7 @@ Dbh::Dbh(char *dsn, char *user, char *pass) { switch_cache_db_connection_options_t options = { {0} }; const char *prefix = "core:"; + switch_cache_db_handle_type_t type; m_connected = false; if (strstr(dsn, prefix) == dsn) { @@ -342,6 +343,12 @@ Dbh::Dbh(char *dsn, char *user, char *pass) if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) == SWITCH_STATUS_SUCCESS) { m_connected = true; } + } else if (!strncasecmp(dsn, "pgsql://", 8)) { + type = SCDB_TYPE_PGSQL; + options.pgsql_options.dsn = (char *)(dsn + 8); + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) == SWITCH_STATUS_SUCCESS) { + m_connected = true; + } } else { options.odbc_options.dsn = dsn; options.odbc_options.user = user; diff --git a/src/switch_channel.c b/src/switch_channel.c index 5ccca55184..5fa30564d2 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -129,6 +129,7 @@ struct switch_channel { switch_mutex_t *dtmf_mutex; switch_mutex_t *flag_mutex; switch_mutex_t *state_mutex; + switch_mutex_t *thread_mutex; switch_mutex_t *profile_mutex; switch_core_session_t *session; switch_channel_state_t state; @@ -352,6 +353,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool); switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool); switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED, pool); + switch_mutex_init(&(*channel)->thread_mutex, SWITCH_MUTEX_NESTED, pool); switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool); (*channel)->hangup_cause = SWITCH_CAUSE_NONE; (*channel)->name = ""; @@ -1925,6 +1927,32 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_name_state(const char *nam return CS_DESTROY; } +static inline void careful_set(switch_channel_t *channel, switch_channel_state_t *state, switch_channel_state_t val) { + + if (switch_mutex_trylock(channel->thread_mutex) == SWITCH_STATUS_SUCCESS) { + *state = val; + switch_mutex_unlock(channel->thread_mutex); + } else { + switch_mutex_t *mutex = switch_core_session_get_mutex(channel->session); + int x = 0; + + for (x = 0; x < 100; x++) { + if (switch_mutex_trylock(mutex) == SWITCH_STATUS_SUCCESS) { + *state = val; + switch_mutex_unlock(mutex); + break; + } else { + switch_cond_next(); + } + } + + if (x == 100) { + *state = val; + } + + } +} + SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state(switch_channel_t *channel, switch_channel_state_t state, const char *file, const char *func, int line) { @@ -1950,7 +1978,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state( switch_mutex_lock(channel->state_mutex); - channel->running_state = state; + careful_set(channel, &channel->running_state, state); if (state <= CS_DESTROY) { switch_event_t *event; @@ -2218,7 +2246,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) State Change %s -> %s\n", channel->name, state_names[last_state], state_names[state]); - channel->state = state; + careful_set(channel, &channel->state, state); if (state == CS_HANGUP && !channel->hangup_cause) { channel->hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING; @@ -2240,6 +2268,16 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_c return channel->state; } +SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel) +{ + switch_mutex_lock(channel->thread_mutex); +} + +SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel) +{ + switch_mutex_unlock(channel->thread_mutex); +} + SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *channel, switch_event_t *event) { switch_caller_profile_t *caller_profile, *originator_caller_profile = NULL, *originatee_caller_profile = NULL; @@ -2254,7 +2292,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann originatee_caller_profile = caller_profile->originatee_caller_profile; } - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(channel->state)); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(channel->running_state)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate)); switch_snprintf(state_num, sizeof(state_num), "%d", channel->state); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", state_num); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index cf7daaac16..e1093c50f3 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1245,6 +1245,11 @@ SWITCH_DECLARE(switch_channel_t *) switch_core_session_get_channel(switch_core_s return session->channel; } +SWITCH_DECLARE(switch_mutex_t *) switch_core_session_get_mutex(switch_core_session_t *session) +{ + return session->mutex; +} + SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(switch_core_session_t *session) { switch_status_t status; @@ -1530,13 +1535,23 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_worker(switch_th while(session_manager.ready) { switch_status_t check_status; + pop = NULL; + if (check) { check_status = switch_queue_trypop(session_manager.thread_queue, &pop); } else { + switch_mutex_lock(session_manager.mutex); + session_manager.popping++; + switch_mutex_unlock(session_manager.mutex); + check_status = switch_queue_pop(session_manager.thread_queue, &pop); + + switch_mutex_lock(session_manager.mutex); + session_manager.popping--; + switch_mutex_unlock(session_manager.mutex); } - if (check_status == SWITCH_STATUS_SUCCESS) { + if (check_status == SWITCH_STATUS_SUCCESS && pop) { switch_thread_data_t *td = (switch_thread_data_t *) pop; if (!td) break; @@ -1614,7 +1629,6 @@ static switch_status_t check_queue(void) switch_mutex_unlock(session_manager.mutex); - while (x < ttl) { switch_thread_t *thread; switch_threadattr_t *thd_attr; @@ -1653,13 +1667,32 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_manager(switch_t switch_yield(100000); if (++x == 300) { - switch_queue_interrupt_all(session_manager.thread_queue); - x = 0; + if (session_manager.popping) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, + "Thread pool: running:%d busy:%d popping:%d\n", session_manager.running, session_manager.busy, session_manager.popping); + + if (session_manager.popping) { + int i = 0; + + switch_mutex_lock(session_manager.mutex); + for (i = 0; i < session_manager.popping; i++) { + switch_queue_trypush(session_manager.thread_queue, NULL); + } + switch_mutex_unlock(session_manager.mutex); + + } + + x--; + + continue; + } else { + x = 0; + } } check_queue(); } - + return NULL; } diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 7fa478815e..b776a14a87 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -293,6 +293,17 @@ SWITCH_DECLARE(void) switch_cache_db_flush_handles(void) SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh) { if (dbh && *dbh) { + + switch((*dbh)->type) { + case SCDB_TYPE_PGSQL: + { + switch_pgsql_flush((*dbh)->native_handle.pgsql_dbh); + } + break; + default: + break; + } + switch_mutex_lock(sql_manager.dbh_mutex); (*dbh)->last_used = switch_epoch_time_now(NULL); @@ -406,7 +417,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h switch (type) { case SCDB_TYPE_PGSQL: { - db_name = connection_options->odbc_options.dsn; + db_name = connection_options->pgsql_options.dsn; odbc_user = NULL; odbc_pass = NULL; } @@ -835,7 +846,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans_full(sw switch(dbh->type) { case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg); + switch_cache_db_execute_sql_real(dbh, "BEGIN EXCLUSIVE", &errmsg); } break; case SCDB_TYPE_ODBC: @@ -1497,7 +1508,7 @@ static uint32_t do_trans(switch_sql_queue_manager_t *qm) switch(qm->event_db->type) { case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql_real(qm->event_db, "BEGIN", &errmsg); + switch_cache_db_execute_sql_real(qm->event_db, "BEGIN EXCLUSIVE", &errmsg); } break; case SCDB_TYPE_ODBC: @@ -2957,6 +2968,8 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ case SCDB_TYPE_ODBC: { char *err; + int result = 0; + switch_cache_db_test_reactive(sql_manager.dbh, "select call_uuid, read_bit_rate, sent_callee_name from channels", "DROP TABLE channels", create_channels_sql); switch_cache_db_test_reactive(sql_manager.dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql); switch_cache_db_test_reactive(sql_manager.dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql); @@ -2973,12 +2986,72 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_cache_db_test_reactive(sql_manager.dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql); switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql); - if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_execute_sql(sql_manager.dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); - } else { - switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels where hostname='';delete from channels where hostname='';", &err); + + switch(sql_manager.dbh->type) { + case SCDB_TYPE_CORE_DB: + { + switch_cache_db_execute_sql_real(sql_manager.dbh, "BEGIN EXCLUSIVE", &err); + } + break; + case SCDB_TYPE_ODBC: + { + switch_odbc_status_t result; + + if ((result = switch_odbc_SQLSetAutoCommitAttr(sql_manager.dbh->native_handle.odbc_dbh, 0)) != SWITCH_ODBC_SUCCESS) { + char tmp[100]; + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result); + err = strdup(tmp); + } + } + break; + case SCDB_TYPE_PGSQL: + { + switch_pgsql_status_t result; + + if ((result = switch_pgsql_SQLSetAutoCommitAttr(sql_manager.dbh->native_handle.pgsql_dbh, 0)) != SWITCH_PGSQL_SUCCESS) { + char tmp[100]; + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result); + err = strdup(tmp); + } + } + break; + } + + switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels where hostname=''", &err); + if (!err) { + switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels where hostname=''", &err); + + switch(sql_manager.dbh->type) { + case SCDB_TYPE_CORE_DB: + { + switch_cache_db_execute_sql_real(sql_manager.dbh, "COMMIT", &err); + } + break; + case SCDB_TYPE_ODBC: + { + if (switch_odbc_SQLEndTran(sql_manager.dbh->native_handle.odbc_dbh, 1) != SWITCH_ODBC_SUCCESS || + switch_odbc_SQLSetAutoCommitAttr(sql_manager.dbh->native_handle.odbc_dbh, 1) != SWITCH_ODBC_SUCCESS) { + char tmp[100]; + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to commit transaction.", result); + err = strdup(tmp); + } + } + break; + case SCDB_TYPE_PGSQL: + { + if (switch_pgsql_SQLEndTran(sql_manager.dbh->native_handle.pgsql_dbh, 1) != SWITCH_PGSQL_SUCCESS || + switch_pgsql_SQLSetAutoCommitAttr(sql_manager.dbh->native_handle.pgsql_dbh, 1) != SWITCH_PGSQL_SUCCESS || + switch_pgsql_finish_results(sql_manager.dbh->native_handle.pgsql_dbh) != SWITCH_PGSQL_SUCCESS) { + char tmp[100]; + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to commit transaction.", result); + err = strdup(tmp); + } + } + break; + } } + if (err) { runtime.odbc_dsn = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Transactions not supported on your DB, disabling non-SQLite support; using SQLite\n"); @@ -3069,6 +3142,9 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_thread_create(&sql_manager.db_thread, thd_attr, switch_core_sql_db_thread, NULL, sql_manager.memory_pool); } + + switch_cache_db_release_db_handle(&sql_manager.dbh); + return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 87b8a32a20..daa5bf37d4 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -521,11 +521,13 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) switch_ivr_parse_all_events(session); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { + switch_channel_state_thread_lock(session->channel); switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_thread_cond_wait(session->cond, session->mutex); } switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING); + switch_channel_state_thread_unlock(session->channel); } switch_ivr_parse_all_events(session); diff --git a/src/switch_event.c b/src/switch_event.c index 566ccc82f8..259a5fa25c 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -37,7 +37,7 @@ #include "tpl.h" //#define SWITCH_EVENT_RECYCLE -#define DISPATCH_QUEUE_LEN 100 +#define DISPATCH_QUEUE_LEN 10000 //#define DEBUG_DISPATCH_QUEUES /*! \brief A node to store binded events */ @@ -291,6 +291,8 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th } +static int PENDING = 0; + static switch_status_t switch_event_queue_dispatch_event(switch_event_t **eventp) { @@ -302,11 +304,14 @@ static switch_status_t switch_event_queue_dispatch_event(switch_event_t **eventp while (event) { int launch = 0; - + switch_mutex_lock(EVENT_QUEUE_MUTEX); - if (switch_queue_size(EVENT_DISPATCH_QUEUE) > (unsigned int)(DISPATCH_QUEUE_LEN * DISPATCH_THREAD_COUNT)) { - launch++; + if (!PENDING && switch_queue_size(EVENT_DISPATCH_QUEUE) > (unsigned int)(DISPATCH_QUEUE_LEN * DISPATCH_THREAD_COUNT)) { + if (SOFT_MAX_DISPATCH + 1 > MAX_DISPATCH) { + launch++; + PENDING++; + } } switch_mutex_unlock(EVENT_QUEUE_MUTEX); @@ -315,6 +320,10 @@ static switch_status_t switch_event_queue_dispatch_event(switch_event_t **eventp if (SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH) { switch_event_launch_dispatch_threads(SOFT_MAX_DISPATCH + 1); } + + switch_mutex_lock(EVENT_QUEUE_MUTEX); + PENDING--; + switch_mutex_unlock(EVENT_QUEUE_MUTEX); } *eventp = NULL; @@ -472,7 +481,6 @@ SWITCH_DECLARE(switch_status_t) switch_event_shutdown(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping dispatch queues\n"); - for(x = 0; x < (uint32_t)DISPATCH_THREAD_COUNT; x++) { switch_queue_trypush(EVENT_DISPATCH_QUEUE, NULL); } @@ -487,8 +495,8 @@ SWITCH_DECLARE(switch_status_t) switch_event_shutdown(void) } x = 0; - while (x < 10000 && THREAD_COUNT) { - switch_cond_next(); + while (x < 100 && THREAD_COUNT) { + switch_yield(100000); if (THREAD_COUNT == last) { x++; } @@ -1139,17 +1147,21 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event) for (hp = ep->headers; hp;) { this = hp; hp = hp->next; - FREE(this->name); if (this->idx) { - int i = 0; + if (!this->array) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "INDEX WITH NO ARRAY WTF?? [%s][%s]\n", this->name, this->value); + } else { + int i = 0; - for (i = 0; i < this->idx; i++) { - FREE(this->array[i]); + for (i = 0; i < this->idx; i++) { + FREE(this->array[i]); + } + FREE(this->array); } - FREE(this->array); } + FREE(this->name); FREE(this->value); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index eb8d4ab9e6..18329714aa 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -153,7 +153,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, if (!switch_channel_media_ready(channel)) { - for (elapsed=0; elapsed<(ms/20); elapsed++) { + for (elapsed=0; switch_channel_up(channel) && elapsed<(ms/20); elapsed++) { if (switch_channel_test_flag(channel, CF_BREAK)) { switch_channel_clear_flag(channel, CF_BREAK); return SWITCH_STATUS_BREAK; diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index b286ab5918..7eb96b287a 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -316,7 +316,16 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) if ((b_state = switch_channel_down_nosig(chan_b))) { goto end_of_bridge_loop; } - + + if (switch_channel_test_flag(chan_a, CF_HOLD_ON_BRIDGE)) { + switch_core_session_message_t hmsg = { 0 }; + switch_channel_clear_flag(chan_a, CF_HOLD_ON_BRIDGE); + hmsg.message_id = SWITCH_MESSAGE_INDICATE_HOLD; + hmsg.from = __FILE__; + hmsg.numeric_arg = 1; + switch_core_session_receive_message(session_a, &hmsg); + } + if (read_frame_count > DEFAULT_LEAD_FRAMES && switch_channel_media_ack(chan_a) && switch_core_session_private_event_count(session_a)) { switch_channel_set_flag(chan_b, CF_SUSPEND); msg.numeric_arg = 42; @@ -1556,6 +1565,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu originatee_channel = switch_core_session_get_channel(originatee_session); + if (switch_channel_test_flag(originator_channel, CF_LEG_HOLDING)) { + switch_channel_set_flag(originator_channel, CF_HOLD_ON_BRIDGE); + } + + if (switch_channel_test_flag(originatee_channel, CF_LEG_HOLDING)) { + switch_channel_set_flag(originatee_channel, CF_HOLD_ON_BRIDGE); + } + + + if (switch_channel_direction(originatee_channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(originatee_channel, CF_DIALPLAN)) { switch_channel_flip_cid(originatee_channel); switch_channel_set_flag(originatee_channel, CF_DIALPLAN); diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index d87d37f7fc..d63ff074f1 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -512,6 +512,7 @@ static switch_status_t do_chat_send(switch_event_t *message_event) switch_chat_interface_t *ci; switch_status_t status = SWITCH_STATUS_FALSE; switch_hash_index_t *hi; + switch_event_t *dup = NULL; const void *var; void *val; const char *proto; @@ -563,12 +564,21 @@ static switch_status_t do_chat_send(switch_event_t *message_event) if ((ci = (switch_chat_interface_t *) val)) { if (ci->chat_send && !strncasecmp(ci->interface_name, "GLOBAL_", 7)) { status = ci->chat_send(message_event); - if (status == SWITCH_STATUS_BREAK) { + if (status == SWITCH_STATUS_SUCCESS) { + /* The event was handled by an extension in the chatplan, + * so the event will be duplicated, modified and queued again, + * but it won't be processed by the chatplan again. + * So this copy of the event can be destroyed by the caller. + */ + switch_mutex_unlock(loadable_modules.mutex); + return SWITCH_STATUS_SUCCESS; + } else if (status == SWITCH_STATUS_BREAK) { + /* The event went through the chatplan, but no extension matched + * to handle the sms messsage. It'll be attempted to be delivered + * directly, and unless that works the sms delivery will have failed. + */ do_skip = 1; - status = SWITCH_STATUS_SUCCESS; - } - - if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { + } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Chat Interface Error [%s]!\n", dest_proto); break; } @@ -588,14 +598,20 @@ static switch_status_t do_chat_send(switch_event_t *message_event) } } - if (status != SWITCH_STATUS_SUCCESS) { - switch_event_t *dup; - switch_event_dup(&dup, message_event); - switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Delivery-Failure", "true"); - switch_event_fire(&dup); + + switch_event_dup(&dup, message_event); + + if ( switch_true(switch_event_get_header(message_event, "blocking")) ) { + if (status == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Delivery-Failure", "false"); + } else { + switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Delivery-Failure", "true"); + } + } else { + switch_event_add_header_string(dup, SWITCH_STACK_BOTTOM, "Nonblocking-Delivery", "true"); } - + switch_event_fire(&dup); return status; } @@ -1766,8 +1782,8 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autolo switch_loadable_module_runtime(); - chat_globals.running = 1; memset(&chat_globals, 0, sizeof(chat_globals)); + chat_globals.running = 1; chat_globals.pool = loadable_modules.pool; switch_mutex_init(&chat_globals.mutex, SWITCH_MUTEX_NESTED, chat_globals.pool); diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c index 22ab6ffd6d..6d6bd656e9 100644 --- a/src/switch_pgsql.c +++ b/src/switch_pgsql.c @@ -43,7 +43,7 @@ struct switch_pgsql_handle { char *dsn; - const char *sql; + char *sql; PGconn* con; int sock; switch_pgsql_state_t state; @@ -96,6 +96,122 @@ SWITCH_DECLARE(switch_pgsql_handle_t *) switch_pgsql_handle_new(const char *dsn) return NULL; } + +#ifdef SWITCH_HAVE_PGSQL +static int db_is_up(switch_pgsql_handle_t *handle) +{ + int ret = 0; + switch_event_t *event; + char *err_str = NULL; + int max_tries = DEFAULT_PGSQL_RETRIES; + int code = 0, recon = 0; + + if (handle) { + max_tries = handle->num_retries; + if (max_tries < 1) + max_tries = DEFAULT_PGSQL_RETRIES; + } + + top: + + if (!handle) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Handle\n"); + goto done; + } + if (!handle->con) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Connection\n"); + goto done; + } + + /* Try a non-blocking read on the connection to gobble up any EOF from a closed connection and mark the connection BAD if it is closed. */ + PQconsumeInput(handle->con); + + if (PQstatus(handle->con) == CONNECTION_BAD) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "PQstatus returned bad connection; reconnecting...\n"); + handle->state = SWITCH_PGSQL_STATE_ERROR; + PQreset(handle->con); + if (PQstatus(handle->con) == CONNECTION_BAD) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PQstatus returned bad connection -- reconnection failed!\n"); + goto error; + } + handle->state = SWITCH_PGSQL_STATE_CONNECTED; + handle->sock = PQsocket(handle->con); + } + +/* if (!PQsendQuery(handle->con, "SELECT 1")) { + code = __LINE__; + goto error; + } + + if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { + code = __LINE__; + goto error; + } + + if (!result || result->status != PGRES_COMMAND_OK) { + code = __LINE__; + goto error; + } + + switch_pgsql_free_result(&result); + switch_pgsql_finish_results(handle); +*/ + ret = 1; + goto done; + + error: + err_str = switch_pgsql_handle_get_error(handle); + + if (PQstatus(handle->con) == CONNECTION_BAD) { + handle->state = SWITCH_PGSQL_STATE_ERROR; + PQreset(handle->con); + if (PQstatus(handle->con) == CONNECTION_OK) { + handle->state = SWITCH_PGSQL_STATE_CONNECTED; + recon = SWITCH_PGSQL_SUCCESS; + handle->sock = PQsocket(handle->con); + } + } + + max_tries--; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]", + switch_str_nil(handle->dsn), switch_str_nil(err_str), code); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n", + switch_str_nil(handle->dsn), switch_str_nil(err_str), code); + + if (recon == SWITCH_PGSQL_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n"); + } else { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n"); + } + if (!max_tries) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up!\n"); + } + + switch_event_fire(&event); + } + + if (!max_tries) { + goto done; + } + + switch_safe_free(err_str); + switch_yield(1000000); + goto top; + + done: + + switch_safe_free(err_str); + + return ret; +} +#endif + + SWITCH_DECLARE(void) switch_pgsql_set_num_retries(switch_pgsql_handle_t *handle, int num_retries) { #ifdef SWITCH_HAVE_PGSQL @@ -117,7 +233,7 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_disconnect(switch_pgsq PQfinish(handle->con); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Disconnected from [%s]\n", handle->dsn); } - + switch_safe_free(handle->sql); handle->state = SWITCH_PGSQL_STATE_DOWN; return SWITCH_PGSQL_SUCCESS; @@ -131,13 +247,14 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handl #ifdef SWITCH_HAVE_PGSQL char *err_str; + switch_safe_free(handle->sql); + handle->sql = strdup(sql); if (!PQsendQuery(handle->con, sql)) { err_str = switch_pgsql_handle_get_error(handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to send query (%s) to database: %s\n", sql, err_str); switch_pgsql_finish_results(handle); goto error; } - handle->sql = sql; return SWITCH_PGSQL_SUCCESS; error: @@ -159,6 +276,8 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_cancel_real(const char *file, ret = SWITCH_PGSQL_FAIL; } PQfreeCancel(cancel); + switch_pgsql_flush(handle); + #endif return ret; } @@ -192,12 +311,29 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsq fds[0].fd = handle->sock; fds[0].events |= POLLIN; fds[0].events |= POLLERR; + fds[0].events |= POLLNVAL; + fds[0].events |= POLLHUP; + fds[0].events |= POLLPRI; + fds[0].events |= POLLRDNORM; + fds[0].events |= POLLRDBAND; /* Wait for the PostgreSQL socket to be ready for data reads. */ - if ((poll_res = poll(&fds[0], 1, wait_time)) > -1 ) { - if (fds[0].revents & POLLIN) { + if ((poll_res = poll(&fds[0], 1, wait_time)) > 0 ) { + if (fds[0].revents & POLLHUP || fds[0].revents & POLLNVAL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PGSQL socket closed or invalid while waiting for result for query (%s)\n", handle->sql); + goto error; + } else if (fds[0].revents & POLLERR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql); + goto error; + } else if (fds[0].revents & POLLIN || fds[0].revents & POLLPRI || fds[0].revents & POLLRDNORM || fds[0].revents & POLLRDBAND) { /* Then try to consume any input waiting. */ if (PQconsumeInput(handle->con)) { + if (PQstatus(handle->con) == CONNECTION_BAD) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Connection terminated while waiting for result.\n"); + handle->state = SWITCH_PGSQL_STATE_ERROR; + goto error; + } + /* And check to see if we have a full result ready for reading */ if (!PQisBusy(handle->con)) { /* If we can pull a full result without blocking, then break this loop */ @@ -211,11 +347,8 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsq switch_pgsql_cancel(handle); goto error; } - } else if (fds[0].revents & POLLERR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql); - goto error; } - } else { + } else if (poll_res == -1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll failed trying to read PGSQL socket for query (%s)\n", handle->sql); goto error; } @@ -228,15 +361,13 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsq goto error; } - - } } else { /* If we had an error trying to consume input, report it and cancel the query. */ err_str = switch_pgsql_handle_get_error(handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str); switch_safe_free(err_str); - switch_pgsql_cancel(handle); + /* switch_pgsql_cancel(handle); */ goto error; } @@ -289,11 +420,17 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsq free(res); res = NULL; *result_out = NULL; - goto error; } return SWITCH_PGSQL_SUCCESS; error: + + /* Make sure the failed connection does not have any transactions marked as in progress */ + switch_pgsql_flush(handle); + + /* Try to reconnect to the DB if we were dropped */ + db_is_up(handle); + #endif return SWITCH_PGSQL_FAIL; } @@ -337,115 +474,6 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const cha #endif } -#ifdef SWITCH_HAVE_PGSQL -static int db_is_up(switch_pgsql_handle_t *handle) -{ - int ret = 0; - switch_event_t *event; - char *err_str = NULL; - int max_tries = DEFAULT_PGSQL_RETRIES; - int code = 0, recon = 0; - - if (handle) { - max_tries = handle->num_retries; - if (max_tries < 1) - max_tries = DEFAULT_PGSQL_RETRIES; - } - - top: - - if (!handle) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Handle\n"); - goto done; - } - if (!handle->con) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Connection\n"); - goto done; - } - - if (PQstatus(handle->con) == CONNECTION_BAD) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "PQstatus returned bad connection; reconnecting...\n"); - handle->state = SWITCH_PGSQL_STATE_ERROR; - PQreset(handle->con); - if (PQstatus(handle->con) == CONNECTION_BAD) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PQstatus returned bad connection -- reconnection failed!\n"); - goto error; - } - handle->state = SWITCH_PGSQL_STATE_CONNECTED; - } - -/* if (!PQsendQuery(handle->con, "SELECT 1")) { - code = __LINE__; - goto error; - } - - if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { - code = __LINE__; - goto error; - } - - if (!result || result->status != PGRES_COMMAND_OK) { - code = __LINE__; - goto error; - } - - switch_pgsql_free_result(&result); - switch_pgsql_finish_results(handle); -*/ - ret = 1; - goto done; - - error: - err_str = switch_pgsql_handle_get_error(handle); - - if (PQstatus(handle->con) == CONNECTION_BAD) { - handle->state = SWITCH_PGSQL_STATE_ERROR; - PQreset(handle->con); - if (PQstatus(handle->con) == CONNECTION_OK) { - handle->state = SWITCH_PGSQL_STATE_CONNECTED; - recon = SWITCH_PGSQL_SUCCESS; - } - } - - max_tries--; - - if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]", - switch_str_nil(handle->dsn), switch_str_nil(err_str), code); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n", - switch_str_nil(handle->dsn), switch_str_nil(err_str), code); - - if (recon == SWITCH_PGSQL_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n"); - } else { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n"); - } - if (!max_tries) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up!\n"); - } - - switch_event_fire(&event); - } - - if (!max_tries) { - goto done; - } - - switch_safe_free(err_str); - switch_yield(1000000); - goto top; - - done: - - switch_safe_free(err_str); - - return ret; -} -#endif - SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_connect(switch_pgsql_handle_t *handle) { @@ -479,7 +507,8 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_connect(switch_pgsql_h #endif } -SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err) +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string_detailed(const char *file, const char *func, int line, + switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err) { #ifdef SWITCH_HAVE_PGSQL switch_pgsql_status_t sstatus = SWITCH_PGSQL_SUCCESS; @@ -488,7 +517,7 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgs handle->affected_rows = 0; - if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { + if (switch_pgsql_handle_exec_base_detailed(file, func, line, handle, sql, err) == SWITCH_PGSQL_FAIL) { goto error; } @@ -533,11 +562,15 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgs #endif } -SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err) +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base_detailed(const char *file, const char *func, int line, + switch_pgsql_handle_t *handle, const char *sql, char **err) { #ifdef SWITCH_HAVE_PGSQL char *err_str = NULL, *er = NULL; + + + switch_pgsql_flush(handle); handle->affected_rows = 0; if (!db_is_up(handle)) { @@ -548,11 +581,14 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) { if (switch_pgsql_send_query(handle, "BEGIN") != SWITCH_PGSQL_SUCCESS) { er = strdup("Error sending BEGIN!"); - switch_pgsql_finish_results(handle); + if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { + db_is_up(handle); /* If finish_results failed, maybe the db went dead */ + } goto error; } if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { + db_is_up(handle); er = strdup("Error sending BEGIN!"); goto error; } @@ -561,7 +597,9 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql if (switch_pgsql_send_query(handle, sql) != SWITCH_PGSQL_SUCCESS) { er = strdup("Error sending query!"); - switch_pgsql_finish_results(handle); + if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { + db_is_up(handle); + } goto error; } @@ -584,7 +622,7 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql if (err_str) { if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); } if (err) { *err = err_str; @@ -596,10 +634,11 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql return SWITCH_PGSQL_FAIL; } -SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec(switch_pgsql_handle_t *handle, const char *sql, char **err) +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_detailed(const char *file, const char *func, int line, + switch_pgsql_handle_t *handle, const char *sql, char **err) { #ifdef SWITCH_HAVE_PGSQL - if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { + if (switch_pgsql_handle_exec_base_detailed(file, func, line, handle, sql, err) == SWITCH_PGSQL_FAIL) { goto error; } @@ -789,6 +828,29 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLSetAutoCommitAttr(switch_p #endif } +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_flush(switch_pgsql_handle_t *handle) +{ +#ifdef SWITCH_HAVE_PGSQL + + PGresult *tmp = NULL; + int x = 0; + + /* Make sure the query is fully cleared */ + while ((tmp = PQgetResult(handle->con)) != NULL) { + PQclear(tmp); + x++; + } + + if (x) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Flushing %d results\n", x); + } + + return SWITCH_PGSQL_SUCCESS; +#else + return (switch_pgsql_status_t) SWITCH_FALSE; +#endif +} + SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLEndTran(switch_pgsql_handle_t *handle, switch_bool_t commit) { #ifdef SWITCH_HAVE_PGSQL diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 8f9fc955a7..73c1db88b0 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -3145,8 +3145,8 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t rtp_session->rtcp_fresh_frame = 1; - rtp_session->stats.rtcp.packet_count += sr->pc; - rtp_session->stats.rtcp.octet_count += sr->oc; + rtp_session->stats.rtcp.packet_count += ntohl(sr->pc); + rtp_session->stats.rtcp.octet_count += ntohl(sr->oc); rtp_session->stats.rtcp.peer_ssrc = ntohl(sr->ssrc); /* sender report */ diff --git a/src/switch_utils.c b/src/switch_utils.c index 090812a45b..fad8530245 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -881,7 +881,7 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, from = "freeswitch"; } #ifdef WIN32 - switch_snprintf(buf, B64BUFFLEN, "type %s | %s -f %s %s %s", filename, runtime.mailer_app, from, runtime.mailer_app_args, to); + switch_snprintf(buf, B64BUFFLEN, "type \"%s\" | \"%s\" -f %s %s %s", filename, runtime.mailer_app, from, runtime.mailer_app_args, to); #else switch_snprintf(buf, B64BUFFLEN, "/bin/cat %s | %s -f %s %s %s", filename, runtime.mailer_app, from, runtime.mailer_app_args, to); #endif diff --git a/src/switch_xml.c b/src/switch_xml.c index e0f3e3d37d..fe67c95169 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -2458,7 +2458,7 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len, *len += sprintf(*s + *len, "%s", XML_INDENT); /* indent */ } } - *len += sprintf(*s + (*len), "", xml->name); /* close tag */ + *len += sprintf(*s + (*len), "\n", xml->name); /* close tag */ } while (txt[off] && off < xml->off)