Exemple #1
0
class HttpServer:
    # prepare may be rewrite it
    config = {
        'SECRET_KEY': 'someWOrkSD20KMS9330)&#',
        'coco': None,
        'LOGIN_URL': '/login'
    }
    init_kwargs = dict(
        async_mode="eventlet",
        # async_mode="threading",
        # ping_timeout=20,
        # ping_interval=10,
        # engineio_logger=True,
        # logger=True
    )

    def __init__(self):
        config.update(self.config)
        self.flask_app = Flask(__name__, template_folder='dist')
        self.flask_app.config.update(config)
        self.socket_io = SocketIO()
        self.register_routes()
        self.register_error_handler()

    def register_routes(self):
        self.socket_io.on_namespace(ProxyNamespace('/ssh'))

    @staticmethod
    def on_error_default(e):
        logger.exception(e)

    def register_error_handler(self):
        self.socket_io.on_error_default(self.on_error_default)

    def run(self):
        # return
        host = config["BIND_HOST"]
        port = config["HTTPD_PORT"]
        print('Starting websocket server at {}:{}'.format(host, port))
        self.socket_io.init_app(
            self.flask_app,
            **self.init_kwargs
        )
        self.socket_io.run(self.flask_app, port=port, host=host, debug=False)

    def shutdown(self):
        self.socket_io.stop()
        pass
Exemple #2
0
from coco.httpd.ws import ProxyNamespace, ElfinderNamespace

logger = get_logger(__file__)

app = Flask(__name__, template_folder='templates', static_folder='static')
app.config.update(config)
socket_io = SocketIO()
socket_io.on_namespace(ProxyNamespace('/ssh'))
socket_io.on_namespace(ElfinderNamespace('/elfinder'))

if os.environ.get('USE_EVENTLET', '1') == '1':
    init_kwargs = {'async_mode': 'eventlet'}
else:
    init_kwargs = {'async_mode': 'threading'}
socket_io.init_app(app, **init_kwargs),
socket_io.on_error_default(lambda x: logger.exception(x))


class HttpServer:
    @staticmethod
    def run():
        host = config["BIND_HOST"]
        port = config["HTTPD_PORT"]
        print('Starting websocket server at {}:{}'.format(host, port))
        socket_io.run(app, port=port, host=host, debug=False)

    @staticmethod
    def shutdown():
        socket_io.stop()
        pass
Exemple #3
0
class Cgi(object):
    def __init__(self, folder='%s/static' % getcwd()):
        self.events = {
            'push-sio': self.push,
            'create-cgi': self.create,
            'cgi-options': self.decorate
        }
        self.args = {
            'emitter': None,
            'host': '0.0.0.0',
            'port': 5000,
            'logger': None,
            'debug': False,
            'deamon': True,
            'key': 'ssl/host.key',
            'crt': 'ssl/host.crt',
            'env': 'production'
        }
        from flask import Flask
        self.cgi = Flask(__name__,
                         template_folder=folder,
                         static_folder=folder)
        from flask_socketio import SocketIO
        # async_mode eventlet|gevent|threading
        self.socket = SocketIO(
            self.cgi, async_mode='threading', debug=self.args.get(
                'debug'))  # eventlet is best performance, but threading works
        self.socket.on_error_default(
            self.error
        )  # == @socketio.on_error_default | socketio.on_error(None)(handler)
        from flask_login import LoginManager
        self.login = LoginManager(self.cgi)
        self.login.login_view = 'login'  # == url_for(login) # name of the function
        from glob import glob
        path = '%s/static/errors/' % getcwd()
        pages = glob('%s[1-5][0-9][0-9].html' % path)
        for i, page in enumerate(pages):
            pages[i] = int(page.replace(path, '').replace('.html', ''))
        CgiErrors().decorate({'errors': pages}).create(self.cgi)
        CgiRoutes().decorate({'watchdog': 'firebase'}).create(self.cgi)

    def decorate(self, arguments):
        from Process import decorate
        return decorate(self, arguments)

    def create(self, data={}):
        self.cgi.config['HOST'] = self.args.get('host')
        self.cgi.config['PORT'] = self.args.get('port')
        self.cgi.config['DEBUG'] = self.args.get('debug')
        self.cgi.config['ENV'] = self.args.get('env')  # production|development
        if not None == self.args.get('logger'):
            # self.cgi.logger = self.args.get('logger') # error can't set attribute
            if (0 < len(self.cgi.logger.handlers)):
                self.cgi.logger.handlers.pop()
            self.cgi.logger.addHandler(self.args.get('logger'))
        from threading import Thread
        self.thread = Thread(target=self.start)
        self.thread.setDaemon(self.args.get('deamon'))
        self.thread.start()
        return self

    def start(self):
        self.cgi.run(host=self.args.get('host'),
                     ssl_context=(self.args.get('crt'), self.args.get('key')))
        return self

    def error(self, error):
        logging.error('default socket error %s' % str(error))

    def push(self, data):
        namespace = data.get('namespace')
        self.socket.emit('response', {
            'call': '%s-got' % namespace,
            'id': 'push-%s' % namespace,
            'data': data
        },
                         namespace='/%s' % namespace)
Exemple #4
0
class Monitor(object):
    def __init__(self, folder=os.getcwd()):
        self.events = {
            'push-sio': self.push,
            'start-monitor': self.create,
            'monitor-options': self.decorate
        }
        self.args = {
            'emitter': None,
            'host': '0.0.0.0',
            'port': 5000,
            'logger': None,
            'debug': False,
            'deamon': True,
            'namespace': 'default'
        }
        from flask import Flask
        self.cgi = Flask(__name__,
                         template_folder=folder,
                         static_folder=folder)
        from flask_socketio import SocketIO
        # async_mode eventlet|gevent|threading
        self.socket = SocketIO(
            self.cgi, async_mode='threading', debug=self.args.get(
                'debug'))  # eventlet is best performance, but threading works
        self.socket.on_error_default(
            self.error
        )  # == @socketio.on_error_default | socketio.on_error(None)(handler)
        MonitorRoutes().create(self.cgi)
        self.pusher = MonitorSocket().create(self.socket)

    def decorate(self, arguments):
        from Util import decorate
        self.pusher.decorate(arguments)
        return decorate(self, arguments)

    def create(self, data={}):
        self.cgi.config['HOST'] = self.args.get('host')
        self.cgi.config['PORT'] = self.args.get('port')
        self.cgi.config['DEBUG'] = self.args.get('debug')
        if not None == self.args.get('logger'):
            # self.cgi.logger = self.args.get('logger') # error can't set attribute
            if (0 < len(self.cgi.logger.handlers)):
                self.cgi.logger.handlers.pop()
            self.cgi.logger.addHandler(self.args.get('logger'))
        from threading import Thread
        self.thread = Thread(target=self.cgi.run)
        self.thread.setDaemon(self.args.get('deamon'))
        self.thread.start()
        self.pusher.create(self.socket)
        return self

    def error(self, error):
        logging.error('default socket error %s' % str(error))

    def push(self, data):
        namespace = data.get('namespace')
        self.socket.emit('response', {
            'call': '%s-got' % namespace,
            'id': 'push-%s' % namespace,
            'data': data
        },
                         namespace='/%s' % namespace)
Exemple #5
0
class SocketIOServer:
    """Basic server for socketio."""
    
    name: str = None
    app: Flask = None
    socket: SocketIO = None

    _socket_base_url: str = None
    _socket_ip: str = '0.0.0.0'
    _socket_port: int = 7666

    def __init__(self, name: str = None, socket_ip: str = None, socket_port: int = None) -> None:
        """
        Init the api server, and init the super class RPC
        """
        if name is None:
            raise Exception("SocketServer needs distinguishable name for logging purposes")
        
        self.name = '{}.{}'.format(__name__, name)
        self.logger = setup_logger(name=self.name)
        self.logger.info('Initializing %s component.', self.name)

        self.app = Flask(__name__)
        CORS(self.app)

        self.app.config['SECRET_KEY'] = "s!"#$123%!%&!&e!"123424#34534$%!5345%&!&c345!"#234$%!1342334224%&!&et!242!"#$%342!%&!&"
        self.socket = SocketIO(self.app)

        if socket_ip is None:
            self.logger.info("SocketServer got no `socket_ip` defaulting to {}".format(self._socket_ip))
        else:
            self._socket_ip = socket_ip

        if socket_port is None:
            self.logger.info("SocketServer got no `socket_port` defaulting to {}".format(self._socket_port))
        else:
            self._socket_port = socket_port

        self._socket_base_url = '{}:{}'.format(self._socket_ip, self._socket_port)

        self.logger.info("Will serve Socket at %s", self._socket_base_url)

    def Start(self) -> None:
        """
        Spawns the thread that will run the `run` method of SocketServer.
        The `run` method creates the HTTP Server and maps it to the Flask app..
        """
        thread = threading.Thread(target=self.run, daemon=True)
        thread.start()

    def cleanup(self) -> None:
        self.logger.info("Stopping API Server")
        self.srv.shutdown()

    def run(self):
        """
        Method that runs flask-socketio app in its own thread forever.
        """

        self.logger.info(f"Starting Socket Server at {self._socket_base_url}")

        try:
            self.socket.run(self.app, host=self._socket_ip, port=self._socket_port, log_output=True)
        except Exception:
            self.logger.exception("Socket Server failed to start.")

    def json_dump(self, return_value):
        """ Helper function to jsonify object for a webserver """
        return jsonify(return_value)

    def json_error(self, error_msg):
        return jsonify({"error": error_msg}), 502

    def register_base_socket_events(self):
        """
        Registers flask app URLs that are calls to functonality in rpc.rpc.
        First two arguments passed are /URL and 'Label'
        Label can be used as a shortcut when refactoring
        :return:
        """
        # Error handling
        self.socket.on_error_default(self._base_error_handler)
        # Testing
        self.socket.on_event("message", self._base_message_handler, namespace="/")
        self.socket.on_event("json", self._base_json_handler, namespace="/")
        self.socket.on_event("connect", self._base_connection_handler, namespace="/")
        self.socket.on_event("disconnect", self._base_disconnection_handler, namespace="/")

    def register_socket_events(self, events: List[SocketIOEvent]):
        """
        Registers flask-socketio events that are handled by the socket server.
        :param events: is a list of events of type `SocketEvent` from the same module.
        :return:
        """
        # Register the passed events
        for event in events:
            self.socket.on_event(
                message=event.name,
                handler=event.handler,
                namespace=event.namespace,
            )

    def _base_error_handler(self, e):
        """
        Base error handler.
        """
        print("An error has occurred: " + str(e))

    def _base_message_handler(self, message):
        """
        Base message handler.
        """
        print("received message: " + message)
    
    def _base_json_handler(self, message):
        """
        Base json handler.
        """
        print("received json: " + message)
    
    def _base_connection_handler(self, message):
        """
        Base connection handler.
        """
        print("received message: " + message)
    
    def _base_disconnection_handler(self, message):
        """
        Base disconnection handler.
        """
        print("received message: " + message)