From 1621a27167041e191289c0eac9a5e1fda84b752a Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Wed, 12 Jun 2013 21:37:12 +0200 Subject: beinc_server nearly done --- beinc_server.json | 1 + beinc_server.py | 205 ++++++++++++++++++++++++++++++++++++++++++++---------- bins_server.py | 140 ------------------------------------- 3 files changed, 168 insertions(+), 178 deletions(-) delete mode 100755 bins_server.py diff --git a/beinc_server.json b/beinc_server.json index 0604d36..1743239 100644 --- a/beinc_server.json +++ b/beinc_server.json @@ -11,6 +11,7 @@ "name": "test", "password": "changeme", "osd_system": "none", + "osd_timeout": 5000, "queue_size": 4 } ] diff --git a/beinc_server.py b/beinc_server.py index a39dd05..cad8d61 100755 --- a/beinc_server.py +++ b/beinc_server.py @@ -15,6 +15,154 @@ __version__ = '1.0-beta' __license__ = "GPL3" +BEINC_OSD_TYPE_NONE = 0 +BEINC_OSD_TYPE_PYNOTIFY = 1 + + + +class BEINCInstance(object): + """ + """ + + def __init__(self, instance_dict): + """ + """ + self.__instance_dict = instance_dict + try: + self.__name = instance_dict['name'] + self.__osd_type = BEINC_OSD_TYPE_NONE + self.__password = instance_dict['password'] + self.__queue_size = int(instance_dict['queue_size']) + self.__message_queue = list() + self.__osd_notification = None + + except Exception as e: + sys.stderr.write( + 'Instance processing error {0}:\n{1}\n'.format(self.__name, + e)) + sys.exit(1) + + + if instance_dict['osd_system'].lower() == 'pynotify': + if not pynotify: + sys.stderr.write( + 'This server does not possess pynotify capability\n') + sys.stderr.write( + "Remove the instance {0} or define it with 'osd_system': 'none'") + sys.exit(1) + + try: + self.__osd_notification = pynotify.Notification(' ') + self.__osd_notification.set_timeout( + instance_dict['osd_timeout']) + self.__osd_notification.set_property( + 'app_name', + '{0} {1}'.format(sys.argv[0], __version__)) + except Exception as e: + sys.stderr.write( + 'Unable to set up a notification object for {0} ({1})\n') + sys.exit(1) + + self.__osd_type = BEINC_OSD_TYPE_PYNOTIFY + + + @property + def name(self): + """ + name-property for the server instance + """ + return self.__name + + + @property + def queueable(self): + """ + name-property for the server instance + """ + return bool(self.__queue_size) + + + def password_match(self, password): + """ + Returns True if 'passowrd' matches the instance-password, + otherwise - False + """ + if self.__password == password: + return True + + return False + + + def send_message(self, title, message): + """ + Displays or enqueues the message, + depending on the instance's type in regard to the osd_system + """ + if self.__osd_type == BEINC_OSD_TYPE_PYNOTIFY: + self.__send_pynotify_messaage(title, message) + else: + self.____send_message_to_queue(title, message) + + + def get_queue(self): + """ + Reruens a json representation of the message queue + """ + jstr = json.dumps(self.__message_queue) + self.__message_queue = list() + return jstr + + + def __send_pynotify_messaage(self, title, message): + """ + Displays pynotify message + """ + + self.__osd_notification.set_properties(summary=title, body=message) + self.__osd_notification.show() + + + def __send_message_to_queue(self, title, message): + """ + Enqueues the message + """ + + if len(self.__message_queue) >= self.__queue_size: + self.__message_queue.pop(0) + + self.__message_queue.append({'title': title, 'message': message}) + + + +def beinc_instance_login(method): + """ + decorator for checking login credentials + """ + + def tmp_func(self, *args, **kwargs): + + if not args: + raise cherrypy.HTTPError(400) + + print('args: {0}'.format(args)) + print('kwargs: {0}'.format(kwargs)) + print(cherrypy.request.config) + + try: + instance = self.__instances(args[0]) + except Exception as e: + raise cherrypy.HTTPError('403 Forbidden', + 'Wrong instance or password') + + if not instance.password_match(kwargs.get('password')): + raise cherrypy.HTTPError('403 Forbidden', + 'Wrong instance or password') + + method(self, *args, **kwargs) + + return tmp_func + + class WebNotifyServer(object): @@ -23,15 +171,13 @@ class WebNotifyServer(object): """ self.__config = config self.__instances = dict() - self.__queues = dict() try: for instance in self.__config['server']['instances']: - self.__queues[instance['name']] = list() - self.__instances[instance['name']] = instance + self.__instances[instance['name']] = BEINCInstance(instance) except Exception as e: - sys.stderr.write('Unable to initialize queues: {0}'.format(e)) + sys.stderr.write('Unable to initialize queues: {0}\n'.format(e)) sys.exit(1) @@ -52,47 +198,20 @@ class WebNotifyServer(object): @cherrypy.expose + @beinc_instance_login def push(self, *args, **kwargs): - if not args: - raise cherrypy.HTTPError(400) - - print('args: {0}'.format(args)) - print('kwargs: {0}'.format(kwargs)) - - instance = self.__get_instance(args[0]) - - if not kwargs.get('password') == instance['password']: - raise cherrypy.HTTPError('403 Forbidden', - 'Wrong instance or password') - + instance = self.__instances(args[0]) return 'OK' - def __get_instance(self, name): - """ - returns a matching 'instance' dictionary - - cherrypy.HTTPError - "403 Forbidden" is raised if no - instance matches 'name' - """ - - try: - for instance in self.__config['server']['instances']: - if name == instance['name']: - return instance - - except Exception as e: - raise cherrypy.HTTPError('403 Forbidden', - 'Wrong instance or password: {0}'.format(e)) - - raise cherrypy.HTTPError("403 Forbidden", "Wrong instance or password") + @cherrypy.expose + @beinc_instance_login + def pull(self, *args, **kwargs): + instance = self.__instances(args[0]) + return 'OK' - # mappings = [ - # (r'^/push/', push), - # (r'^.*$', default), - # ] def main(): @@ -151,6 +270,16 @@ def main(): 'server.ssl_private_key': config_dict['server']['general']['ssl_private_key'], }) + try: + import pynotify + if not pynotify.init("BEINC Notify"): + sys.stderr.write('pynotify.init failed! Exiting...\n') + sys.exit(1) + except Exception as e: + sys.stderr.write( + 'Notice: pynotify support unavailable ({0})\n'.format(e)) + pynotify = False + try: cherrypy.quickstart(WebNotifyServer(config_dict)) diff --git a/bins_server.py b/bins_server.py deleted file mode 100755 index 68ccb74..0000000 --- a/bins_server.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import argparse -import getpass -import json -import os -import sys - -import cherrypy - -import settings - - -class CustomSocketServer(SocketServer.TCPServer): - - def __init__(self, server_address, RequestHandlerClass, queue): - SocketServer.TCPServer.__init__(self, - server_address, - RequestHandlerClass) - self.queue = queue - - -class MyTCPHandler(SocketServer.StreamRequestHandler): - """ - The RequestHandler class for our server. - - It is instantiated once per connection to the server, and must - override the handle() method to implement communication to the - client. - """ - - def handle(self): - - data = self.rfile.readline().strip() - - if self.server.queue.qsize() > 3: - self.server.queue.get() - - self.server.queue.put(data) - #print(self.data) - - -class WebNotifyServer(object): - - def __init__(self, queue): - self.queue = queue - - @cherrypy.expose - def notifications(self): - - entry_list = list() - - while not self.queue.empty(): - entry_list.append(self.queue.get(False)) - - #print (json.dumps(entry_list, sort_keys=True, indent=4)) - return json.dumps(entry_list) - - -def socket_server(queue): - - try: - server = CustomSocketServer((settings.SOCKET_SERVER_HOST, - settings.SOCKET_SERVER_PORT), - MyTCPHandler, - queue) - server.serve_forever() - - except Exception as e: - sys.stderr.write("SocketServer error: {0}".format(e)) - sys.exit(1) - - sys.exit(0) - - - -def web_server(queue): - - cherrypy.config.update({ - 'server.socket_host': settings.WEB_SERVER_HOST, - 'server.socket_port': settings.WEB_SERVER_PORT, - 'server.ssl_module': 'pyopenssl', - 'server.ssl_certificate': settings.WEB_SERVER_CERT, - 'server.ssl_private_key': settings.WEB_SERVER_KEY, - }) - - try: - - cherrypy.quickstart(WebNotifyServer(queue)) - - except Exception as e: - sys.stderr.write("WebServer error: {0}".format(e)) - sys.exit(1) - - sys.exit(0) - - -def main(): - - parser = argparse.ArgumentParser(description='The following options are available') - - - parser.add_argument('-d', - action='store_true', - dest='daemonize', - default=False, - help='daemonize the server process') - - parser.add_argument('-H', '--hostname', - metavar='HOSTNAME', - type=str, - dest='hostname', - default='127.0.0.1', - help="Server IP / hostname") - - parser.add_argument('-P', '--port', - metavar='PORT', - type=int, - dest='port', - default='9998', - help="Server port") - - parser.add_argument('-p', '--password', - metavar='PASSWORD', - type=str, - dest='password', - help="Access password for the BOINS server") - - parser.add_argument('-v', '--version', - action='version', - version='%(prog)s {0}'.format(__VERSION__), - help='display program-version and exit') - - - - sys.exit(0) - -if __name__ == "__main__": - main() -- cgit v1.3