def _send_raw_to_freeswitch_cli(self, cmd): con = ESLconnection(self.conf['fs_esl_ip'], self.conf['fs_esl_port'], self.conf['fs_esl_pass']) if con.connected(): con.api(cmd) return True return False
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
def makeCall(self, destination): con = ESLconnection(self.conf['fs_esl_ip'], self.conf['fs_esl_port'], self.conf['fs_esl_pass']) if con.connected(): con.api( str("originate {origination_call_id_name=%s,origination" "_caller_id_number=%s}sofia/internal/%s@%s:" "5060 &echo" % (self.user, self.user, destination, self.other_ip))) else: raise Exception("ESL Connection Failed")
def makeCall(self, destination): username = subscriber.get_username_from_imsi(self.user) con = ESLconnection(self.conf['fs_esl_ip'], self.conf['fs_esl_port'], self.conf['fs_esl_pass']) if con.connected(): con.api( str("originate {origination_call_id_name=%s,origination" "_caller_id_number=%s}sofia/internal/%s@%s:%s" "5062 &echo" % (username, username, destination, self.other_ip))) else: raise Exception("ESL Connection Failed")
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
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
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,)