Ejemplo n.º 1
0
bool BoardFXO::KhompPvtFXO::onDtmfDetected(K3L_EVENT *e)
{
    DBG(FUNC, PVT_FMT(_target, "(FXO) c"));

    bool ret = true;

    try
    {
        ScopedPvtLock lock(this);

        if (callFXO()->_flags.check(Kflags::WAIT_SEND_DTMF) ||
                callFXO()->_flags.check(Kflags::CALL_WAIT_SEIZE))
        {
            /* waiting digit or seize means DEADLOCK if we try to 
             *  queue something below. */
            DBG(FUNC, PVT_FMT(_target, "not queueing dtmf, waiting stuff!"));
            return true;
        }

        ret = KhompPvt::onDtmfDetected(e);
    }
    catch (ScopedLockFailed & err)
    {
        LOG(ERROR, PVT_FMT(_target, "(FXO) r (unable to lock %s!)") % err._msg.c_str() );
        return false;
    }

    DBG(FUNC, PVT_FMT(_target, "(FXO) r"));

    return ret;
}
Ejemplo n.º 2
0
bool BoardFXO::KhompPvtFXO::onCallAnswerInfo(K3L_EVENT *e)
{
    DBG(FUNC, PVT_FMT(_target, "(FXO) c"));
    try
    {
        ScopedPvtLock lock(this);

        int info_code = -1;

        switch (e->AddInfo)
        {
            case kcsiCellPhoneMessageBox:
                info_code = CI_MESSAGE_BOX;
                break;
            case kcsiHumanAnswer:
                info_code = CI_HUMAN_ANSWER;
                break;
            case kcsiAnsweringMachine:
                info_code = CI_ANSWERING_MACHINE;
                break;
            case kcsiCarrierMessage:
                info_code = CI_CARRIER_MESSAGE;
                break;
            case kcsiUnknown:
                info_code = CI_UNKNOWN;
                break;
            default:
                DBG(FUNC, PVT_FMT(_target, "got an unknown call answer info '%d', ignoring...") % e->AddInfo);
                break;
        }

        if (info_code != -1)
        {
            if (callFXO()->_call_info_report)
            {
                //TODO: HOW WE TREAT THAT 
                // make the channel export this 
                setAnswerInfo(info_code);
            }

            if (callFXO()->_call_info_drop & info_code)
            {
                command(KHOMP_LOG,CM_DISCONNECT);
            }
        }
    }
    catch (ScopedLockFailed & err)
    {
        LOG(ERROR, PVT_FMT(_target,"(FXO) r (unable to lock %s!)") % err._msg.c_str() );
        return false;
    }

    DBG(FUNC, PVT_FMT(_target, "(FXO) r"));
    return true;
}
Ejemplo n.º 3
0
bool BoardFXO::KhompPvtFXO::setupConnection()
{
    if(!call()->_flags.check(Kflags::IS_INCOMING) && !call()->_flags.check(Kflags::IS_OUTGOING))
    {
        DBG(FUNC,PVT_FMT(_target, "Channel already disconnected"));
        return false;
    }

    callFXO()->_flags.clear(Kflags::CALL_WAIT_SEIZE);
    callFXO()->_flags.clear(Kflags::WAIT_SEND_DTMF);

    /* if received some disconnect from 'drop collect call'
       feature of some pbx, then leave the call rock and rolling */
    //Board::board(_target.device)->_timers.del(callFXO()->_idx_disconnect);

    bool fax_detected = callFXO()->_flags.check(Kflags::FAX_DETECTED) || (callFXO()->_var_fax_adjust == T_TRUE);

    bool res_out_of_band_dtmf = (call()->_var_dtmf_state == T_UNKNOWN || fax_detected ?
        Opt::_options._suppression_delay() && Opt::_options._out_of_band_dtmfs() && !fax_detected : (call()->_var_dtmf_state == T_TRUE));

    bool res_echo_cancellator = (call()->_var_echo_state == T_UNKNOWN || fax_detected ?
        Opt::_options._echo_canceller() && !fax_detected : (call()->_var_echo_state == T_TRUE));

    bool res_auto_gain_cntrol = (call()->_var_gain_state == T_UNKNOWN || fax_detected ?
        Opt::_options._auto_gain_control() && !fax_detected : (call()->_var_gain_state == T_TRUE));

    if (!call()->_flags.check(Kflags::REALLY_CONNECTED))
    {
        obtainRX(res_out_of_band_dtmf);

        /* esvazia buffers de leitura/escrita */
        cleanupBuffers();

        if (!call()->_flags.check(Kflags::KEEP_DTMF_SUPPRESSION))
            dtmfSuppression(res_out_of_band_dtmf);

        if (!call()->_flags.check(Kflags::KEEP_ECHO_CANCELLATION))
            echoCancellation(res_echo_cancellator);

        if (!call()->_flags.check(Kflags::KEEP_AUTO_GAIN_CONTROL))
            autoGainControl(res_auto_gain_cntrol);

        startListen(false);

        startStream();

        DBG(FUNC, PVT_FMT(_target, "(FXO) Audio callbacks initialized successfully"));
    }

    return KhompPvt::setupConnection();
}
Ejemplo n.º 4
0
bool BoardFXO::KhompPvtFXO::sendDtmf(std::string digit)
{
    if(_transfer->checkUserXferUnlocked(digit))
    {
        DBG(FUNC, PVT_FMT(target(), "started (or waiting for) an user xfer"));
        return true;
    }

    bool ret = KhompPvt::sendDtmf(callFXO()->_digits_buffer);

    callFXO()->_digits_buffer.clear();

    return ret;
}
Ejemplo n.º 5
0
bool BoardFXO::KhompPvtFXO::indicateBusyUnlocked(int cause, bool sent_signaling)
{
    DBG(FUNC, PVT_FMT(_target, "(FXO) c"));

    if(!KhompPvt::indicateBusyUnlocked(cause, sent_signaling))
    {
        DBG(FUNC, PVT_FMT(_target, "(FXO) r (false)"));
        return false;
    }

    if(call()->_flags.check(Kflags::IS_INCOMING))
    {
        /* already connected or sent signaling... */
        mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
        
        if(!call()->_flags.check(Kflags::CONNECTED) && !sent_signaling)
        {
            /* we are talking about branches, not trunks */ 
            command(KHOMP_LOG, CM_CONNECT);
            callFXO()->_busy_disconnect = Board::board(_target.device)->_timers.add(Opt::_options._fxo_busy_disconnection(), &BoardFXO::KhompPvtFXO::busyDisconnect, this);
        }
    }
    else if(call()->_flags.check(Kflags::IS_OUTGOING))
    {
        /* already connected or sent signaling... */
        mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
    }

    DBG(FUNC,PVT_FMT(_target, "(FXO) r"));
    return true; 
}
Ejemplo n.º 6
0
bool BoardFXO::KhompPvtFXO::onSeizeSuccess(K3L_EVENT *e)
{
    DBG(FUNC, PVT_FMT(_target, "(FXO) c"));

    try
    {
        ScopedPvtLock lock(this);

        callFXO()->_flags.clear(Kflags::CALL_WAIT_SEIZE);

    }
    catch (ScopedLockFailed & err)
    {
        LOG(ERROR, PVT_FMT(_target, "(FXO) r (unable to lock %s!)") % err._msg.c_str() );
        return false;
    }

    DBG(FUNC, PVT_FMT(_target, "(FXO) r"));

    return true;
}
Ejemplo n.º 7
0
bool BoardFXO::KhompPvtFXO::onDtmfSendFinish(K3L_EVENT *e)
{
    DBG(FUNC, PVT_FMT(_target, "(FXO) c"));

    bool ret = true;

    try
    {
        ScopedPvtLock lock(this);

        ret = KhompPvt::onDtmfSendFinish(e);

        if (callFXO()->_flags.check(Kflags::EARLY_RINGBACK))
        {
            callFXO()->_flags.clear(Kflags::EARLY_RINGBACK);

            /* start grabbing */
            startListen();

            /* activate resources early... */
            bool fax_detected = callFXO()->_flags.check(Kflags::FAX_DETECTED);

            bool res_out_of_band_dtmf = Opt::_options._suppression_delay() && Opt::_options._out_of_band_dtmfs() && !fax_detected;
            bool res_echo_cancellator = Opt::_options._echo_canceller() && !fax_detected;
            bool res_auto_gain_cntrol = Opt::_options._auto_gain_control() && !fax_detected;

            if (!call()->_flags.check(Kflags::KEEP_DTMF_SUPPRESSION))
                dtmfSuppression(res_out_of_band_dtmf);

            if (!call()->_flags.check(Kflags::KEEP_ECHO_CANCELLATION))
                echoCancellation(res_echo_cancellator);

            if (!call()->_flags.check(Kflags::KEEP_AUTO_GAIN_CONTROL))
                autoGainControl(res_auto_gain_cntrol);

            /* start sending audio if wanted so */
            if (Opt::_options._fxo_send_pre_audio())
                startStream();

            //TODO: Verificar isso aqui
            if (call()->_pre_answer)
            {
                /* tell the user we are answered! */
                switch_channel_mark_answered(getFSChannel());
                //pvt->signal_state(AST_CONTROL_ANSWER);
            }
            else
            {
                /* are we ringing, now? lets try this way! */
                switch_channel_mark_ring_ready(getFSChannel());
                //pvt->signal_state(AST_CONTROL_RINGING);
            }
        }
    }
    catch (ScopedLockFailed & err)
    {
        LOG(ERROR, PVT_FMT(_target, "(FXO) r (unable to lock %s!)") % err._msg.c_str() );
        return false;
    }
    catch(Board::KhompPvt::InvalidSwitchChannel & err)
    {
        LOG(ERROR, PVT_FMT(_target, "(FXO) r (no valid channel: %s)") % err._msg.c_str());
        return false;
    }

    DBG(FUNC, PVT_FMT(_target, "(FXO) r"));

    return ret;
}
Ejemplo n.º 8
0
int BoardFXO::KhompPvtFXO::makeCall(std::string params)
{
    DBG(FUNC,PVT_FMT(_target, "(FXO) c"));

    int ret = ksSuccess;

    /* we always have audio */
    call()->_flags.set(Kflags::HAS_PRE_AUDIO);
    
    if(callFXO()->_call_info_drop == 0 && !callFXO()->_call_info_report)
    {
        command(KHOMP_LOG, CM_DISABLE_CALL_ANSWER_INFO);
    }

    if (!callFXO()->_pre_digits.empty())
    {
        /* Seize the line at local PABX. */

        callFXO()->_flags.set(Kflags::CALL_WAIT_SEIZE);

        if (!command(KHOMP_LOG, CM_SEIZE, call()->_orig_addr.c_str()))
            return ksFail;            

        int timeout = 150;

        if(!loopWhileFlagTimed(Kflags::CALL_WAIT_SEIZE, timeout))
            return ksFail;

        if (callFXO()->_flags.check(Kflags::CALL_WAIT_SEIZE) || (timeout <= 0))
            return ksFail;

        /* Grab line from local PABX. */

        callFXO()->_flags.set(Kflags::WAIT_SEND_DTMF);

        if (!command(KHOMP_LOG, CM_DIAL_DTMF, callFXO()->_pre_digits.c_str()))
            return ksFail;            
        
        if(!loopWhileFlagTimed(Kflags::WAIT_SEND_DTMF, timeout))
            return ksFail;

        if (callFXO()->_flags.check(Kflags::WAIT_SEND_DTMF) || (timeout <= 0))
            return ksFail;

        /* Seize line from public central (works because the     *
        * continuous cadence is always detected by the k3l api. */

        callFXO()->_flags.set(Kflags::CALL_WAIT_SEIZE);

        if (!command(KHOMP_LOG, CM_SEIZE, call()->_orig_addr.c_str()))
            return ksFail;

        if(!loopWhileFlagTimed(Kflags::CALL_WAIT_SEIZE, timeout))
            return ksFail;

        if (callFXO()->_flags.check(Kflags::CALL_WAIT_SEIZE) || (timeout <= 0))
            return ksFail;

        /* we want the audio as soon as dialing ends */
        callFXO()->_flags.set(Kflags::EARLY_RINGBACK);
    
        if (!command(KHOMP_LOG, CM_DIAL_DTMF, call()->_dest_addr.c_str()))
            return ksFail;
    }
    else
    {
        /* we want the audio as soon as dialing ends */
        callFXO()->_flags.set(Kflags::EARLY_RINGBACK);


        if(!call()->_orig_addr.empty())
            params += STG(FMT(" orig_addr=\"%s\"") % _call->_orig_addr);


        ret = KhompPvt::makeCall(params);

        if(ret != ksSuccess)
        {
            LOG(ERROR, PVT_FMT(target(), "Fail on make call"));
        }

        call()->_cleanup_upon_hangup = (ret == ksInvalidParams);
    }

    DBG(FUNC,PVT_FMT(_target, "(FXO) r"));
    return ret;
}
Ejemplo n.º 9
0
bool BoardFXO::KhompPvtFXO::onAudioStatus(K3L_EVENT *e)
{
    DBG(STRM, PVT_FMT(_target, "(FXO) c"));

    try
    {
        //ScopedPvtLock lock(this);

        if(e->AddInfo == kmtFax)
        {
            DBG(STRM, PVT_FMT(_target, "Fax detected"));

            /* hadn't we did this already? */
            bool already_detected = call()->_flags.check(Kflags::FAX_DETECTED);            

            time_t time_was = call()->_call_statistics->_base_time;
            time_t time_now = time(NULL);

            bool detection_timeout = (time_now > (time_was + (time_t) (Opt::_options._fax_adjustment_timeout())));
            
            BEGIN_CONTEXT
            {
                ScopedPvtLock lock(this);

                /* already adjusted? do not adjust again. */
                if (already_detected || detection_timeout)
                    break;

                if (callFXO()->_call_info_drop != 0 || callFXO()->_call_info_report)
                {
                    /* we did not detected fax yet, send answer info! */
                    setAnswerInfo(Board::KhompPvt::CI_FAX);

                    if (callFXO()->_call_info_drop & Board::KhompPvt::CI_FAX)
                    {
                        /* fastest way to force a disconnection */
                        command(KHOMP_LOG,CM_DISCONNECT);//,SCE_HIDE);
                    }
                }

                if (Opt::_options._auto_fax_adjustment())
                {
                    DBG(FUNC, PVT_FMT(_target, "communication will be adjusted for fax!"));
                    _fax->adjustForFax();
                }
            }
            END_CONTEXT

            if (!already_detected)
            {
                ScopedPvtLock lock(this);

                /* adjust the flag */
                call()->_flags.set(Kflags::FAX_DETECTED);
            }
        }
    }
    catch (ScopedLockFailed & err)
    {
        LOG(ERROR, PVT_FMT(_target, "(FXO) r (unable to lock %s!)") % err._msg.c_str() );
        return false;
    }

    bool ret = KhompPvt::onAudioStatus(e);

    DBG(STRM, PVT_FMT(_target, "(FXO) r"));

    return ret;
}