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

trunk.cpp

// Copyright (C) 2000-2001 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.

#include "server.h"
#include <cc++/strchar.h>

#ifdef      HAVE_SSTREAM
#include <sstream>
#else
#include <strstream>
#endif

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

char Trunk::digit[16] = {
      '0', '1', '2', '3',
      '4', '5', '6', '7',
      '8', '9', '*', '#',
      'a', 'b', 'c', 'd'};

Trunk::Trunk(int port, int card, int dspan) :
ScriptInterp((aaScript *)driver, keymemory.getSymbolSize(), keymemory.getPageSize())
{
      int i;
      static char *names[] = {SYM_TIME, SYM_DATE, SYM_DURATION, SYM_COUNT, SYM_RINGS, SYM_STATE};

      driver->setTrunkGroup(port, card, dspan);
      group = driver->getTrunkGroup(port);
      group->enterMutex();
      group->incCapacity();
      member = ++group->members;
      group->leaveMutex();

      ++driver->portCount;

      for(i = 0; i < 10; ++i)
            dialgroup[i] = false;

      flags.dtmf = flags.offhook = flags.reset = false;
      flags.trunk = TRUNK_MODE_INACTIVE;
      flags.dsp = DSP_MODE_INACTIVE;
      flags.script = false;
      flags.ready = false;
      flags.onexit = false;   
      flags.dnd = false;
      id = port;
      span = dspan;
      rings = 0;
      starttime = idletime = synctimer = exittimer = 0;
      thread = NULL;
      script = NULL;
      digits = 0;
#ifdef      XML_SCRIPTS
      altimage = NULL;
      altmodule = NULL;
#endif
      apppath[0] = 0;
      extNumber[0] = 0;
      seq = 0;
      tonetmp = NULL;

      dtmf.bin.id = SYM_DIGITS;
      dtmf.bin.flags.type = NORMAL;
      dtmf.bin.flags.readonly = false;
      dtmf.bin.flags.system = true;
      dtmf.bin.flags.initial = false;
      dtmf.bin.flags.commit = true;
      dtmf.bin.flags.size = MAX_DIGITS;
      dtmf.bin.next = NULL;

      for(i = 0; i < 6; ++i)
      {
            numbers[i].sym.id = names[i];
            numbers[i].sym.flags.type = NORMAL;
            numbers[i].sym.flags.readonly = true;
            numbers[i].sym.flags.system = true;
            numbers[i].sym.flags.initial = false;
            numbers[i].sym.flags.commit = false;
            numbers[i].sym.flags.size = 10;
            numbers[i].sym.next = NULL;
      }
      strcpy(numbers[5].sym.data, "init");
      dtmf.bin.data[0] = 0;
}

00102 bool Trunk::isAdmin(void)
{
      const char *cp = getSymbol(SYM_LOGIN);
      if(!cp)
            return false;

      if(!stricmp(cp, "admin"))
            return true;

      return false;
}

00114 const char *Trunk::getStation(void)
{
      const char *kw = getKeyword("station");
      if(!kw)
            kw = group->getLast("station");

      return kw;
}

00123 void Trunk::setIdle(bool mode)
{
      if(mode)
            ++driver->idleCount;
      else
            --driver->idleCount;
}

00131 phTone *Trunk::getTone(void)
{
      if(data.tone.tone)
            return data.tone.tone;

      if(tonetmp)
            delete tonetmp;

      if(!data.tone.freq2)
            tonetmp = new phTone(NULL, data.tone.duration, data.tone.freq1);
      else
            tonetmp = new phTone(NULL, data.tone.duration, data.tone.freq1, data.tone.freq2);

      data.tone.tone = tonetmp;
      return tonetmp;
}

00148 void Trunk::enterState(const char *state)
{
      snprintf(numbers[5].sym.data, 11, "%s", state);
      debug->debugState(this, (char *)state);
      monitor->monitorState(this, (char *)state);
}     

00155 int Trunk::getDigit(char dig)
{
      int i;

      dig = tolower(dig);
      for(i = 0; i < 16; ++i)
      {
            if(digit[i] == dig)
                  return i;
      }
      return -1;
}

#ifdef      HAVE_TGI
void Trunk::libtts(const char *msg, ttsmode_t mode)
{
      tgicmd_t cmd;
#ifdef      HAVE_SSTREAM
      ostringstream str;
      str.str() = "";
#else
      strstream str(cmd.cmd, sizeof(cmd.cmd));
#endif

      cmd.port = id;
      cmd.mode = TGI_EXEC_AUDIO;
      cmd.cmd[0] = 0;

      str << keyhandlers.getLast("say") << ".tts";
      str << " language=" << getSymbol(SYM_LANGUAGE);
      str << " audio=" << "temp/.tts." << id << ".ul";
      str << " voice=" << getSymbol(SYM_VOICE);
      switch(mode)
      {
      case TTS_GATEWAY_TEXT:
            str << " phrase=" << msg;
            break;
      case TTS_GATEWAY_FILE:
            str << " source=" << msg;
            break;
      }
#ifdef      HAVE_SSTREAM
      snprintf(cmd.cmd, sizeof(cmd.cmd), "%s", str.str().c_str());
#else
      str << ends;
#endif
      ::write(tgipipe[1], &cmd, sizeof(cmd));
}

#endif

00206 bool Trunk::isReady(void)
{
      trunkmode_t trk = flags.trunk;
      if(trk != TRUNK_MODE_INACTIVE)
            return false;

      return flags.ready;
}

00215 void Trunk::setDTMFDetect(void)
{
      Line *line = getScript();
      if(isActive() && line)
      {
            switch(flags.digits)
            {
            case DTMF_MODE_LINE:
                  if(line->method == (Method)&Trunk::scrCollect)
                        setDTMFDetect(true);
                  else
                        setDTMFDetect(getMask() & 0x00000008);
                  break;
            case DTMF_MODE_SCRIPT:
                  if(line->method == (Method)&Trunk::scrCollect)
                        setDTMFDetect(true);
                  else
                        setDTMFDetect(getObject()->mask & 0x8);
                  break;
            case DTMF_MODE_ON:
                  setDTMFDetect(true);
                  break;
            case DTMF_MODE_OFF:
                  setDTMFDetect(false);
            }
      }
      else
            setDTMFDetect(false);
}

00245 bool Trunk::recvEvent(TrunkEvent *event)
{
      Trunk *trk = event->parm.send.src;
      const char *gid = getSymbol(SYM_GID);
      if(!gid)
            return false;

      if(!trk)
      {
            setSymbol(SYM_EVENTID, "server-control");
            setSymbol(SYM_EVENTMSG, event->parm.send.msg);
            return trunkSignal(TRUNK_SIGNAL_EVENT);
      }

      trk->enterMutex();
      if(trk->seq != event->parm.send.seq)
      {
            trk->leaveMutex();
            return false;
      }

      gid = trk->getSymbol(SYM_GID);
      if(!gid)
      {
            trk->leaveMutex();
            return false;
      }
      setSymbol(SYM_EVENTID, gid);
      setSymbol(SYM_EVENTMSG, event->parm.send.msg);

      trk->leaveMutex();
      return trunkSignal(TRUNK_SIGNAL_EVENT);
}

00279 char **Trunk::getInitial(char **args)
{
      char namebuf[sizeof(buffer)];
      char *name;
      args[1] = NULL;

      name = (char *)group->getSchedule(buffer);

      if(!name)
      {
            args[0] = "down::service";
            return args;
      }

      if(strstr(name, "::"))
      {
            args[0] = name;
            return args;
      }

      if(service[0])
      {
            args[0] = service;
            return args;
      }


      if(upflag && !strnicmp(name, "http:", 5))
      {
            snprintf(namebuf, sizeof(namebuf), "href=%s", name);
            strcpy(buffer, namebuf);
            args[0] = "up::load";
            args[1] = buffer;
            args[2] = NULL;
            return args;
      }
      else if(upflag)
      {
            snprintf(namebuf, sizeof(namebuf), "up::%s", name);
            strcpy(buffer, namebuf);
            name = buffer;
      }

      args[0] = name;
      args[1] = NULL;
      return args;
}

00327 void Trunk::setList(char **list)
{
      char buffer[256];
      char *tok, *key, *value;

      while(*list)
      {
            strcpy(buffer, *list);
            key = strtok_r(buffer, "=", &tok);
            value = strtok_r(NULL, "=", &tok);
            if(key && value)
            {
                  if(!strnicmp(key, "server.", 7))
                        key = NULL;
                  else if(!stricmp(key, SYM_LOGIN))
                        key = NULL;
                  else if(!strnicmp(key, "driver.", 7))
                        key = NULL;
                  else if(!strnicmp(key, "user.", 5))
                        key = NULL;  
                  else if(!strnicmp(key, "line.", 5))
                        key = NULL;
                  else if(!strnicmp(key, "sql.", 4))
                        key = NULL;
                  else if(!strnicmp(key, "global.", 7))
                        key = NULL;
                  else if(!strnicmp(key, "rpc.", 4))
                        key = NULL;
            }
            if(key && value) 
                  setConst(key, urlDecode(value));
            ++list;
      }
}

00362 void Trunk::commit(Symbol *sym)
{
      const char *gid;

      if(!stricmp(sym->id, "rpc.status"))
      {
            gid = getSymbol(SYM_GID);
            if(!gid)
                  return;
            gid = strchr(gid, '-');
            if(gid)
                  ++gid;
            else
                  return;
            rpclog.setInfo(gid, sym->data);
      }
      else if(sym == &dtmf.bin)
            digits = strlen(dtmf.bin.data);
      else
            ScriptSymbol::commit(sym);
}

00384 void Trunk::repSymbol(const char *id, const char *data)
{
      if(data)
            setSymbol(id, data);
}

#ifndef     SCRIPT_SG_VARIABLES

00392 bool Trunk::setVariable(const char *id, int size, const char *value)
{
        Symbol *sym;
        long val;

      if(!id)
            return false;

      if(*id == '%' || *id == '&')
            ++id;

        if(!size)
                size = getSymbolSize();

        if(strchr(id, '.'))
                sym = getEntry(id, size);
        else
                sym = getLocal(id, size);

        if(!sym)
                return false;

        if(!value)
                return true;

        switch(sym->flags.type)
        {
        case SEQUENCE:
        case CACHE:
        case FIFO:
        case STACK:
                return postSymbol(sym, value);
        case COUNTER:
                val = atoi(value);
                snprintf(sym->data, sym->flags.size + 1, "%ld", --val);
                break;
        default:
                strncpy(sym->data, value, sym->flags.size);
                sym->data[sym->flags.size] = 0;
        }
      sym->flags.initial = false;
        if(sym->flags.commit)
                commit(sym);

        return true;
}

00439 const char *Trunk::getVariable(const char *id)
{
        Symbol *sym;

        if(!id)
                return NULL;

        if(*id == '&' || *id == '&')
                ++id;

        if(strchr(id, '.'))
                sym = getEntry(id, 0);
        else
                sym = getLocal(id, 0);

        if(!sym)
                return NULL;

        if(sym->flags.initial)
                return NULL;

        return readSymbol(sym);
}


#endif

00466 Script::Symbol *Trunk::getEntry(const char *name, int size)
{
      int i;
      time_t now;
      struct tm *dt;
      struct tm tbuf;
      Module *mod = Module::symFirst;
      Script::Symbol *sym;
      char buf[128];
      char *login;

      if(*name == '%')  // bug in interp
            ++name;

        if(!strnicmp(name, "global.", 7))
                return globals.getEntry(name, size);
      else if(!strnicmp(name, "server.", 7))
            return globals.getEntry(name, 0); 
      else if(!strnicmp(name, "line.", 5))
      {
            snprintf(buf, sizeof(buf), "line.%d.%s", id, name + 5);
            sym = globals.getEntry(buf, 0);
            if(!sym)
            {
                  snprintf(buf, sizeof(buf), "line.default.%s", name + 5);
                  sym = globals.getEntry(buf, 0);
            }
            return sym;
      }            
      else if(!strnicmp(name, "user.", 5))
      {
            login = getSymbol(SYM_LOGIN);
            if(!strnicmp(name, "user.password", 13))
            {
                  if(!isUser(login))
                        return globals.getEntry("password.nobody");

                  snprintf(buf, sizeof(buf), "%s.password", login);
                  sym = globals.getEntry(buf, 0);
                  if(!sym)
                        return globals.getEntry("password.new");
                  if(!stricmp(sym->data, "new"))
                        return globals.getEntry("password.new");
                  if(sym->flags.initial)
                        return globals.getEntry("password.new");
                  if(!sym->data[0] || !stricmp(sym->data, "none"))
                        return globals.getEntry("password.none");
                  return globals.getEntry("password.set");
            } 
            if(!isUser(login))
                  return NULL;

            if(!stricmp(login, "none"))
                  return NULL;

            snprintf(buf, sizeof(buf), "%s.%s", login, name + 5);
            sym = globals.getEntry(buf, size);
            if(!sym || sym->flags.initial)
            {
                  snprintf(buf, sizeof(buf), "default.%s", name + 5);
                  sym = globals.getEntry(buf, size);
            }
            return sym;
      } 

      while(mod)
      {
            sym = mod->getSymbol(this, name, size);
            if(sym)
                  return sym;
            mod = mod->symNext;
      }

      if(!stricmp(name, SYM_DIGITS))
      {
            dtmf.bin.data[digits] = 0;
            return &dtmf.bin;
      }

      for(i = 0; i < 6; ++i)
      {
            if(!stricmp(name, numbers[i].sym.id))
                  break;
      }

      if(i >= 5)
            return ScriptSymbol::getEntry(name, size);

      if(i < 3)
            time(&now);
      
      switch(i)
      {
      case 4:
            sprintf(numbers[4].sym.data, "%d", rings);
            break;
      case 3:
            sprintf(numbers[3].sym.data, "%d", digits);
            break;
      case 2:
            if(starttime)
                  sprintf(numbers[2].sym.data, "%ld", now - starttime);
            else
                  numbers[2].sym.data[0] = 0;
            break;
      case 1:
            dt = localtime_r(&now, &tbuf);
            sprintf(numbers[1].sym.data, "%04d%02d%02d",
                  dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday);
            break;
      case 0:
            dt = localtime_r(&now, &tbuf);
            sprintf(numbers[0].sym.data, "%02d%02d%02d",
                  dt->tm_hour, dt->tm_min, dt->tm_sec);
      }

      return &numbers[i].sym;
}

00585 bool Trunk::attach(const char *name)
{
      char buf[65];
      class Module *mod;
      time_t now;
      struct tm *dt;
      struct tm tbuf;
      char buffer[33];
      char *index[128];
      char **pol = index;
      const char *xml;
      char *pid;
      trunkmode_t trk = flags.trunk;
      Trunk *parent = NULL;
      TrunkEvent event;
      const char *args[2];
      char *e;
      const char *login;
      Symbol *sym;
      

      // This concerns me.  Why are we returning false?
      // What, in fact, is this case?

      // Since we just set TRUNK_MODE_OUTGOING, in our parent
      // stack frame, I'll kill the flags.script case if we
      // are outbound scheduled.

      //Matt B

      if(!running)
            return false;

      cdrv = NULL;
      getName(buffer);
//    slog(Slog::levelDebug) << buffer << ": low water mark at attach; " << getPages() << endl;


      if(trk != TRUNK_MODE_OUTGOING) 
      {
          if(flags.script)
              return false;
      }

      flags.reset = flags.dtmf = flags.offhook = flags.once = flags.onexit = false;
      tgi.pid = 0;
      flags.digits = DTMF_MODE_LINE;
      autoloop(true);

      pid = getSymbol(SYM_PARENT);
      if(pid)
            parent = driver->getTrunkId(pid);
#ifdef      XML_SCRIPTS
      if(!altimage) {

            mod = NULL;
            xml = group->getLast("xml");
            if(!xml)
                  xml = keyhandlers.getLast("xml");
            if(xml)
                  mod = getModule(MODULE_XML, xml);
 
            if(mod)
            {
                  altimage = mod->getXML();
                  altmodule = mod;
            }
      }

      if(strchr(name, '/') && altimage) {
            args[0] = name;
            args[1] = NULL;
            altimage->getCompile("#");
            altimage->addCompile(0, "load", args);
            altimage->addCompile(0, "hangup", NULL);
            altimage->putCompile(altimage->main);
            name = "#";
      }
#endif

      if(!ScriptInterp::attach(name))
      {
            if(parent)
            {
                  event.id = TRUNK_CHILD_FAIL;
                  parent->postEvent(&event);
            }
            return false;
      }

      ScriptImage *img = getImage();

      flags.script = true;

      setSymbol(SYM_TONE, 16);
      setSymbol(SYM_ANNOTATION, 160);
      setSymbol(SYM_PLAYED, 12);
      setSymbol(SYM_RECORDED, 12);
      setSymbol(SYM_OFFSET, 12);
      setSymbol(SYM_CREATED, 20);
      setSymbol(SYM_LOCKFILE, 64);

      setSymbol(SYM_HOME, 64);
      setSymbol(SYM_HOME, "");
      setSymbol(SYM_ERROR, 64);
      setSymbol(SYM_ERROR, "none");

      setSymbol(SYM_EVENTID, 32);
      setSymbol(SYM_EVENTMSG, 64);

      setSymbol(SYM_EXTENSION, 8);
      setSymbol(SYM_EXTENSION, img->getLast("extension"));

      setSymbol(SYM_FORMAT, 8);
      setSymbol(SYM_FORMAT, getDefaultEncoding());

      setSymbol(SYM_PLAYWAIT, 3);
      setSymbol(SYM_PLAYWAIT, keyhandlers.getLast("timeout"));
      
      setSymbol(SYM_TRIM, 8);
      setSymbol(SYM_TRIM, "1200");

      setSymbol(SYM_BASE, 160);
      setSymbol(SYM_BASE, "http://localhost/");

      setSymbol(SYM_LANGUAGE, 16);
      e = getenv("BAYONNE_LANGUAGE");
      if(e)
            setSymbol(SYM_LANGUAGE, e);
      else
            setSymbol(SYM_LANGUAGE, img->getLast("language"));
      repSymbol(SYM_LANGUAGE, group->getLast("language"));

      setSymbol(SYM_VOICE, 16);
      e = getenv("BAYONNE_VOICE");
      if(e)
            setSymbol(SYM_VOICE, e);
      else
            setSymbol(SYM_VOICE, img->getLast("voice"));
      repSymbol(SYM_VOICE, group->getLast("voice"));

      setSymbol(SYM_APPL, 16);
      setSymbol(SYM_APPL, img->getLast("application"));
      repSymbol(SYM_APPL, group->getLast("application"));

      setSymbol(SYM_VOLUME, 3);
      setSymbol(SYM_VOLUME, group->getLast("volume"));

      setSymbol(SYM_BUFFER, 8);
      setSymbol(SYM_BUFFER, "8000");

      setConst(SYM_NAME, "UNKNOWN");
      setConst(SYM_CALLER, "UNKNOWN");
      setConst(SYM_DIALED,  group->getNumber());
      setConst(SYM_INFODIGITS, "00");
      setConst(SYM_CLID, "UNKNOWN");
      setConst(SYM_DNID, "UNKNOWN");

      setSymbol(SYM_LOGIN, 16);

      if(extNumber[0])
      {
            setConst(SYM_EXTNUMBER, extNumber);
            setSymbol(SYM_LOGIN, extNumber);
      }
      else
      {
            login = keyserver.getLogin();
            if(!stricmp(login, "none") || !stricmp(login, "admin"))
                  setSymbol(SYM_LOGIN, login);
            else if(!stricmp(login, "port"))
            {
                  snprintf(buf, 4, "%03d", id);
                  setSymbol(SYM_LOGIN, buf);
            }
            else
                  setSymbol(SYM_LOGIN, "none");
      }

      sym = getEntry(SYM_LOGIN, 0);
      sym->flags.readonly = true;

      initSyms();

      sprintf(buf, "%03d", id);
      setConst(SYM_ID, buf);
      setConst(SYM_TRUNKID, buf);

//    sprintf(buf, "%d", driver->getTrunkCount());
//    setConst(SYM_PORTS, buf);

      time(&now);

      sprintf(buf, "%s-%03d-%010ld", keyserver.getNode(), id, now);
      setConst(SYM_GID, buf);
      setConst(SYM_CALLFWD, "none");
      setSymbol(SYM_JOINID, 16);
      setSymbol(SYM_PICKUP, 16);
      setSymbol(SYM_RECALL, 16);
      setSymbol(SYM_TRANSFER, 16);
      setSymbol(SYM_TRUNK, 16);
      setSymbol(SYM_INTERCOM, 16);
      switch(flags.trunk)
      {
      case TRUNK_MODE_INCOMING:
            setConst(SYM_CALLTYPE, "incoming");
            break;
      case TRUNK_MODE_OUTGOING:
            setConst(SYM_CALLTYPE, "outgoing");
      }

      if(parent)
      {
            event.id = TRUNK_CHILD_START;
            event.parm.trunk = this;
            parent->postEvent(&event);
      }

      if(span)
      {
            sprintf(buf, "%d", span);
            setConst(SYM_SPAN, buf);
      }

      dt = localtime_r(&now, &tbuf);
      sprintf(buf, "%04d%02d%02d",
            dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday);
      setConst(SYM_STARTDATE, buf);
      sprintf(buf, "%02d%02d%02d",
            dt->tm_hour, dt->tm_min, dt->tm_sec);
      setConst(SYM_STARTTIME, buf);

//    setConst(SYM_RELEASE, "1");
//    setConst(SYM_VERSION, cmd->getLast("version"));
//    setConst(SYM_SERVER, cmd->getLast("server"));
//    setConst(SYM_DRIVER, plugins.getDriverName());
//    setConst(SYM_NODE, cmd->getLast("node"));
      setConst(SYM_START, name);
//    setConst(SYM_SCRIPTS, keypaths.getScriptFiles());
//    setConst(SYM_PROMPTS, keypaths.getPromptFiles());

      sprintf(buf, "%d", member);
      setConst(SYM_MEMBER, buf);

      group->getIndex(index, 127);
      while(*pol)
      {
            sprintf(buf, "policy.%s", *pol);
            setConst(buf, group->getLast(*pol));
            ++pol;
      }

      application.getIndex(index, 127);
      pol = index;
      while(*pol)
      {
            sprintf(buf, "application.%s", *pol);
            setSymbol(buf, group->getLast(*pol));
            ++pol;
      }

      attachModules(this);
      cdrc = 0;
      if(!starttime)
      {
            time(&starttime);
            time(&idletime);
            idle_timer = group->getIdleTime();
      }

      debug->debugState(this, "attach script");
      return true;
}

00859 void Trunk::detach(void)
{
      Trunk *child = NULL;
      TrunkEvent event;
      char buffer[256];
      char overflow[256];
      int i = 0;
      char *val, *tag, *gid;
      unsigned len = 0;

      if(!flags.script || !running)
            return;

      if(tonetmp)
            delete tonetmp;

      tonetmp = NULL;

      ++seq;
      getName(buffer);
//    slog(Slog::levelDebug) << buffer << ": hi water mark at detach; " << getPages() << endl;
      buffer[0] = 0;
      if(cdrv)
      {
            while(i < cdrv->argc && len < sizeof(buffer))
            {
                  tag = cdrv->args[i++];
                  if(*tag == '=')
                        val = getContent(cdrv->args[i++]);
                  else if(*tag == '%')
                        val = getContent(tag);
                  else
                        continue;

                  if(!val)
                        continue;

                  if(!*val)
                        continue;

                  urlEncode(val, overflow, sizeof(overflow));
                  if(len)
                        buffer[len++] = ' ';
                  strncpy(buffer + len, ++tag, sizeof(buffer) - len - 1);
                  len += strlen(tag);
                  buffer[len++] = '=';
                  strncpy(buffer + len, overflow, sizeof(buffer) - len);
                  len = strlen(buffer);
                  buffer[sizeof(buffer) - 1] = 0;
            }
            audit(this, buffer);
      }

      cdrv = NULL;

      tag = getSymbol(SYM_PARENT);
      if(tag)
            child = driver->getTrunkId(tag);

      if(child)
      {
            event.id = TRUNK_CHILD_EXIT;
            child->postEvent(&event);
      }

      gid = getSymbol(SYM_GID);
      if(gid)
            gid = strchr(gid, '-');
      
      if(gid)
            rpclog.stop(++gid);

      dtmf.bin.data[0] = 0;
      digits = 0;
      cdrc = 0;
      ScriptInterp::detach();
      detachModules(this);
      ScriptSymbol::purge();
      starttime = 0;
      flags.script = false;
      flags.onexit = false;
      if(tgi.pid)
            kill(tgi.pid, SIGHUP);
      tgi.pid = 0;

      if(tonetmp)
      {
            delete tonetmp;
            tonetmp = NULL;
      }

#ifdef      XML_SCRIPTS
      if(altimage)
            altimage->purge();
#endif
      debug->debugState(this, "detach script");
}

00957 void Trunk::stopServices(void)
{
      if(thread)
      {
            if(thread->isExiting())
                  delete thread;
      }
      thread = NULL;
}

00967 const char *Trunk::getPrefixPath(void)
{
      const char *prefix = getMember();

        if(!prefix)
                prefix = "";

        if(!stricmp(prefix, "feed"))
                prefix = "memory";
        else
                prefix = getKeyword("prefix");

        if(!prefix)
                return prefix;

        if(!stricmp(prefix, "memory"))
                return keypaths.getLast("tmpfs");
        return prefix;
}

00987 const char *Trunk::getExtReference(const char *ref)
{
      const char *cp = strchr(ref, '-');
      Trunk *trunk;

      if(!cp)
            return ref;

      trunk = driver->getTrunkPort(atoi(++cp));
      if(!trunk)
            return NULL;

      if(!trunk->extNumber[0])
            return NULL;

      return trunk->extNumber;
}

01005 timeout_t Trunk::getTimeout(const char *keywd)
{
      ScriptImage *img = getImage();
      if(keywd)
            keywd = getKeyword(keywd);
      if(!keywd)
            keywd = getValue("86400");
      return getSecTimeout(keywd);
}

01015 timeout_t Trunk::getInterdigit(const char *keywd)
{
      ScriptImage *img = getImage();

      if(keywd)
            keywd = getKeyword(keywd);
      if(!keywd)
            keywd = getValue(img->getLast("interdigit"));
      return getSecTimeout(keywd);
}

01026 unsigned short Trunk::getDigitMask(const char *cp)
{
      static char *digits = "0123456789*#abcd";
      unsigned short mask = 0;
      const char *dp;

      if(cp)
            cp = getKeyword(cp);

      if(!cp)
            cp = getValue(NULL);

      if(!cp)
            return 0;
      
      while(*cp)
      {
            dp = strchr(digits, tolower(*cp));
            ++cp;
            if(dp)
                  mask |= (1 << (int)(dp - digits));
      }
      return mask;
}

01051 bool Trunk::trunkSignal(trunksignal_t signal)
{
      Line *line;

      if(!isActive())
            return false;

      if(signal == TRUNK_SIGNAL_HANGUP)
      {
            if(flags.onexit)
                  return false;
      }

      if(!signal)
      {
            advance();
            return true;
      }

      if(signal == TRUNK_SIGNAL_GOTO)
      {
            line = getScript();
            if(line->argc)
                        scrGoto();
            else
                  advance();
            return true;
      }

      if(ScriptInterp::signal((unsigned long)(signal) - 1))
      {
            line = getScript();
            if(signal == TRUNK_SIGNAL_HANGUP)
            {
                  autoloop(false);
                  if(line)
                        flags.onexit = true;
            }
            if(line)
                  if(line->method == (Method)&Trunk::scrRedirect)
                        (this->*(line->method))();
            return true;
      }

      return false;
}

01098 bool Trunk::idleHangup(void)
{
      time_t now;

      if(!idle_timer)
            return false;

      time(&now);
      if(now - idletime > idle_timer)
      {
            exit();
            return true;
      }
      return false;
}

timeout_t getMSTimeout(const char *opt)
{
        char *end;
        char decbuf[4];
        long value;
        unsigned len;

        if(!opt)
                opt = "0";

        value = strtol(opt, &end, 10) * 1000;
        if(*end == '.')
        {
                strncpy(decbuf, ++end, 3);
                decbuf[4] = 0;
                len = strlen(decbuf);
                while(len < 3)
                        decbuf[len++] = '0';
                value += strtol(decbuf, &end, 10);
        }


        switch(*end)
        {
        case 'h':
        case 'H':
                return value * 3600;
        case 'm':
        case 'M':
                if(end[1] == 's' || end[1] == 'S')
                        return value / 1000;
                return value * 60;
        default:
                return value / 1000;
        }
}
            
timeout_t getSecTimeout(const char *opt)
{
      char *end;
      char decbuf[4];
      long value;
      unsigned len;

      if(!opt)
            opt = "0";

      value = strtol(opt, &end, 10) * 1000;
      if(*end == '.')
      {
            strncpy(decbuf, ++end, 3);
            decbuf[4] = 0;
            len = strlen(decbuf);
            while(len < 3)
                  decbuf[len++] = '0';
            value += atol(decbuf);
      }

      switch(*end)
      {
      case 'h':
      case 'H':
            return value * 3600;
      case 'm':
      case 'M':
            if(end[1] == 's' || end[1] == 'S')
                  return value / 1000;
            return value * 60;
      default:
            return value;
      }                       
}

bool getLogical(const char *str)
{
      if(*str == '.')
            ++str;
      switch(*str)
      {
      case '0':
      case 'f':
      case 'F':
      case 'N':
      case 'n':
            return false;
      }
      return true;
}

#ifdef      XML_SCRIPTS
Script::Name *Trunk::getScriptImage(const char *name)
{
      if(*name == '#')
      {
            if(!altimage)
                  return NULL;
            return altimage->getScript(name);
      }
      return ScriptInterp::getScriptImage(name);
}
#endif

#ifdef      SCRIPT_IF_OVERRIDE

bool Trunk::ifFeature(ScriptInterp *interp, const char *v)
{
      if(!stricmp(v, "join") && (driver->getCaps() & Driver::capJoin))
            return true;

      if(!stricmp(v, "switch") && (driver->getCaps() & Driver::capSwitch))
            return true;

      if(!stricmp(v, "spans") && (driver->getCaps() & Driver::capSpans))
            return true;

      if(!stricmp(v, "speed") && (driver->getCaps() & Driver::capSpeed))
            return true;

      if(!stricmp(v, "gain") && (driver->getCaps() & Driver::capGain))
            return true;

      if(!stricmp(v, "pitch") && (driver->getCaps() & Driver::capPitch))
            return true;

      if(!stricmp(v, "tts") && hasTTS())
            return true;

#ifdef      HAVE_TGI
      if(!stricmp(v, "tgi"))
            return true;
#else
      if(!stricmp(v, "tgi"))
            return false;
#endif

      if(!stricmp(v, "say") && tts)
            return true;

      if(!strnicmp(v, "conf", 4) && (driver->getCaps() & Driver::capConference))
            return true;

      if(!stricmp(v, "voice") && (((Trunk *)(interp))->getCapabilities() & TRUNK_CAP_VOICE))
            return true;

        if(!stricmp(v, "dial") && (((Trunk *)(interp))->getCapabilities() & TRUNK_CAP_DIAL))
                return true;

        if(!stricmp(v, "fax") && (((Trunk *)(interp))->getCapabilities() & (TRUNK_CAP_SENDFAX|TRUNK_CAP_RECVFAX)))
                return true;

        if(!stricmp(v, "data") && (((Trunk *)(interp))->getCapabilities() & TRUNK_CAP_DATA))
                return true;

        if(!stricmp(v, "station") && (((Trunk *)(interp))->getCapabilities() & TRUNK_CAP_STATION))
                return true;

      if(!stricmp(v, "reroute") && (driver->getCaps() & Driver::capReroute))
               return true;


      return false;
}

bool Trunk::ifDTMF(ScriptInterp *interp, const char *v)
{
      if(!stricmp(v, "line") && ((Trunk *)(interp))->flags.digits == DTMF_MODE_LINE)
            return true;

      if(!stricmp(v, "script") && ((Trunk *)(interp))->flags.digits == DTMF_MODE_SCRIPT)
            return true;

      if(!stricmp(v, "on") && ((Trunk *)(interp))->flags.digits == DTMF_MODE_ON)
            return true;

      if(!stricmp(v, "off") && ((Trunk *)(interp))->flags.digits == DTMF_MODE_OFF)
            return true;

      return false;
}

bool Trunk::isActiveUser(ScriptInterp *interp, const char *v)
{
      char namebuf[65];
      Symbol *sym;

      snprintf(namebuf, sizeof(namebuf), "%s.password", v);
      sym = globals.getEntry(namebuf, 0);

      if(!sym)
            return false;

      if(!sym->flags.initial)
            return false;

      return true;
}

bool Trunk::isHunt(ScriptInterp *interp, const char *v)
{
      char namebuf[65];

      snprintf(namebuf, sizeof(namebuf), "hunt.%s.id", v);
      if(globals.getSymbol(namebuf))
            return true;

      return false;
}

bool Trunk::isVirtual(ScriptInterp *interp, const char *v)
{
      char namebuf[33];
      Symbol *sym;

      v = getExtReference(v);

      if(!v)
            return false;

      if(!isExtension(interp, v))
            return false;

      snprintf(namebuf, sizeof(namebuf), "%s.type", v);
      sym = globals.getEntry(namebuf, 0);
      if(!sym)
            return false;

      if(!stricmp(sym->data, "virtual"))
            return true;

      return false;
}

bool Trunk::isStation(ScriptInterp *interp, const char *v)
{
        char namebuf[33];
        Symbol *sym;

        v = getExtReference(v);

        if(!v)
                return false;

        if(!isExtension(interp, v))
                return false;

        snprintf(namebuf, sizeof(namebuf), "%s.type", v);
        sym = globals.getEntry(namebuf, 0);
        if(!sym)
                return false;

        if(!stricmp(sym->data, "station"))
                return true;

        return false;
}


bool Trunk::isExtension(ScriptInterp *interp, const char *v)
{
      Trunk *trunk;

      v = getExtReference(v);
      
      if(!v)
            return false;

      trunk = driver->getExtNumber(v);
      if(!trunk)
            return false;

      return true;
}     

bool Trunk::isDnd(ScriptInterp *interp, const char *v)
{
        Trunk *trunk;

        v = getExtReference(v);

        if(!v)
                return false;

        trunk = driver->getExtNumber(v);
        if(!trunk)
                return false;

        return trunk->flags.dnd;
}

bool Trunk::isService(ScriptInterp *interp, const char *v)
{
      const char *svc;

      if(!stricmp(v, "up") && !service[0])
            return true;

      if(!service[0])
            return false;

        if(!stricmp(v, "test"))
        {
                if(!strnicmp(service, "test::", 6))
                        return true;
        }

        if(!strnicmp(service, "test::", 6))
                return false;


      if(!stricmp(v, "down"))
            return true;

            if(strchr(service, ':'))
                svc += 2;
        else
                svc = service;

        if(!stricmp(v, svc))
                return true;

        return false;
}

bool Trunk::isNode(ScriptInterp *interp, const char *v)
{
      const char *node = keyserver.getNode();
      if(!node)
            return false;

      if(!stricmp(node, v))
            return true;

      return false;
}

bool Trunk::hasGroup(ScriptInterp *interp, const char *v)
{
      if(getGroup(v))
            return true;

      return false;
}

bool Trunk::hasPlugin(ScriptInterp *interp, const char *v)
{
      if(getModule(MODULE_ANY, v))
            return true;

      return false;
}

bool Trunk::hasVoice(ScriptInterp *interp, const char *v)
{
      const char *prompts = keypaths.getLast("prompts");
      char buf[256];

      snprintf(buf, sizeof(buf), "%s/%s", prompts, v);
      if(isDir(buf))
            return true;

      return false;
}

bool Trunk::hasSysVoice(ScriptInterp *interp, const char *v)
{
        const char *prompts = keypaths.getLast("prompts");
        char buf[256];

        snprintf(buf, sizeof(buf), "%s/sys/%s", prompts, v);
        if(isDir(buf))
                return true;

        return false;
}

bool Trunk::hasAltVoice(ScriptInterp *interp, const char *v)
{
        const char *prompts = keypaths.getLast("altprompts");
        char buf[256];

      if(!prompts)
            prompts = keyserver.getPrefix();

        snprintf(buf, sizeof(buf), "%s/%s", prompts, v);
        if(isDir(buf))
                return true;

        return false;
}

bool Trunk::hasAppVoice(ScriptInterp *interp, const char *v)
{
        const char *prompts = keypaths.getLast("prompts");
      Name *scr = interp->getObject();
      char *cp;
        char buf[256];
      char name[65];

      snprintf(name, sizeof(name), "%s", scr->name);
      cp = strchr(name, ':');
      if(cp)
            *cp = 0;

        snprintf(buf, sizeof(buf), "%s/%s/%s", prompts, v, name);
        if(isDir(buf))
                return true;

        return false;
}


#endif

#ifdef      CCXX_NAMESPACES
};
#endif

Generated by  Doxygen 1.6.0   Back to index