class RestServer(InboundEventSocket, RestApi): name = "RestServer" def __init__(self, configfile): os.environ['PLIVO_REST_CONFIG'] = configfile # create flask app self.app = Flask(self.name) # load config into flask app self.app.config.from_envvar('PLIVO_REST_CONFIG') # init logger self._init_logger() # create rest server fs_host, fs_port = self.app.config['FS_INBOUND_ADDRESS'].split(':', 1) fs_port = int(fs_port) fs_password = self.app.config['FS_PASSWORD'] InboundEventSocket.__init__(self, fs_host, fs_port, fs_password, filter='ALL') # expose api functions to flask app for path, func_desc in urls.URLS.iteritems(): func, methods = func_desc fn = getattr(self, func.__name__) self.app.add_url_rule(path, func.__name__, fn, methods=methods) # create wsgi server http_host, http_port = self.app.config['HTTP_ADDRESS'].split(':', 1) http_port = int(http_port) self.http_server = WSGIServer((http_host, http_port), self.app, log=self.logger) def _init_logger(self): logdebug = self.app.config.get('DEBUG', False) logtype = self.app.config.get('LOG_TYPE', 'stdout') if logtype == 'syslog': syslog_addr = self.app.config.get('SYSLOG_ADDRESS', '/dev/log') syslog_facility = self.app.config.get('SYSLOG_FACILITY', 'local0') self.logger = SysLogger(syslog_addr, syslog_facility) elif logtype == 'file': logfile = self.app.config.get('LOG_FILE', '/tmp/ivr.log') self.logger = FileLogger(logfile) else: self.logger = StdoutLogger() self.logger.name = self.name self.app._logger = self.logger if logdebug: self.logger.set_debug() else: self.logger.set_info() def start(self): # run #self.app.debug = True #self.app.run() #self.connect() self.http_server.serve_forever()
class PlivoRestServer(PlivoRestApi): """Class PlivoRestServer""" name = "PlivoRestServer" def __init__(self, configfile, daemon=False, pidfile='/tmp/plivo_rest.pid'): """Constructor Initialize main properties such as daemon, pidfile, config, etc... This will init the http server that will provide the Rest interface, the rest server is configured on HTTP_ADDRESS Extra: * FS_INBOUND_ADDRESS : Define the event_socket interface to connect to in order to initialize CallSession with Freeswitch * FS_OUTBOUND_ADDRESS : Define where on which address listen to initialize event_socket session with Freeswitch in order to control new CallSession """ self._daemon = daemon self._run = False self._pidfile = pidfile # load config self._config = helpers.get_config(configfile) # create flask app self.app = Flask(self.name) self.app.secret_key = helpers.get_conf_value(self._config, 'rest_server', 'SECRET_KEY') self.app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 # create logger self.create_logger() # create rest server self.fs_inbound_address = helpers.get_conf_value(self._config, 'freeswitch', 'FS_INBOUND_ADDRESS') fs_host, fs_port = self.fs_inbound_address.split(':', 1) fs_port = int(fs_port) fs_password = helpers.get_conf_value(self._config, 'freeswitch', 'FS_PASSWORD') # get auth id and auth token self.auth_id = helpers.get_conf_value(self._config, 'rest_server', 'AUTH_ID') self.auth_token = helpers.get_conf_value(self._config, 'rest_server', 'AUTH_TOKEN') # get outbound socket host/port fs_out_address = helpers.get_conf_value(self._config, 'freeswitch', 'FS_OUTBOUND_ADDRESS') fs_out_host, fs_out_port = fs_out_address.split(':', 1) # if outbound host is 0.0.0.0, send to 127.0.0.1 if fs_out_host == '0.0.0.0': fs_out_address = '127.0.0.1:%s' % fs_out_port # create inbound socket instance self._rest_inbound_socket = RESTInboundSocket(fs_host, fs_port, fs_password, outbound_address=fs_out_address, auth_id=self.auth_id, auth_token=self.auth_token, filter='ALL', log=self.log) # expose api functions to flask app for path, func_desc in urls.URLS.iteritems(): func, methods = func_desc fn = getattr(self, func.__name__) self.app.add_url_rule(path, func.__name__, fn, methods=methods) # create wsgi server self.http_address = helpers.get_conf_value(self._config, 'rest_server', 'HTTP_ADDRESS') http_host, http_port = self.http_address.split(':', 1) http_port = int(http_port) self.http_server = WSGIServer((http_host, http_port), self.app, log=self.log) def create_logger(self): """This will create a logger Based on the settings in the configuration file, LOG_TYPE will determine if we will log in file, syslog or stdout To log in file we use the following setting : LOG_FILE = /tmp/plivo-rest.log To log to syslog we have several settings to configure the logging : * LOG_TYPE = syslog * SYSLOG_ADDRESS = /dev/log * SYSLOG_FACILITY = local0 """ if self._daemon is False: self.log = StdoutLogger() self.log.set_debug() self.app.debug = True else: logtype = helpers.get_conf_value(self._config, 'rest_server', 'LOG_TYPE') if logtype == 'file': logfile = helpers.get_conf_value(self._config, 'rest_server', 'LOG_FILE') self.log = FileLogger(logfile) elif logtype == 'syslog': syslogaddress = helpers.get_conf_value(self._config, 'rest_server', 'SYSLOG_ADDRESS') syslogfacility = helpers.get_conf_value(self._config, 'rest_server', 'SYSLOG_FACILITY') self.log = SysLogger(syslogaddress, syslogfacility) else: self.log = StdoutLogger() debug_mode = helpers.get_conf_value(self._config, 'rest_server', 'DEBUG') if debug_mode == 'true': self.log.set_debug() self.app.debug = True else: self.log.set_info() self.log.name = self.name self.app._logger = self.log def do_daemon(self): """This will daemonize the current application Two settings from our configuration files are also used to run the daemon under a determine user & group. REST_SERVER_USER : determine the user running the daemon REST_SERVER_GROUP : determine the group running the daemon """ # get user/group from config user = helpers.get_conf_value(self._config, 'rest_server', 'REST_SERVER_USER') group = helpers.get_conf_value(self._config, 'rest_server', 'REST_SERVER_GROUP') if not user or not group: uid = os.getuid() user = pwd.getpwuid(uid)[0] gid = os.getgid() group = grp.getgrgid(gid)[0] # daemonize now plivo.utils.daemonize.daemon(user, group, path='/', pidfile=self._pidfile, other_groups=()) def sig_term(self, *args): """if we receive a term signal, we will shutdown properly """ self.log.warn("Shutdown ...") self.stop() sys.exit(0) def stop(self): """Method stop stop the infinite loop from start method and close the socket """ self._run = False self._rest_inbound_socket.exit() def start(self): """start method is where we decide to : * catch term signal * run as daemon * start the http server * connect to Freeswitch via our Inbound Socket interface * wait even if it takes forever, ever, ever, evveeerrr... """ self.log.info("RESTServer starting ...") # catch SIG_TERM gevent.signal(signal.SIGTERM, self.sig_term) # run self._run = True if self._daemon: self.do_daemon() # connection counter retries = 1 # start http server self.http_proc = gevent.spawn(self.http_server.serve_forever) self.log.info("RESTServer started at: 'http://%s'" % self.http_address) # start inbound socket try: while self._run: try: self.log.info("Trying to connect to FreeSWITCH at: %s" \ % self.fs_inbound_address) self._rest_inbound_socket.connect() # reset retries when connection is a success retries = 1 self.log.info("Connected to FreeSWITCH") # serve forever self._rest_inbound_socket.serve_forever() except ConnectError, e: if self._run is False: break self.log.error("Connect failed: %s" % str(e)) # sleep after connection failure sleep_for = retries * 10 self.log.error("Reconnecting in %d seconds" % sleep_for) gevent.sleep(sleep_for) # don't sleep more than 120 secs if retries < 12: retries += 1 except (SystemExit, KeyboardInterrupt): pass # kill http server self.http_proc.kill() # finish here self.log.info("RESTServer Exited")
class PlivoOutboundServer(OutboundServer): def __init__(self, configfile, daemon=False, pidfile="/tmp/plivo_outbound.pid", filter=None): self._request_id = 0 self._daemon = daemon self._run = False self._pidfile = pidfile # load config self._config = helpers.get_config(configfile) # create logger self.create_logger() # create outbound server self.fs_outbound_address = helpers.get_conf_value(self._config, "freeswitch", "FS_OUTBOUND_ADDRESS") fs_host, fs_port = self.fs_outbound_address.split(":", 1) fs_port = int(fs_port) self.default_answer_url = helpers.get_conf_value(self._config, "freeswitch", "DEFAULT_ANSWER_URL") self.auth_id = helpers.get_conf_value(self._config, "rest_server", "AUTH_ID") self.auth_token = helpers.get_conf_value(self._config, "rest_server", "AUTH_TOKEN") self.default_hangup_url = helpers.get_conf_value(self._config, "freeswitch", "DEFAULT_HANGUP_URL") # default hangup_url is answer_url if not self.default_hangup_url: self.default_hangup_url = self.default_answer_url # This is where we define the connection with the # Plivo XML grammar Processor OutboundServer.__init__(self, (fs_host, fs_port), PlivoOutboundEventSocket, filter) def _get_request_id(self): try: self._request_id += 1 except OverflowError: self._request_id = 1 return self._request_id def do_handle(self, socket, address): request_id = self._get_request_id() self.log.info("(%d) New request from %s" % (request_id, str(address))) self._handle_class( socket, address, self.log, default_answer_url=self.default_answer_url, default_hangup_url=self.default_hangup_url, auth_id=self.auth_id, auth_token=self.auth_token, request_id=request_id, filter=self._filter, ) self.log.info("(%d) End request from %s" % (request_id, str(address))) def create_logger(self): if self._daemon is False: self.log = StdoutLogger() self.log.set_debug() else: logtype = helpers.get_conf_value(self._config, "freeswitch", "LOG_TYPE") if logtype == "file": logfile = helpers.get_conf_value(self._config, "freeswitch", "LOG_FILE") self.log = FileLogger(logfile) elif logtype == "syslog": syslogaddress = helpers.get_conf_value(self._config, "freeswitch", "SYSLOG_ADDRESS") syslogfacility = helpers.get_conf_value(self._config, "freeswitch", "SYSLOG_FACILITY") self.log = SysLogger(syslogaddress, syslogfacility) else: self.log = StdoutLogger() debug_mode = helpers.get_conf_value(self._config, "freeswitch", "DEBUG") if debug_mode == "true": self.log.set_debug() else: self.log.set_info() def do_daemon(self): # get user/group from config user = helpers.get_conf_value(self._config, "freeswitch", "FS_OUTBOUND_USER") group = helpers.get_conf_value(self._config, "freeswitch", "FS_OUTBOUND_GROUP") if not user or not group: uid = os.getuid() user = pwd.getpwuid(uid)[0] gid = os.getgid() group = grp.getgrgid(gid)[0] # daemonize now plivo.utils.daemonize.daemon(user, group, path="/", pidfile=self._pidfile, other_groups=()) def sig_term(self, *args): self.stop() self.log.warn("Shutdown ...") sys.exit(0) def stop(self): self._run = False self.kill() def start(self): self.log.info("Starting OutboundServer ...") # catch SIG_TERM gevent.signal(signal.SIGTERM, self.sig_term) # run self._run = True if self._daemon: self.do_daemon() super(PlivoOutboundServer, self).start() self.log.info("OutboundServer started at '%s'" % str(self.fs_outbound_address)) try: while self._run: gevent.sleep(1.0) except (SystemExit, KeyboardInterrupt): pass self.log.info("OutboundServer Exited")
class PlivoOutboundServer(outboundsocket.OutboundServer): def __init__(self, configfile, daemon=False, pidfile='/tmp/plivo_outbound.pid'): self._request_id = 0 self._daemon = daemon self._run = False self._pidfile = pidfile # load config self._config = helpers.get_config(configfile) # set trace flag self._trace = helpers.get_conf_value(self._config, 'freeswitch', 'FS_OUTBOUND_TRACE') == 'true' # create logger self.create_logger() # create outbound server self.fs_outbound_address = helpers.get_conf_value(self._config, 'freeswitch', 'FS_OUTBOUND_ADDRESS') fs_host, fs_port = self.fs_outbound_address.split(':', 1) fs_port = int(fs_port) self.default_answer_url = helpers.get_conf_value(self._config, 'freeswitch', 'DEFAULT_ANSWER_URL') self.auth_id = helpers.get_conf_value(self._config, 'rest_server', 'AUTH_ID') self.auth_token = helpers.get_conf_value(self._config, 'rest_server', 'AUTH_TOKEN') self.default_hangup_url = helpers.get_conf_value(self._config, 'freeswitch', 'DEFAULT_HANGUP_URL') self.default_http_method = helpers.get_conf_value(self._config, 'rest_server', 'DEFAULT_HTTP_METHOD') if not self.default_http_method in ('GET', 'POST'): self.default_http_method = 'POST' self.extra_fs_vars = helpers.get_conf_value(self._config, 'freeswitch', 'EXTRA_FS_VARS') # This is where we define the connection with the # Plivo XML element Processor outboundsocket.OutboundServer.__init__(self, (fs_host, fs_port), PlivoOutboundEventSocket, filter=None) def _get_request_id(self): try: self._request_id += 1 except OverflowError: self._request_id = 1 return self._request_id def handle_request(self, socket, address): request_id = self._get_request_id() self.log.info("(%d) New request from %s" % (request_id, str(address))) self._requestClass(socket, address, self.log, default_answer_url=self.default_answer_url, default_hangup_url=self.default_hangup_url, default_http_method=self.default_http_method, extra_fs_vars=self.extra_fs_vars, auth_id=self.auth_id, auth_token=self.auth_token, request_id=request_id, trace=self._trace ) self.log.info("(%d) End request from %s" % (request_id, str(address))) def create_logger(self): if self._daemon is False: logtype = helpers.get_conf_value(self._config, 'freeswitch', 'LOG_TYPE') if logtype == 'dummy': self.log = DummyLogger() else: self.log = StdoutLogger() self.log.set_debug() else: logtype = helpers.get_conf_value(self._config, 'freeswitch', 'LOG_TYPE') if logtype == 'file': logfile = helpers.get_conf_value(self._config, 'freeswitch', 'LOG_FILE') self.log = FileLogger(logfile) elif logtype == 'syslog': syslogaddress = helpers.get_conf_value(self._config, 'freeswitch', 'SYSLOG_ADDRESS') syslogfacility = helpers.get_conf_value(self._config, 'freeswitch', 'SYSLOG_FACILITY') self.log = SysLogger(syslogaddress, syslogfacility) elif logtype == 'dummy': self.log = DummyLogger() else: self.log = StdoutLogger() debug_mode = helpers.get_conf_value(self._config, 'freeswitch', 'DEBUG') if debug_mode == 'true' or self._trace is True: self.log.set_debug() else: self.log.set_info() def do_daemon(self): # get user/group from config user = helpers.get_conf_value(self._config, 'freeswitch', 'FS_OUTBOUND_USER') group = helpers.get_conf_value(self._config, 'freeswitch', 'FS_OUTBOUND_GROUP') if not user or not group: uid = os.getuid() user = pwd.getpwuid(uid)[0] gid = os.getgid() group = grp.getgrgid(gid)[0] # daemonize now plivo.utils.daemonize.daemon(user, group, path='/', pidfile=self._pidfile, other_groups=()) def sig_term(self, *args): self.stop() self.log.warn("Shutdown ...") sys.exit(0) def start(self): self.log.info("Starting OutboundServer ...") # catch SIG_TERM gevent.signal(signal.SIGTERM, self.sig_term) # run self._run = True if self._daemon: self.do_daemon() super(PlivoOutboundServer, self).start() self.log.info("OutboundServer started at '%s'" \ % str(self.fs_outbound_address)) self.serve_forever() self.log.info("OutboundServer Exited")