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

dcb.cpp

// Copyright (C) 2000 Open Source Telecom Corporation + Etoile Diese
//  
// 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".

#include "driver.h"

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

DialogicDCB *DialogicDCB::first = NULL;
unsigned DialogicDCB::max = 0;
DialogicConf *DialogicConf::first = NULL;
Mutex *DialogicDCB::mut = NULL;

DialogicDCB::DialogicDCB(const char *name, unsigned size)
{
      next = first;
      first = this;
      count = size;
      used = 0;
      dsp = 0;
      snprintf(devname, sizeof(devname), "%s", name);
      if (mut == NULL) mut = new Mutex();
}

DialogicDCB::~DialogicDCB()
{
      if (mut != NULL) delete mut;
      if(used)
            dcb_close(dsp);
}

void DialogicDCB::free(unsigned size)
{
      used -= size;

      if(!used)
            dcb_close(dsp);
}

void DialogicDCB::cleanup(void)
{
      DialogicDCB *node = first;
      DialogicDCB *next;
      while(node)
      {
            next = node->next;
            delete node;
            node = next;
      }
}

DialogicDCB *DialogicDCB::get(unsigned size)
{
      DialogicDCB *node = first;

      if(size > max)
            return NULL;

      while(node)
      {
            if(node->count - node->used >= size)
                  break;
            node = node->next;
      }
      if(!node)
            return NULL;

      if(!node->used)
            node->dsp = dcb_open(node->devname, 0);

      node->used += size;
      return node;
}

unsigned DialogicDCB::detect(void)
{
      char devname[16];
      int handle;
      unsigned board = 1;
      unsigned dsp;
      int count;

      for(;;)
      {
            dsp = 1;
            snprintf(devname, sizeof(devname), "dcbB%d", board);
            handle = dcb_open(devname, 0);
            if(handle < 0)
                  break;
            slog.debug() << "dcb: board " << board << " detected" << endl;
            dcb_close(handle);

            for(;;)
            {
                  snprintf(devname, sizeof(devname), "dcbB%dD%d", board, dsp++);
                  slog.debug() << "dcb: trying board " << devname << endl;
                  handle = dcb_open(devname, 0);
                  if(handle < 0)
                        break;
                  if(dcb_dsprescount(handle, &count) < 0)
                        count = 0;
                  dcb_close(handle);
                  slog.debug() << "dcb: board " << devname << " detected. count = " << count << endl;
                  if(count > max)
                        max = count;
                  if(count)
                        new DialogicDCB(devname, count);
            }
            ++board;
      }
      return max;
}

const char *DialogicDCB::establish(const char *conf, unsigned int size, int tsdev, int attributes, unsigned int fixed)
{
      mut->enterMutex();
      slog.debug() << "dcb: establishing a new conference " << conf << endl;
      const char *ret = NULL;
      if (size > 0) {
            DialogicDCB *node = DialogicDCB::get(size);
            if (node != NULL) {
                  MS_CDT cdt;
                  SC_TSINFO tsinfo;
                  long scts;
                  int id;

                  // Time slot
                  tsinfo.sc_numts = 1;
                  tsinfo.sc_tsarrayp = &scts;
                  if (dt_getxmitslot(tsdev, &tsinfo) == -1) {
                        slog.error() << "dcb: error time slot info : " << ATDV_ERRMSGP(tsdev) << endl;
                        node->free(size);
                  }
                  else {
                        cdt.chan_num = (int)scts;
                        cdt.chan_sel = MSPN_TS;
                        cdt.chan_attr = attributes;

                        // Establish the conference
                        if (dcb_estconf(node->dsp, &cdt, 1, MSCA_NULL, &id) == -1) {
                              slog.error() << "dcb: error establishing the conf : " << ATDV_ERRMSGP(tsdev) << endl;
                              node->free(size);
                        }
                        else {

                              // References the conference in the table
                              DialogicConf *newConf = new DialogicConf(conf, node, id, size, fixed);
                              ret = newConf->yourName();

                              // Listen
                              tsinfo.sc_numts = 1;
                              tsinfo.sc_tsarrayp = (long int *)&cdt.chan_lts;
                              if (dt_listen(tsdev, &tsinfo) == -1) {
                                    slog.error() << "dcb: error listening the conf " << conf << " : " << ATDV_ERRMSGP(tsdev) << endl;
                              }
                        }
                  }
            }
            else {
                  slog.error() << "dcb: error not enough slots for " << conf << endl;
            }
      }
      mut->leaveMutex();
      return ret;
}

const char *DialogicDCB::enter(const char *conf, unsigned int size, int tsdev, int attributes, unsigned int fixed)
{
      const char *ret = NULL;
      mut->enterMutex();
      DialogicConf *oConf = DialogicConf::get(conf);

      // No conf with that name
      if (oConf == NULL) {
            mut->leaveMutex();
            ret = DialogicDCB::establish(conf, size, tsdev, attributes, fixed);
      }

      // The conf was found
      else {
            MS_CDT cdt;
            SC_TSINFO tsinfo;
            long scts;
            int id;

            // Time slot
            tsinfo.sc_numts = 1;
            tsinfo.sc_tsarrayp = &scts;
            if (dt_getxmitslot(tsdev, &tsinfo) == -1) {
                  slog.error() << "dcb: error time slot info for entering " << conf << " : " << ATDV_ERRMSGP(tsdev) << endl;
                  oConf->let();
            }
            else {
                  cdt.chan_num = (int)scts;
                  cdt.chan_sel = MSPN_TS;
                  cdt.chan_attr = attributes;

                  // Enter the conference
                  if (dcb_addtoconf(oConf->yourNode()->dsp, oConf->yourConfid(), &cdt) == -1) {
                        slog.error() << "dcb: error entering the conf " << conf << " : " << ATDV_ERRMSGP(tsdev) << endl;
                        oConf->let();
                  }
                  else {
                        ret = oConf->yourName();

                        // Listen
                        tsinfo.sc_numts = 1;
                        tsinfo.sc_tsarrayp = (long int *)&cdt.chan_lts;
                        if (dt_listen(tsdev, &tsinfo) == -1) {
                              slog.error() << "dcb: error listening the conf " << conf << " : " << ATDV_ERRMSGP(tsdev) << endl;
                        }
                  }
            }
      }
      DialogicConf::dump();
      mut->leaveMutex();
      return ret;
}

unsigned int DialogicDCB::leave(const char *conf, int tsdev)
{
      unsigned int ret = 0;
      mut->enterMutex();
      DialogicConf *oConf = DialogicConf::let(conf);
      if (oConf != NULL) {
            MS_CDT cdt;
            SC_TSINFO tsinfo;
            long scts;
            int id;

            // Unlisten
            if (dt_unlisten(tsdev) == -1) {
                  slog.error() << "dcb: error unlistening the conf " << conf << " : " << ATDV_ERRMSGP(tsdev) << endl;
            }

            // Time slot
            tsinfo.sc_numts = 1;
            tsinfo.sc_tsarrayp = &scts;
            if (dt_getxmitslot(tsdev, &tsinfo) == -1) {
                  slog.error() << "dcb: error time slot info for leaving " << conf << " : " << ATDV_ERRMSGP(tsdev) << endl;
            }
            else {
                  cdt.chan_num = (int)scts;
                  cdt.chan_sel = MSPN_TS;

                  // Leave the conference
                  if (dcb_remfromconf(oConf->yourNode()->dsp, oConf->yourConfid(), &cdt) == -1) {
                        if (strcmp(ATDV_ERRMSGP(tsdev), "No error")) {
                              slog.error() << "dcb: error leaving the conf " << conf << " : " << ATDV_ERRMSGP(tsdev) << endl;
                        }
                        else {
                              ret = 1;
                        }
                  }
                  else {
                        ret = 1;
                  }
            }

            // If no more conferee
            if (oConf->yourCount() == 0) {
                  slog.debug() << "dcb: deleting the conference " << conf << endl;

                  // Close the conf
                  if (dcb_delconf(oConf->yourNode()->dsp, oConf->yourConfid()) == -1) {
                        slog.error() << "dcb: error deleting the conf " << conf << " : " << ATDV_ERRMSGP(oConf->yourNode()->dsp) << endl;
                        slog.debug() << "CONF IN ERROR : " << oConf->yourName() << "(" << oConf->yourConfid() << ") - " << oConf->yourCount() << "/" << oConf->yourSize() << endl;
                  }
                  delete oConf;
            }
      }
      else {
            slog.error() << "dcb: error search conf for leaving " << conf << endl;
      }
      DialogicConf::dump();
      mut->leaveMutex();
      return ret;
}

void DialogicDCB::destroy(const char *conf)
{
      mut->enterMutex();
      slog.debug() << "dcb: deleting the conference " << conf << endl;
      DialogicConf *oConf = DialogicConf::destroy(conf);
      if (oConf != NULL) {

            // Delete the conference
            if (dcb_delconf(oConf->yourNode()->dsp, oConf->yourConfid()) == -1) {
                  slog.error() << "dcb: error deleting the conf " << conf << " : " << ATDV_ERRMSGP(oConf->yourNode()->dsp) << endl;
            }
            delete oConf;
      }
      else {
            slog.error() << "dcb: error search conf for destroying " << conf << endl;
      }
      mut->leaveMutex();
}

unsigned int DialogicDCB::getMore(unsigned int size)
{
      if (size > 0) {
            if(count - used >= size) {
                  if(!used) dsp = dcb_open(devname, 0);
                  used += size;
                  return size;
            }
            else {
                  return 0;
            }
      }
      return 0;
}

DialogicConf::DialogicConf(const char *nm, DialogicDCB *n, int i, unsigned int s, unsigned int f) : name(NULL), node(n), confid(i), count(1), size(s), fixed(f)
{
      char temp[256];

      // If no conf name asked
      if (nm == NULL) {
            snprintf(temp, 255, "conf-%s-%d", n->getDevname(), i);
            name = (char *)malloc(strlen(temp) + 1);
            strcpy(name, temp);
      }
      else
      if (nm[0] == 0) {
            snprintf(temp, 255, "conf-%s-%d", n->getDevname(), i);
            name = (char *)malloc(strlen(temp) + 1);
            strcpy(name, temp);
      }
      else {
            name = (char *)malloc(strlen(nm) + 1);
            strcpy(name, nm);
      }

      // Insert in the chain
      next = first;
      previous = NULL;
      first = this;
      if (next != NULL) next->yourPrevious(this);
}

DialogicConf::~DialogicConf(void)
{
      if (name != NULL) {
            free(name);
      }
      if (next != NULL) next->yourPrevious(previous);
      if (previous != NULL) previous->yourNext(next);
      else first = next;
      if (count > 0) {
            slog.error() << "dcb: WARNING! Not all the conferees left the conference and I am destroying it" << endl;
      }
      node->free(size);
}

DialogicConf *DialogicConf::search(const char *conf, unsigned int notfull, unsigned int notempty)
{
      DialogicConf *oConf = first;

      while(oConf != NULL)
      {
            if(!strcmp(oConf->name, conf) && (!notfull || oConf->count < oConf->size || !oConf->fixed) && (!notempty || oConf->count > 0))
                  break;
            oConf = oConf->next;
      }
      return oConf;
}

void DialogicConf::dump(void)
{
      DialogicConf *oConf = first;

      while(oConf != NULL)
      {
            slog.debug() << "DUMP CONFS : " << oConf->yourName() << "(" << oConf->yourConfid() << ") - " << oConf->yourCount() << "/" << oConf->yourSize() << endl;
            oConf = oConf->next;
      }
}

DialogicConf *DialogicConf::get(const char *conf)
{
      // Search for not a full conference with that name
      DialogicConf *oConf = search(conf, 1, 0);
      if (oConf != NULL) {

            // I don't fill the reserved pool
            if (oConf->count < oConf->size) {
                  oConf->count++;
            }

            // All the reserved slots are occupied
            else {

                  // May I find a supplementary resource
                  if (oConf->node->getMore(1)) {
                        oConf->count++;
                        oConf->size++;
                  }
            }
      }
      return oConf;
}

DialogicConf *DialogicConf::let(const char *conf)
{
      // Search for not an empty conference with that name
      DialogicConf *oConf = search(conf, 0, 1);
      if (oConf != NULL) oConf->let();
      return oConf;
}

DialogicConf *DialogicConf::destroy(const char *conf)
{
      return search(conf, 0, 0);
}

void DialogicConf::let(void) {
      if (count > 0) count--;
}

bool DialogicTrunk::conferenceHandler(TrunkEvent *event)
{
      const char *ptr = NULL;

      switch(event->id)
      {
      case TRUNK_STOP_STATE:
            slog(Slog::levelDebug) << "conferenceHandler : STOP_STATE " << endl ;

            // If the request were to destroy or leave the conf, the conferee has already gone
            if (data.conference.option == CONF_DEFAULT) {

                  // Else he has to quit the conf
                  if (!DialogicDCB::leave(data.conference.name, tsdev)) {
                        Trunk::error("conference-leave-failed");
                  }
                  tsConnect();
            }

            // The end
            handler = &DialogicTrunk::stepHandler;
            stopChannel(EV_ASYNC);
            _stopping_state = true;
            return true;
            break;

      case TRUNK_ENTER_STATE:

            // Option
            switch (data.conference.option) {
            case CONF_DEFAULT:
                  slog(Slog::levelDebug) << "conferenceHandler : TRUNK_ENTER_STATE default" << endl;
                  ptr = DialogicDCB::enter(data.conference.name, data.conference.size, tsdev, data.conference.attributes, data.conference.fixed);
                  if (ptr == NULL) {
                        Trunk::error("conference-not-entered");
                        handler = &DialogicTrunk::stepHandler;
                        return true;
                  }
                  else {
                        strncpy(data.conference.name, ptr, 255);
                        setSymbol("confName", ptr);
                        enterState("conference");
                        if (data.conference.attributes & MSPA_RO) {
                              status[id] = 'c';
                        }
                        else {
                              status[id] = 'C';
                        }
                        return true;
                  }
                  break;

            case CONF_ESTABLISH:
                  slog(Slog::levelDebug) << "conferenceHandler : TRUNK_ENTER_STATE establish" << endl;
                  ptr = DialogicDCB::establish(data.conference.name, data.conference.size, tsdev, data.conference.attributes, data.conference.fixed);
                  if (ptr == NULL) {
                        Trunk::error("conference-not-established");
                        handler = &DialogicTrunk::stepHandler;
                        return true;
                  }
                  else {
                        handler = &DialogicTrunk::stepHandler;
                        strncpy(data.conference.name, ptr, 255);
                        setSymbol("confName", ptr);
                        stopChannel(EV_ASYNC);
                        _stopping_state = true;
                        trunkSignal(TRUNK_SIGNAL_STEP);
                        return true;
                  }
                  break;

            case CONF_ENTER:
                  slog(Slog::levelDebug) << "conferenceHandler : TRUNK_ENTER_STATE enter" << endl;
                  ptr = DialogicDCB::enter(data.conference.name, data.conference.size, tsdev, data.conference.attributes, data.conference.fixed);
                  if (ptr == NULL) {
                        Trunk::error("conference-not-entered");
                        handler = &DialogicTrunk::stepHandler;
                        return true;
                  }
                  else {
                        handler = &DialogicTrunk::stepHandler;
                        strncpy(data.conference.name, ptr, 255);
                        setSymbol("confName", ptr);
                        stopChannel(EV_ASYNC);
                        _stopping_state = true;
                        trunkSignal(TRUNK_SIGNAL_STEP);
                        return true;
                  }

            case CONF_LEAVE:
                  slog(Slog::levelDebug) << "conferenceHandler : TRUNK_ENTER_STATE leave" << endl;
                  if (!DialogicDCB::leave(data.conference.name, tsdev)) {
                        Trunk::error("conference-leave-failed");
                  }
                  handler = &DialogicTrunk::stepHandler;
                  tsConnect();
                  stopChannel(EV_ASYNC);
                  _stopping_state = true;
                  trunkSignal(TRUNK_SIGNAL_STEP);
                  return true;
                  break;

            case CONF_DESTROY:
                  slog(Slog::levelDebug) << "conferenceHandler : TRUNK_ENTER_STATE destroy" << endl;
                  handler = &DialogicTrunk::stepHandler;
                  DialogicDCB::destroy(data.conference.name);
                  tsConnect();
                  stopChannel(EV_ASYNC);
                  _stopping_state = true;
                  trunkSignal(TRUNK_SIGNAL_STEP);
                  return true;
                  break;

            default:
                  slog(Slog::levelDebug) << "conferenceHandler : TRUNK_ENTER_STATE ?????" << endl;
                  handler = &DialogicTrunk::stepHandler;
                  Trunk::error("conference-unknown-keyword");
                  return true;
                  break;
            }
      break;
      }
      return false;
}

#ifdef CCXX_NAMESPACES
};
#endif


Generated by  Doxygen 1.6.0   Back to index