Exemplo n.º 1
0
def main(config):
            
    configureLogging(config)
    log = logging.getLogger('main')
    
    if config.getboolean('daemon', 'daemon'):
        pidfile = config.get('daemon', 'pidfile')
        daemonize(pidfile)
        
    
    pw = config.get('host', 'password')
    h = config.get('host', 'host')
    p = config.get('host', 'port')
    
    #Setting up the DB connection
    log.info('Connecting to DB on: %s ' % (config.get('database', 'url')))

    if ("sqlite" in config.get('database', 'url')):
        engine = create_engine( config.get('database', 'url'), poolclass=NullPool )
        log.warning('You are using SQLite and we will use NullPool as pooling engine.')
    else:
        engine = create_engine( config.get('database', 'url'), pool_recycle=3600 )


    Session = sessionmaker( autoflush=False, autocommit=False, bind=engine)
    
    log.info('Connecting to: %s:%s ' % (h, p))
    con = ESLconnection(h, p, pw)
    con.events('plain', 'CUSTOM conference::maintenance')
    conferences = {}
    while con.connected():
        e = con.recvEvent()

        if e is None:
            continue
            

        conf_uuid = getUnquotedHeader(e, 'Conference-Unique-ID')
        action = getUnquotedHeader(e, 'Action')
        conf_size = getUnquotedHeader(e, 'Conference-Size')
        
        if action == 'stop-recording':
            try:
                TrackerConference.stop_recording(e, config, Session())
                continue
            except Exception, e:
                log.critical('An error has occurred while executing stop-recording!\n%s' % traceback.format_exc())
                continue
        
        if conf_uuid not in conferences.keys():
            try:
                conf = TrackerConference(e, config, Session())
                conferences[conf_uuid] = conf
            except Exception, e:
                log.warning('An error occured creating a new conference object! Continuing... \n%s' % e)
                continue
Exemplo n.º 2
0
def connect(host, port, pw):
    """
    Return a connected handle
    """
    log = logging.getLogger(__name__)
    log.info('Connecting to: %s:%s', host, port)
    timer = 0.5
    c = ESLconnection(host, port, pw)
    c.events('plain', 'CUSTOM conference::maintenance')
    while True:
        if c.connected():
            log.info("Connected to ESL.")
            break
        log.warning("Connection failed. Retrying in %2.2f", timer)
        sleep(timer)
        if timer < 3:
            timer = timer*1.2
        c = ESLconnection(host, port, pw)
        c.events('plain', 'CUSTOM conference::maintenance')
    return c
Exemplo n.º 3
0
def main(config):
            
    configureLogging(config)
    log = logging.getLogger('main')
    
    if config.getboolean('daemon', 'daemon'):
        global PIDFILE
        PIDFILE = config.get('daemon', 'pidfile')
        daemonize()
        
    
    pw = config.get('host', 'password')
    h = config.get('host', 'host')
    p = config.get('host', 'port')
    
    #Setting up the DB connection
    log.info('Connecting to DB on: %s ' % (config.get('database', 'url')))

    if ("sqlite" in config.get('database', 'url')):
        engine = create_engine( config.get('database', 'url'), poolclass=NullPool )
        log.warning('You are using SQLite and we will use NullPool as pooling engine.')
    else:
        engine = create_engine( config.get('database', 'url'), pool_recycle=3600 )


    sm = sessionmaker( autoflush=False, autocommit=False, bind=engine)
    Session = scoped_session( sm )
    
    log.info('Connecting to: %s:%s ' % (h, p))
    con = ESLconnection(h, p, pw)
    con.events('plain', 'CUSTOM conference::maintenance')
    while con.connected():
        e = con.recvEvent()

        if e is None:
            continue
        log.debug('Received event:\n%s' % e.serialize())

        conf_uuid = getUnquotedHeader(e, 'Conference-Unique-ID')
        conf_profile = getUnquotedHeader(e, 'Conference-Profile-Name')
        conf_name = getUnquotedHeader(e, 'Conference-Name')
        conf_size = getUnquotedHeader(e, 'Conference-Size')
        caller_id_name = getUnquotedHeader(e, 'Caller-Caller-ID-Name')
        caller_id_number = getUnquotedHeader(e, 'Caller-Caller-ID-Number')
        member_id = getUnquotedHeader(e, 'Member-ID')
        member_type = getUnquotedHeader(e, 'Member-Type')
        action = getUnquotedHeader(e, 'Action')
        event_date = getUnquotedHeader(e, 'Event-Date-Local')
        if event_date is not None:
            # Check the python version, because strptime does not exist in it.
            if sys.version_info[2] < 5:
                spl = event_date.split('-')
                year = int(spl[0])
                month = int(spl[1])
                spl2 = spl[2].split(' ')
                day = int(spl2[0])
                spl3 = spl2[1].split(':')
                hour = int(spl3[0])
                minutes = int(spl3[1])
                seconds = int(spl3[2])
                event_date = datetime(year=year, month=month, day=day, hour=hour, minute=minutes, second=seconds)
            else:
                event_date = datetime.strptime(event_date, '%Y-%m-%d %H:%M:%S')

        if not conf_name:
            log.warning('There is no conf name on this event.\n%s' % e.serialize())
            continue
            
        try:
            owner = Session.query(ModeratorPin).get(conf_name)
        except Exception, err:
            log.critical(traceback.format_exc())
        if owner is None:
            log.critical('Error because we could not get owner.')
            Session.remove()
            continue
            
        confObj = Session.query(Conference).get(conf_uuid)
        if confObj is None:
            log.debug('Conference does not exist, we must create one.')
        
        if action == 'add-member':
            log.info('Member added...')
            if conf_size == '1':
                confObj = Conference(conf_uuid, event_date, unicode(conf_name), unicode(conf_profile))
                owner.conferences.append(confObj)
                Session.add(confObj)
                log.debug('Action taken on %s. %s' % (conf_name, action))
                actionObj = ConferenceAction(unicode(action), 
                                            unicode(caller_id_name),
                                            unicode(caller_id_number),
                                            unicode(conf_size),
                                            unicode(member_type),
                                            event_date,
                                            confObj.id)
                confObj.actions.append(actionObj)
                Session.add(actionObj)
                Session.commit()
                Session.remove()
                log.debug('Conference %s has been created.' % conf_name)
                continue
                
        elif action == 'del-member':
            if conf_size == '0':
                confObj.ended = event_date
                log.debug('Action taken on %s. %s' % (conf_name, action))
                actionObj = ConferenceAction(unicode(action), 
                                            unicode(caller_id_name),
                                            unicode(caller_id_number),
                                            unicode(conf_size),
                                            unicode(member_type),
                                            event_date,
                                            confObj.id)
                confObj.actions.append(actionObj)
                Session.add(actionObj)

                Session.commit()
                Session.remove()
                log.debug('Conference %s has been destroyed.' % conf_name)
                continue
                

        
        log.debug('Action taken on %s. %s' % (conf_name, action))

        # This action comes after the conference has ended.
        if action == 'stop-recording':
            confObj.recording = os.path.join(config.get('mp3', 'store_to'), getUnquotedHeader(e, 'Path').split('/').pop()[:-3] + 'mp3')
            host = unicode(getUnquotedHeader(e, 'FreeSWITCH-IPv4'))
            Session.commit()
            try:
                owner_obj = Session.query(ModeratorPin).get(confObj.owner)
            except Exception, e:
                log.critical('Could not find owner. Db corruption? %s' % e)
                log.critical('Exception: %s' % traceback.format_exc())
                Session.remove()
                continue
                
            t = Thread(target=postRecordingThread, args=(config, getUnquotedHeader(e, 'Path'), confObj, host, owner_obj))
            log.debug('Starting thread %s' % t)
            t.start()
            log.debug('Thread started...')
            Session.remove()
            continue
Exemplo n.º 4
0
class Connection(object):
    '''Connection wrapper which can provide mutex attr access making the
    underlying ESL.ESLconnection thread safe.

    (Note: must be explicitly connected before use.)
    '''
    def __init__(self, host, port='8021', auth='ClueCon',
                 locked=True, lock=None):
        """
        Parameters
        -----------
        host : string
            host name or ip address for server hosting an esl connection.
        port : string
            port where esl connection socket is being offered.
        auth : string
            authentication password for esl connection.
        locked : bool
            indicates whether to return a thread safe derivative of the default
            ESLConnection class.
        lock : instance of mp.Lock
            a lock implementation which the connection will utilize when
            serializing accesses from multiple threads (requires locked=True)
        """
        self.host = host
        self.port = port
        self.auth = auth
        self.log = utils.get_logger(utils.pstr(self))
        self._sub = ()  # events subscription
        if locked:
            self._mutex = lock or mp.Lock()
        # don't connect by default
        self._con = False

    def __enter__(self, **kwargs):
        self.connect(**kwargs)
        return self

    def __exit__(self, exception_type, exception_val, trace):
        self.disconnect()

    @staticmethod
    def _handle_socket_data(event):
        body = event.getBody() if event else None
        if not body:
            return False, None
        if '-ERR' in body.splitlines()[-1]:
            raise utils.APIError(body)
        return True, body

    def api(self, cmd, errcheck=True):
        '''Invoke esl api command (with error checking by default).
        Returns an ESL.ESLEvent instance for event type "SOCKET_DATA".
        '''
        self.log.debug("api cmd '{}'".format(cmd))
        with self._mutex:
            try:
                event = self._con.api(cmd)
                if errcheck:
                    _, body = self._handle_socket_data(event)
                return event
            except AttributeError:
                raise ConnectionError("call `connect` first")

    def cmd(self, cmd):
        '''Return the string-body output from invoking a command.
        '''
        return self.api(cmd).getBody().strip()

    def bgapi(self, cmd):
        self.log.debug("bgapi cmd '{}'".format(cmd))
        with self._mutex:
            try:
                return self._con.bgapi(cmd)
            except AttributeError:
                raise ConnectionError("call `connect` first")

    def __getattr__(self, name):
        if name == '_con':
            return object.__getattribute__(self, name)
        try:
            attr = getattr(self._con, name)
            if not callable(attr):
                return attr
            else:
                # wrap callables with a mutex
                @functools.wraps(attr)
                def method(*args, **kwargs):
                    with self._mutex:
                        return attr(*args, **kwargs)
                return method
        except AttributeError:
            if name in dir(ESLconnection):
                raise AttributeError(
                    "Call `connect()` before before accessing the '{}' "
                    "attribute".format(name))
            else:
                raise

    def __dir__(self):
        dircon = dir(self._con) if self.connected() else []
        return utils.dirinfo(self) + dircon

    def disconnect(self):
        """Rewrap disconnect to avoid deadlocks
        """
        if self.connected():
            ret = self._con.disconnect()
            self._sub = ()  # reset subscription
            return not bool(ret)
        return False

    def connect(self, host=None, port=None, auth=None):
        """Reconnect if disconnected
        """
        host = host or self.host
        port = port or self.port
        auth = auth or self.auth
        if not self.connected():
            # XXX: try a few times since connections seem to be flaky
            # We should probably try to fix this in the _ESL.so
            for _ in range(5):
                self._con = ESLconnection(*map(str, (host, port, auth)))
                time.sleep(0.05)  # I wouldn't tweak this if I were you.
                if self.connected() and check_con(self._con):
                        break
                else:
                    self._con = False
        if not check_con(self._con):
            raise ConnectionError(
                "Failed to connect to server at '{}:{}'\n"
                "Please check that FreeSWITCH is running and "
                "accepting esl connections.".format(host, port))

    def connected(self):
        '''Return bool indicating if this connection is active
        '''
        if not self._con:
            return False
        return bool(self._con.connected())

    def subscribe(self, event_types, fmt='plain'):
        """Subscribe connection to receive events for all names
        in `event_types`
        """
        if not self.connected():
            raise ConnectionError(
                "connection must be active before registering for events")
        for name in event_types:
            prefix = 'CUSTOM ' if "::" in name else ''
            self._con.events(fmt, "{}{}".format(prefix, name))
            self._sub += (name,)