Logo Search packages:      
Sourcecode: bayonne version File versions  Download package

trunk.cpp

// Copyright (C) 2000 Open Source Telecom Corporation.
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Bayonne as noted here.
//
// This exception is that permission is hereby granted to link Bayonne 
// with the Dialogic runtime libraries to produce a executable image
// without requiring Dialogic's sources to be supplied so long as each
// each source file so linked contains this exclusion.
//
// This exception does not however invalidate any other reasons why
// the resulting executable file might be covered by the GNU General
// public license or invalidate the licensing requirements of any
// other component or library.
//
// This exception applies only to the code released by OST under the
// name Bayonne.  If you copy code from other releases into a copy of
// Bayonne, as the General Public License permits, the exception does not
// apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own to Bayonne, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice, at which
// point the terms of your modification would be covered under the GPL
// as explicitly stated in "COPYING".

extern "C" {
#include <sys/poll.h>
};
#include <strstream>
//#include <cc++/xml.h>
#include "driver.h"
#include "possibilite.h"
#include "reroute.h"

#define     EVENT_BUFFER_SIZE 16

#ifdef CCXX_NAMESPACES
namespace ost {
using namespace std;
#endif

char DialogicTrunk::status[600];

DialogicTrunk::DialogicTrunk(int id, devices_t *devif) :
TimerPort(), Trunk(id, 0, devif->span), Thread(0), URLAudio(), AudioService()
{
      TrunkEvent event;
      unsigned long opts;
      CT_DEVINFO ctinfo;
      short wparm;
      char bparm;
      const char *cp;

      trunk = (Trunk *)this;
      handler = NULL;
      join = NULL;
      lastring = 0;
      tsdev = devif->tsdev;
      chdev = devif->chdev;
      linedev = devif->linedev;
      _blocked = true;
      callstate = GCST_NULL;
      crn = -1;

      //if(tsdev > -1)
      //    interface = devif->iface;
      //else
      //    interface = ANALOG;
      interface = ISDN;

      intts.sc_numts = voxts.sc_numts = faxts.sc_numts = 1;
      voxts.sc_tsarrayp = &tsinfo[0];
      intts.sc_tsarrayp = &tsinfo[1];
      faxts.sc_tsarrayp = &tsinfo[2];

      routing = true;
      _waiting = false;
      
      pipe(evbuf);
      opts = fcntl(evbuf[1], F_GETFL);
      fcntl(evbuf[1], F_SETFL, opts | O_NONBLOCK);
      digtpt[0].tp_type = IO_CONT;
      digtpt[0].tp_termno = DX_MAXDTMF;
      digtpt[0].tp_length = 1;
      digtpt[0].tp_flags = TF_MAXDTMF;
      digtpt[1].tp_type = IO_CONT;
      digtpt[1].tp_termno = DX_DIGMASK;
      digtpt[1].tp_flags = TF_DIGMASK;
      digtpt[2].tp_type = IO_CONT;
        digtpt[2].tp_termno = DX_MAXSIL;
        digtpt[2].tp_length = 0;
        digtpt[2].tp_flags = TF_10MS;
        digtpt[3].tp_type = IO_CONT;
        digtpt[3].tp_termno = DX_LCOFF;
        digtpt[3].tp_length = 3;
        digtpt[3].tp_flags = TF_LCOFF | TF_10MS;
        digtpt[4].tp_type = IO_EOT;
        digtpt[4].tp_termno = DX_MAXTIME;
        digtpt[4].tp_flags = TF_MAXTIME | TF_10MS;

      iofile.io_type = IO_DEV | IO_UIO | IO_EOT;
      iofile.io_bufp = 0;
      iofile.io_offset = 0;
      iofile.io_length = -1;
      iofile.io_fhandle = id;
      iofile.io_nextp = NULL;

      iotone.io_type = IO_MEM | IO_EOT;
      iotone.io_offset = 0;
      iotone.io_fhandle = 0;
      iotone.io_nextp = NULL;

      handler = &DialogicTrunk::idleHandler;
      event.id = TRUNK_ENTER_STATE;

      cp = group->getLast("talkoff");
      if(!cp)
            cp = dialogicivr.getTalkback();
      if(cp)
      {
            wparm = atoi(cp);
            if(dx_setparm(chdev, DXCH_DTMFTLK, (void *)&wparm))
                  postError(chdev, "dx_setparm");
      }
      cp = group->getLast("debounce");
      if(!cp)
            cp = dialogicivr.getDebounce();
      if(cp)
      {
            wparm = atoi(cp);
            if(dx_setparm(chdev, DXCH_DTMFDEB, (void *)&wparm))
                  postError(chdev, "dx_setparm");
      }

      cp = group->getLast("winktimer");
      if(cp)
      {
            bparm = atoi(cp) / 10;
            if(dx_setparm(chdev, DXCH_WINKLEN, (void *)&bparm))
                  postError(chdev, "dx_setparm");
      }

      cp = group->getLast("winkdelay");
      if(cp)
      {
            bparm = atoi(cp) / 10;
            if(dx_setparm(chdev, DXCH_WINKDLY, (void *)&bparm))
                  postError(chdev, "dx_setparm");
      }

      cp = group->getLast("minwink");
      if(cp)
      {
            bparm = atoi(cp) / 10;
            if(dx_setparm(chdev, DXCH_MINRWINK, (void *)&bparm))
                  postError(chdev, "dx_setparm");
      }           

      cp = group->getLast("maxwink");
      if(cp)
      {
            bparm = atoi(cp) / 10;
            if(dx_setparm(chdev, DXCH_MAXRWINK, (void *)&bparm))
                  postError(chdev, "dx_setparm");
      }
                        
//    (this->*handler)(&event);
}

DialogicTrunk::~DialogicTrunk()
{
      terminate();
      stopChannel(EV_ASYNC);
      tsRelease();

      if(crn != -1)
      {
            gc_DropCall(crn, GC_NORMAL_CLEARING, EV_SYNC);
            gc_ReleaseCallEx(crn, EV_SYNC);
      }

      if(dialogicivr.getBoardType() == SPRINGWARE)
            if(dx_close(chdev) < 0)
                  postError(chdev, "dx_close");

      ::close(evbuf[0]);
      ::close(evbuf[1]);
}

bool DialogicTrunk::Join(DialogicTrunk *trunk)
{
      int d1, d2, m1, m2;
      unsigned flags = MD_PCM | PM_SR8;
      SC_TSINFO tsinfo1, tsinfo2, rtsinfo;
      long scts1, scts2, arrayp[32];

      if(interface == ANALOG)
      {
            if(!routing)
                  return false;

            d1 = chdev;
            m1 = SC_LSI;
      }
      else
      {
            d1 = tsdev;
            m1 = SC_DTI;
      }
      if(trunk->interface == ANALOG)
      {
            if(!trunk->routing)
                  return false;
            d2 = trunk->chdev;
            m2 = SC_LSI;
      }
      else
      {
            d2 = trunk->tsdev;
            m2 = SC_DTI;
      }
      if(trunk->join)
            return false;

      trunk->enterMutex();
        nr_scroute(d1, m1, d2, m2, SC_FULLDUP);
        join = trunk;
        join->join = this;
      trunk->leaveMutex();
      if(trunk->data.join.recfn)
      {
            switch(getEncoding())
            {
            case mulawAudio:
                  flags = MD_PCM | PM_SR8;
                  break;
            case alawAudio:
                  flags = MD_PCM | PM_ALAW | PM_SR8;
                  break;
            case voxADPCM:
                  flags = MD_ADPCM | PM_SR6;
            default:
                  return false;
            }
            tsinfo1.sc_numts = 1;
            tsinfo1.sc_tsarrayp = &scts1;
            switch(m1)
            {
            case SC_LSI:
                  dx_getxmitslot(d1, &tsinfo1);
                  break;
            case SC_DTI:
                  break;
            }
            tsinfo2.sc_numts = 1;
            tsinfo2.sc_tsarrayp = &scts2;
            switch(m2)
            {
            case SC_LSI:
                  dx_getxmitslot(d2, &tsinfo2);
                  break;
            case SC_DTI:
                  break;
            }
            arrayp[0] = scts1;
            arrayp[1] = scts2;
            rtsinfo.sc_numts = 2;
            rtsinfo.sc_tsarrayp = &arrayp[0];   
            if(dx_recm(chdev, &trunk->iofile, dialogicivr.getPlayTPT(),
                        EV_ASYNC | flags, &rtsinfo) < 0)
                  postError(chdev, "vox");
      }
      return true;
}

bool DialogicTrunk::Listen(DialogicTrunk *trunk)
{
      int d1, d2, m1, m2, v2;

      if(interface == ANALOG)
      {
            if(!routing)
                  return false;

            d1 = chdev;
            m1 = SC_LSI;
      }
      else
      {
            d1 = tsdev;
            m1 = SC_DTI;
      }
      if(trunk->interface == ANALOG)
      {
            if(!trunk->routing)
                  return false;
            v2 = d2 = trunk->chdev;
            m2 = SC_LSI;
      }
      else
      {
            d2 = trunk->tsdev;
            v2 = trunk->chdev;
            m2 = SC_DTI;
      }

      switch(data.join.direction)
      {
            case JOIN_RECV:
                  nr_scroute(d2, m2, d1, m1, SC_HALFDUP);
                  break;
            case JOIN_XMIT:
                  nr_scroute(v2, SC_VOX, d1, m1, SC_HALFDUP);
                  break;
            case JOIN_FULL:
                  return false;
      }

      join = trunk;
      join->join = NULL;
      return true;
}

void DialogicTrunk::Part(void)
{
      TrunkEvent event;
      int d1, d2, m1, m2, v2;

      if(!join)
            return;

      if(interface == ANALOG)
      {
            m1 = SC_LSI;
            d1 = chdev;
      }
      else
      {
            m1 = SC_DTI;
            d1 = tsdev;
      }

      if(join->interface == ANALOG)
      {
            v2 = d2 = join->chdev;
            m2 = SC_LSI;
      }
      else
      {
            d2 = join->tsdev;
            v2 = join->chdev;
            m2 = SC_DTI;
      }

      if(NULL == join->join)
      {
            switch(data.join.direction)
            {
                  case JOIN_RECV:
                        nr_scunroute(d2, m2, d1, m1, SC_HALFDUP);
                        tsConnect();
                        break;
                  case JOIN_XMIT:
                        nr_scunroute(v2, SC_VOX, d1, m1, SC_HALFDUP);
                        tsConnect();
                        break;
                  case JOIN_FULL:
                        break;
            }
      }
      else
      {
            join->enterMutex();
            nr_scunroute(d1, m1, d2, m2, SC_FULLDUP);
            tsConnect();
            join->tsConnect();
            join->join = NULL;
            join->leaveMutex();
            event.id = TRUNK_PART_TRUNKS;
            event.parm.ok = false;
            join->postEvent(&event);
      }
      join = NULL;
}     

void DialogicTrunk::tsRelease(void)
{
      if(interface == ANALOG)
      {
            if(routing)
                  nr_scunroute(chdev, SC_LSI, chdev, SC_VOX, SC_FULLDUP);
      }
      else
            nr_scunroute(tsdev, SC_DTI, chdev, SC_VOX, SC_FULLDUP);
}

void DialogicTrunk::tsConnect(void)
{
      if(interface == ANALOG)
      {
            if(routing)
            {
                  nr_scunroute(chdev, SC_LSI, chdev, SC_VOX, SC_FULLDUP);
                  nr_scroute(chdev, SC_LSI, chdev, SC_VOX, SC_FULLDUP);
            }
      }
      else
      {
            nr_scunroute(tsdev, SC_DTI, chdev, SC_VOX, SC_FULLDUP);
            if(nr_scroute(tsdev, SC_DTI, chdev, SC_VOX, SC_FULLDUP) < 0)
                  slog(Slog::levelError) << "globalcall: scbus routing failed, tsdev=" << tsdev << ", chdev=" << chdev << endl;
      }
}

void DialogicTrunk::run(void)
{
      char buf[EVENT_BUFFER_SIZE];
      TrunkEvent *event = (TrunkEvent *)&buf;
      int timeout;
      struct pollfd pfd;

      Thread::sleep(4000 + 20 * id);
      event->id = TRUNK_ENTER_STATE;
      (this->*handler)(event);

      for(;;)
      {
            enterMutex();
            timeout = TimerPort::getTimer();
            if(!timeout)
            {
                  event->id = TRUNK_TIMER_EXPIRED;
                  TimerPort::endTimer();
                  postEvent(event);
                  leaveMutex();
                  continue;
            }

            leaveMutex();           
            if(timeout > 0)
            {
                  pfd.fd = evbuf[0];
                  pfd.events = POLLIN | POLLRDNORM;
                  if(::poll(&pfd, 1, timeout) < 1)
                  {
                        event->id = TRUNK_TIMER_EXPIRED;
                        postEvent(event);
                        continue;
                  }
            }
            
            if(::read(evbuf[0], &buf, sizeof(buf)) != sizeof(buf))
            {
                  slog(Slog::levelError) << "dx(" << id << "): event failure in read" << endl;
                  continue;
            }
            if(event->id != TRUNK_NULL_EVENT)
                  postEvent(event);
      }
}

void DialogicTrunk::putEvent(TrunkEvent *evt)
{
      char buf[EVENT_BUFFER_SIZE];
      TrunkEvent null;

      if(!evt && isThread())
            return;

      if(!evt)
      {
            null.id = TRUNK_NULL_EVENT;
            evt = &null;
      }     
      memcpy(buf, evt, sizeof(TrunkEvent));
      if(::write(evbuf[1], &buf, sizeof(buf)) != sizeof(buf))
            slog(Slog::levelError) << "dx(" << id << "): event overflow" << endl;
}

bool DialogicTrunk::postEvent(TrunkEvent *event)
{
      bool rtn = true;
      trunkhandler_t prior;

      enterMutex();
      switch(event->id)
      {
      case TRUNK_TIMER_SYNC:
            if(!synctimer)
                  rtn = false;
            synctimer = 0;
            break;
      case TRUNK_TIMER_EXIT:
            if(!exittimer)
                  rtn = false;
            exittimer = 0;
            break;
      case TRUNK_TIMER_EXPIRED:
            if(TimerPort::getTimer() < 0)
                  rtn = false;
            TimerPort::endTimer();
            break;
      case TRUNK_DTMF_KEYUP:
            if(Trunk::flags.offhook)
                  time(&idletime);
            if(!Trunk::flags.dtmf)
                  rtn = false;
            break;
      default:
            break;
      }
      if(!rtn)
      {
            leaveMutex();
            return false;
      }

      if(!handler)
      {
            slog(Slog::levelWarning) << "dx( " << id << ")";
            slog() << ":no handler active; event=" << event->id << endl;
            leaveMutex();
            return false;
      }

retry:
      debug->debugEvent(this, event);
      prior = handler;
      rtn = (this->*handler)(event);
      if(rtn)
      {
            if(handler != prior)
            {
                  event->id = TRUNK_ENTER_STATE;
                  goto retry;
            }
            putEvent(NULL);
            leaveMutex();
            return true;
      }

      rtn = true;
      switch(event->id)
      {
      case TRUNK_MAKE_IDLE:
            handler = &DialogicTrunk::idleHandler;
            break;
      case TRUNK_MAKE_BUSY:
      case TRUNK_MAKE_STANDBY:
            handler = &DialogicTrunk::busyHandler;
            break;
      case TRUNK_STOP_STATE:
            TimerPort::endTimer();
            handler = &DialogicTrunk::stepHandler;
            break;
      case TRUNK_EXIT_STATE:
            break;
      case TRUNK_EXIT_SHELL:
            tgi.pid = 0;
            break;
      case TRUNK_RINGING_ON:
            ++rings;
            break;
      case TRUNK_ENTER_STATE:
            if(Trunk::flags.offhook)
                  Trunk::setDTMFDetect();
            else
                  setDTMFDetect(false);
            TimerPort::endTimer();
            break;
      case TRUNK_LINE_WINK:
            if(!Trunk::flags.offhook)
                  break;
      case TRUNK_CPA_DIALTONE:
      case TRUNK_STOP_DISCONNECT:
      case TRUNK_CALL_FAILURE:
            if(Trunk::flags.onexit)
                  break;
            if(trunkSignal(TRUNK_SIGNAL_HANGUP))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_SEND_MESSAGE:
            if(recvEvent(event))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_TIMER_EXPIRED:
            trunkSignal(TRUNK_SIGNAL_TIMEOUT);
            event->id = TRUNK_STOP_STATE;
            goto retry;
            break;
      case TRUNK_TIMER_SYNC:
            if(trunkSignal(TRUNK_SIGNAL_TIME))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_TIMER_EXIT:
            if(trunkSignal(TRUNK_SIGNAL_TIME))
                  event->id = TRUNK_STOP_STATE;
            else
                  event->id = TRUNK_STOP_DISCONNECT;
            goto retry;
      case TRUNK_CHILD_EXIT:
            if(!ScriptInterp::isActive())
                  break;
            if(trunkSignal(TRUNK_SIGNAL_CHILD))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      case TRUNK_DTMF_KEYUP:
            if(digits < 32)
                  dtmf.bin.data[digits++] = digit[event->parm.dtmf.digit];
            dtmf.bin.data[digits] = 0;
            if(trunkSignal((trunksignal_t)(event->parm.dtmf.digit + TRUNK_SIGNAL_0)))
            {
                  event->id = TRUNK_STOP_STATE;
                  goto retry;
            }
            break;
      default:
            rtn = false;
      }
      if(handler != prior)
      {
            event->id = TRUNK_ENTER_STATE;
            goto retry;
      }
      leaveMutex();     
      putEvent(NULL);
      return rtn;
}

void DialogicTrunk::postError(int dev, const char *msg)
{
      char buffer[33];

      getName(buffer);
      slog(Slog::levelError) << buffer << ": " << msg << " " << ATDV_ERRMSGP(dev) << endl;
}

void DialogicTrunk::postGCError(const char *msg)
{
      char buffer[33];
      int gc_error;
      int cclibid;
      long cc_error;
      char *errormsg;

      getName(buffer);
      gc_ErrorValue(&gc_error, &cclibid, &cc_error);
      gc_ResultMsg(LIBID_GC, (long)gc_error, &errormsg);

      slog(Slog::levelError) << buffer << ": " << msg << " " << gc_error << " " << errormsg << endl;
}

void DialogicTrunk::postGCError2(const char *msg)
{
      char buffer[33];
      int gc_error;
      GC_INFO t_Info;

      getName(buffer);
      gc_error = gc_ErrorInfo(&t_Info);
      if (gc_error == GC_SUCCESS) {
            slog(Slog::levelError) << buffer << ": error retrieved OK " << endl;
            slog(Slog::levelError) << buffer << ": value: " << t_Info.gcValue << " msg: " << t_Info.gcMsg << " add: " << t_Info.additionalInfo << endl;
      } else {
            slog(Slog::levelError) << buffer << ": error retrieved KO " << endl;
      }

}

void DialogicTrunk::exit(void)
{
      if(!Trunk::flags.onexit)
            if(redirect("::exit"))
            {
                  autoloop(false);
                  Trunk::flags.onexit = true;
                  return;
            }

      char buffer[33];
      getName(buffer);
      slog(Slog::levelDebug) << buffer << ": script exiting" << endl;
      handler = &DialogicTrunk::hangupHandler;
}

void DialogicTrunk::getName(char *buffer)
{
      sprintf(buffer, "dx(%0d)", id);
}

unsigned long DialogicTrunk::getIdleTime(void)
{
      time_t now;
      time(&now);
//    if(handler == &DialogicTrunk::idleHandler)
//          return now - idletime;

      return 0;
}

void DialogicTrunk::setDTMFDetect(bool flag)
{
      Trunk::flags.dtmf = flag;

      if(flag)
      {
            if(dialogicivr.getBoardType() == DM3)
            {
                  if(dx_setevtmsk(chdev, DM_DIGITS) < 0)
                        postError(chdev, "dx_setevtmsk");
            }
            else
            {
                  if(dx_setevtmsk(chdev, DM_LCOFF|DM_LCON|DM_DIGITS) < 0)
                        postError(chdev, "dx_setevtmsk");
            }
      }
      else
      {
            if(dialogicivr.getBoardType() == DM3)
            {
                  if(dx_setevtmsk(chdev, DM_DIGOFF) < 0)
                        postError(chdev, "dx_setevtmsk");
            }
            else
            {
                  if(dx_setevtmsk(chdev, DM_LCOFF|DM_LCON|DM_DIGOFF) < 0)
                        postError(chdev, "dx_setevtmsk");
            }
            //dx_clrdigbuf(chdev);
      }
}

bool DialogicTrunk::waitCall(void)
{
      if(gc_WaitCall(linedev, NULL, NULL, -1, EV_ASYNC) == 0)
            return true;
      else
            return false;
}

bool DialogicTrunk::callProgress(int indicator)
{
      char buffer[33];
      int state = -1;
      getName(buffer);
      gc_GetCallState(crn, &state);
      slog(Slog::levelDebug) << buffer << "State:: " << state << endl;

      getName(buffer);
      slog(Slog::levelDebug) << buffer << "CALLPROGRESS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
      slog(Slog::levelDebug) << buffer << "trunk.cpp callProgress: begin" << endl;

      if(gc_CallProgress(crn, indicator) == GC_SUCCESS)
            return true;
      else
            return false;
}

bool DialogicTrunk::acceptCall(void)
{
      if(Trunk::flags.offhook || _accepted)
            return false;

      if(gc_AcceptCall(crn, 0, EV_ASYNC) < 0)
      {
            postGCError("gc_AcceptCall");
            return false;
      }

      _accepted = true;

      return true;
}

bool DialogicTrunk::answerCall(void)
{
      if(Trunk::flags.offhook)
            return false;

      if(gc_AnswerCall(crn, 0, EV_ASYNC) < 0)
      {
            postGCError("gc_AnswerCall");
            return false;
      }

      Trunk::flags.offhook = true;
      return true;
}

bool DialogicTrunk::hangupCall(void)
{
      int cause;

      if(!Trunk::flags.offhook && !_accepted)
            return false;

      _disconnecting = true;

      switch(callstate)
      {
      case GCST_ACCEPTED:
      case GCST_OFFERED:
            cause = GC_CALL_REJECTED;
            break;
      default:
            cause = GC_NORMAL_CLEARING;
      }

      if(crn != -1)
      {
            if(gc_DropCall(crn, cause, EV_ASYNC) < 0)
            {
                  resetChannel();
                  postGCError("gc_DropCall");
                  return false;
            }
      }
      else resetChannel();

      Trunk::flags.offhook = false;
      return true;
}

void DialogicTrunk::releaseCall(void)
{
      _disconnecting = false;

      if(gc_ReleaseCallEx(crn, EV_ASYNC) < 0)
      {
            int state;

            gc_GetCallState(crn, &state);
            slog(Slog::levelDebug) << buffer << "trunk.cpp releaseCall: releasing CRN: " << crn << " FAILED state=" << state << endl;
            postGCError("gc_ReleaseCallEx");
      }
      else slog(Slog::levelDebug) << buffer << "trunk.cpp releaseCall: releasing CRN: " << crn << " OK state=" << state << endl;

      
}

void DialogicTrunk::resetChannel(void)
{
      gc_ResetLineDev(linedev, EV_ASYNC);
}

bool DialogicTrunk::makeCall(char digit[16], int timeout)
{
      char buffer[33];
      
      getName(buffer);
      
      MAKECALL_BLK makecall_blk;
      GC_MAKECALL_BLK gclib_blk;
      int rtn = 0;

      makecall_blk.isdn.BC_xfer_cap=BEAR_CAP_SPEECH;
      makecall_blk.isdn.BC_xfer_mode=ISDN_ITM_CIRCUIT;
      makecall_blk.isdn.BC_xfer_rate=BEAR_RATE_64KBPS;
      //makecall_blk.isdn.facility_coding_value = ISDN_CPN;
      makecall_blk.isdn.facility_coding_value = ISDN_NOTUSED;
      makecall_blk.isdn.destination_number_type = dialogicivr.getNumberType();
      makecall_blk.isdn.destination_number_plan = dialogicivr.getNumberPlan();

      if(data.dialxfer.callingdigit)
      {
            makecall_blk.isdn.origination_number_type = dialogicivr.getNumberType();
            makecall_blk.isdn.origination_number_plan = dialogicivr.getNumberPlan();
            sprintf(makecall_blk.isdn.origination_phone_number,
                  data.dialxfer.callingdigit);
      }
      else
      {
            makecall_blk.isdn.origination_number_type = ISDN_NOTUSED;
            makecall_blk.isdn.origination_number_plan = ISDN_NOTUSED;
            makecall_blk.isdn.origination_sub_number_type = ISDN_NOTUSED;
            makecall_blk.isdn.origination_phone_number[0] = '\0';
      }
      makecall_blk.isdn.facility_feature_service = ISDN_NOTUSED;
      makecall_blk.isdn.usrinfo_layer1_protocol = dialogicivr.getL1Protocol();
      makecall_blk.isdn.usr_rate = ISDN_NOTUSED;
      makecall_blk.isdn.usrinfo_bufp = NULL;
      makecall_blk.isdn.nsfc_bufp = NULL;
      makecall_blk.isdn.destination_sub_number_type = NAT_NUMBER;
      makecall_blk.isdn.destination_sub_phone_number[0] = '\0';
      gclib_blk.gclib = NULL;
      gclib_blk.cclib = (void *)&makecall_blk;

      rtn = gc_MakeCall(linedev, &crn, digit, &gclib_blk, 0, EV_ASYNC);

      if(rtn < 0) crn = -1;
      if(crn <= 0)
      {
            slog(Slog::levelError) << buffer << ": makeCall error: crn <= 0. Going to reset line" << endl;
            gc_ResetLineDev(linedev, EV_ASYNC);
            postGCError2("gc_MakeCall");
            return false;
      }

      if(timeout)
            TimerPort::setTimer(data.dialxfer.timeout + 120 *strlen(data.dialxfer.digit));

      return true;
}

void DialogicTrunk::stopChannel(int mode = EV_ASYNC)
{
      if(dx_stopch(chdev, mode) < 0)
            postError(chdev, "dx_shopch");
}

bool DialogicTrunk::playTone(phTone *tone)
{
      iotone.io_bufp = (char *)tone->getSamples();
      iotone.io_length = tone->getDuration() * 8;
      if(dx_play(chdev, &iotone, dialogicivr.getPlayTPT(),
            EV_ASYNC | MD_PCM | PM_SR8) < 0)
      {
            postError(chdev, "dxplay");
            return false;
      }
      return true;
}

bool DialogicTrunk::playTone(unsigned f1, unsigned f2, int a1, int a2, timeout_t dur)
{
      TN_GEN tone;

      dx_bldtngen(&tone, f1, f2, a1, a2, (short)(dur / 10));

      if(dx_playtone(chdev, &tone, dialogicivr.getPlayTPT(), EV_ASYNC) < 0)
      {
            postError(chdev, "dx_playtone");
            return false;
      }
      return true;
}

bool DialogicTrunk::playAudio(void)
{
      unsigned flags = MD_PCM | PM_SR8;

      switch(getEncoding())
      {
      case mulawAudio:
            flags = MD_PCM | PM_SR8;
            break;
      case alawAudio:
            flags = MD_PCM | PM_ALAW | PM_SR8;
            break;
      case voxADPCM:
            flags = MD_ADPCM | PM_SR6;
            break;
      case pcm16Mono:
            // 16 bit pcm is converted to ulaw in uio.cpp
            flags = MD_PCM | PM_SR8;
            break;
      default:
            return false;
      }

      if(dx_play(chdev, &iofile, dialogicivr.getPlayTPT(), 
            EV_ASYNC | flags) < 0)
      {
            postError(chdev, "dx_play");
            return false;
      }
      return true;
}

bool DialogicTrunk::recordAudio(void)
{
      unsigned flags = MD_PCM | PM_SR8;
      DV_TPT *rectpt = dialogicivr.getRecordTPT();

      frames = 0;

      switch(getEncoding())
      {
      case mulawAudio:
            flags = MD_PCM | PM_SR8;
            break;
      case alawAudio:
            flags = MD_PCM | PM_ALAW | PM_SR8;
            break;
      case voxADPCM:
            flags = MD_ADPCM | PM_SR6;
      default:
            return false;
      }

      if(data.record.silence)
      {
            if(dialogicivr.getBoardType() == DM3)
                  rectpt[0].tp_length = data.record.silence * 10;
            else
                  rectpt[1].tp_length = data.record.silence * 10;
      }
      else
      {
            if(dialogicivr.getBoardType() == DM3)
                  rectpt = NULL;
            else
                  rectpt[1].tp_length = 0;
      }

      if(dx_rec(chdev, &iofile, rectpt, EV_ASYNC | flags) < 0)
      {
            postError(chdev, "dx_rec");
            return false;
      }
      return true;
}

void DialogicTrunk::getCallerId(void)
{
      char cid[GC_ADDRSIZE];

      strcpy((char *)cid, "pstn:");

      if(gc_GetANI(crn, cid + 5) == GC_SUCCESS)
      {
            setConst(SYM_CALLER, (char *)cid);
            setConst(SYM_CLID, (char *)cid + 5);
      }
      if(gc_GetDNIS(crn, cid + 5) == GC_SUCCESS)
      {
            setConst(SYM_DIALED, (char *)cid);
            setConst(SYM_DNID, (char *)cid + 5);
      }


      setConst("session.callednaspos", callednasposs);
      setConst("pstn.callednaspos", callednasposs);
      setConst("pstn.callingnaspos", callingnasposs);
      setConst("pstn.contextepos", contextposs);
      setConst("pstn.retourpos", retourposs);

}

char *DialogicTrunk::getContinuation(void)
{
      char *fn;

      if(data.play.mode == PLAY_MODE_ONE || data.play.mode == PLAY_MODE_TEMP)
            return NULL;

retry:
      fn = getPlayfile();
      if(fn && data.play.mode == PLAY_MODE_ANY)
      {
            if(!canAccess(fn))
                  goto retry;
      }
      return fn; 
}

bool DialogicTrunk::scrJoin(void)
{
      Trunk *trunk = dialogicivr.getTrunkId(getValue(getKeyword("id")));
      const char *mode = getMember();
      const char *cp = getKeyword("record");
 
        if(!trunk)
        {
                Trunk::error("join-no-port");
                return true;
        }                                                                        

      if(!mode)
            mode = "duplex";

      data.join.hangup = false;
      data.join.waiting = NULL;
      data.join.direction = JOIN_FULL;

      if(!stricmp(mode, "receive"))
            data.join.direction = JOIN_RECV;
      else if (!stricmp(mode, "transmit"))
            data.join.direction = JOIN_XMIT;
      else if(!stricmp(mode, "hangup"))
            data.join.hangup = true;

      if(NULL != cp)
      {
            data.join.recfn = (char *)cp;
            data.join.encoding = getKeyword("encoding");
            data.join.annotation = getKeyword("annotation");
            data.join.extension = getKeyword("extension");
            if(!data.join.encoding)
                  data.join.encoding = getDefaultEncoding();
            if(!data.join.extension)
                  data.join.extension = getSymbol(SYM_EXTENSION);
      }
      else
            data.join.recfn = NULL;
      
        mode = getKeyword("count");
        if(mode)
                data.join.count = atoi(mode);
        else
                data.join.count = 0;

        mode = getKeyword("waitTime");
        if(mode)
                data.join.count = getSecTimeout(mode) /
                        keythreads.getResetDelay() + 1;

      data.join.seq = trunk->getSequence();
      data.join.waiting = data.join.trunk = trunk;
      data.join.wakeup = getTimeout("maxTime");
        trunkStep(TRUNK_STEP_JOIN);
        return false;
}

bool DialogicTrunk::scrWait(void)
{
      struct stat ino;
      char *fn;
      char *cp;
      const char *mem = getMember();

      if(NULL != (cp = getKeyword("play")))
      {
            sprintf(data.play.list, cp);
            data.play.list[sizeof(data.play.list) - 1] = 0;
            data.play.name = data.play.list;
            data.play.volume = atoi(getSymbol(SYM_VOLUME));
            data.play.timeout = 0;
            data.play.term = 0;
            data.play.mode = PLAY_MODE_NORMAL;
            data.play.limit = data.play.offset = 0;

            if(*data.play.name)
            {
                  fn = getPlayfile();
                  stat(fn, &ino);
                  URLAudio::close();
                  open(fn);
                  if(!isOpen())
                              slog(Slog::levelError) << buffer << ": " << fn << ": cannot open" << endl;
                  else
                        playAudio();
            }
      }

      if(mem)
      {
            data.join.waiting = NULL;
            data.join.hangup = false;
            if(!stricmp(mem, "parent"))
                  data.join.waiting = dialogicivr.getTrunkId(getSymbol(SYM_PARENT));
            else if(!stricmp(mem, "hangup"))
                  data.join.hangup = true;
      }
      else
      {
            data.join.waiting = NULL;
            data.join.hangup = false;
      }

      data.join.count = 0;
        data.join.trunk = NULL;
        data.join.wakeup = getTimeout("maxTime");
        trunkStep(TRUNK_STEP_JOIN);
        return false;
}
 
bool DialogicTrunk::scrReroute(void)
{
      const char *option = getMember();
      char *forwarddest = NULL;
      char *backwarddest = NULL;
      char *context = NULL;
      char *backcontext = NULL;

      // Parse the arguments
      Line *line = getScript();
      for (unsigned int argc = 0 ; argc < line->argc ; argc++) {
            if (!strcmp(line->args[argc], "=forwarddest")) {

                  forwarddest = line->args[++argc];
                  if (forwarddest[0] == '%') {
                        forwarddest = getContent(forwarddest);
                  }
                  if (strlen(forwarddest) > sizeof(data.reroute.forwarddest) - 1) {
                        forwarddest[sizeof(data.reroute.forwarddest)] = 0;
                  }
                  strcpy(data.reroute.forwarddest, forwarddest);
            }
            if (!strcmp(line->args[argc], "=backwarddest")) {

                  backwarddest = line->args[++argc];
                  if (backwarddest[0] == '%') {
                        backwarddest = getContent(backwarddest);
                  }
                  if (strlen(backwarddest) > sizeof(data.reroute.backwarddest) - 1) {
                        backwarddest[sizeof(data.reroute.backwarddest)] = 0;
                  }
                  strcpy(data.reroute.backwarddest, backwarddest);
            }

            if (!strcmp(line->args[argc], "=context")) {

                  context = line->args[++argc];
                  if (context[0] == '%') {
                        context = getContent(context);
                  }
                  if (strlen(context) > sizeof(data.reroute.context) - 1) {
                        context[sizeof(data.reroute.context)] = 0;
                  }
                  strcpy(data.reroute.context, context);
            }
            if (!strcmp(line->args[argc], "=backcontext")) {

                  backcontext = line->args[++argc];
                  if (backcontext[0] == '%') {
                        backcontext = getContent(backcontext);
                  }
                  if (strlen(backcontext) > sizeof(data.reroute.backcontext) - 1) {
                        backcontext[sizeof(data.reroute.backcontext)] = 0;
                  }
                  strcpy(data.reroute.backcontext, backcontext);
            }
      }

      // Default behavior
      if (!option) {
            strcpy(data.reroute.option, "1");
      }
      else {
            if (strlen(option) > sizeof(data.reroute.option) - 1) {
                  strncpy(data.reroute.option, option, sizeof(data.reroute.option) - 1);
                  data.reroute.option[sizeof(data.reroute.option) - 1] = 0;
            }
            else {
                  strcpy(data.reroute.option, option);
            }
      }
      slog(Slog::levelDebug) << "scrReroute  option = " << data.reroute.option << endl ;
      {
            reroutage_t r;
            unsigned char trameReroutage[128];
            int len, res;
            IE_BLK    ie_blk;
            
            initReroute(&r);

            // Set forward characteristics :

            switch (atoi(data.reroute.option)) {
                  case 1:
                        setType(&r, REROUTAGE_NAS_GTX); 
                        setNumero(&r, PARAM_NUM,  (unsigned char *) data.reroute.forwarddest );
                        break;
                  case 2:
                        setType(&r, REROUTAGE_NAB_GTX); 
                        setNumero(&r, PARAM_NAB,  (unsigned char *) data.reroute.forwarddest );
                        break;
                  case 3:
                        setType(&r, REROUTAGE_ANNUAIRE); 
                        break;
                  case 4:
                        setType(&r, REROUTAGE_NTR_NAS); 
                        break;
                  case 5:
                        setType(&r, REROUTAGE_INDEFINI); 
                        break;
                  case 6:
                        setType(&r, REROUTAGE_NONTRANSPARENT); 
                        break;
                  default :
                        slog(Slog::levelError) << "Unknown forwarding type - switched to default " << endl ;
                        setType(&r, REROUTAGE_NAS_GTX); 
                        break;
            }

            setCascade(&r, 1); 

            if (context)
                  setContexte(&r, PARAM_CONTEXTE_ASCII, (unsigned char *) data.reroute.context);
            if (backcontext)
                  setRetour(&r, (unsigned char *) data.reroute.backcontext);
            if (backwarddest)
                  setNasRetour(&r, (unsigned char *) data.reroute.backwarddest);

            // Build the packet :
            len = makeTrame(&r, trameReroutage);
            ie_blk.length = len + 7;
            memcpy(ie_blk.data, trameReroutage, len + 7);
            slog(Slog::levelDebug) << "Forward to " << data.reroute.forwarddest << " (" << data.reroute.context << ")" << endl ;
            // and send it :
            res = cc_SndMsg(crn,  SndMsg_Facility , &ie_blk);
            if (res != 0)
                  slog(Slog::levelError) << "cc_SndMsg failure : " << res << endl ;
      }

        trunkStep(TRUNK_STEP_REROUTE);
      return false;
}

bool DialogicTrunk::scrConference(void)
{
      const char *option = getMember();
      char *name = NULL;
      char *size = NULL;
      unsigned int sz = 1;
      char *attr = NULL;
      int attributes = MSPA_NULL;
      unsigned int fixed = 0;
      data.conference.option = CONF_UNKNOWN;

      // Analyze the arguments
      Line *line = getScript();
      for (unsigned int argc = 0 ; argc < line->argc ; argc++) {
            if (!strcmp(line->args[argc], "=name")) {

                  // Name of the conference
                  name = line->args[++argc];
                  if (name[0] == '%') {
                        name = getContent(name);
                  }
                  if (strlen(name) > 255) {
                        name[255] = 0;
                  }
            }
            if (!strcmp(line->args[argc], "=size")) {

                  // Number of conferees
                  size = line->args[++argc];
                  if (size[0] == '%') {
                        size = getContent(size);
                  }
                  if (size != NULL) {
                        sz = (unsigned int)atoi(size);
                        if (sz == 0) sz = 1;
                  }
            }
            if (!strcmp(line->args[argc], "=attr")) {

                  // Attributes
                  attr = line->args[++argc];
                  if (attr[0] == '%') {
                        attr = getContent(attr);
                  }
                  if (attr != NULL) {
                        if (strstr(attr, "ro") != NULL) {
                              attributes |= MSPA_RO;
                        }
                        if (strstr(attr, "periodicTone") != NULL) {
                              attributes |= MSPA_TARIFF;
                        }
                        if (strstr(attr, "fixed") != NULL) {
                              fixed = 1;
                        }
                  }
            }
      }

      // Behavior
      if (!option) {
            data.conference.option = CONF_DEFAULT;
            data.conference.size = sz;
            data.conference.attributes = attributes;
            data.conference.fixed = fixed;
      }
      else
      if (!strcmp(option, "enter")) {
            data.conference.option = CONF_ENTER;
            data.conference.size = sz;
            data.conference.attributes = attributes;
            data.conference.fixed = fixed;
      }
      else
      if (!strcmp(option, "leave")) {
            data.conference.option = CONF_LEAVE;
      }
      else
      if (!strcmp(option, "establish")) {
            data.conference.option = CONF_ESTABLISH;
            data.conference.size = sz;
            data.conference.attributes = attributes;
            data.conference.fixed = fixed;
      }
      else
      if (!strcmp(option, "destroy")) {
            data.conference.option = CONF_DESTROY;
      }
      else {
            data.conference.option = CONF_UNKNOWN;
      }
      if (name ==NULL) data.conference.name[0] = 0;
      else strncpy(data.conference.name, name, 255);
        trunkStep(TRUNK_STEP_CONFERENCE);
      return false;
}

#ifdef CCXX_NAMESPACES
};
#endif


Generated by  Doxygen 1.6.0   Back to index