#! /usr/bin/env python3.5 # Copyright 2017 Digital # # This file is part of BeeWatch. # # BeeWatch is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # BeeWatch is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with BeeWatch. If not, see . import curio import blinker import logging import logging.handlers import digilib.network import os import queue import select import socket import sys import threading import time import traceback import digilib.pin import digilib.network import beewatch import beewatch.pinapi log = logging.getLogger(__name__+"") # lapi = logging.getLogger(__name__+".api") # lschat = logging.getLogger(__name__+".schat") lch = logging.getLogger(__name__+".chandler") lserver = logging.getLogger(__name__+".server") class BeeWatchServer(digilib.network.Server): """ BeeWatchServer is a subclass of digilib.network.Server. It connects to the gpio control socket and adds protetction by requireing user authentification. This isn't implemented yet. """ def __init__(self,*args,**kwargs): super(BeeWatchServer, self).__init__( *args, handler_class=beewatch.server.ConnHandlerBeeWatch, **kwargs, ) def make_socket(self): s = super(BeeWatchServer,self).make_socket() # only for debugging because I'm impatient and don't want to wait lch.warning("setting sokopt SO_REUSEADDR to 1. DEBUGGING ONLY") s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) return s class ConnHandlerBeeWatch(digilib.network.ConnHandler): """ Connection handler for the beewatch server. Applies permission system, parses commands and tells apis what to do. """ def __init__(self, socket, addr, server): super(ConnHandlerBeeWatch, self).__init__(socket, addr, server) async def handle(self, data): """ The handle method parses commands and responds if a command was not found. It executes synchronous and asynchronous methods correctly and logs the traceback if an exception occured. """ data = data.strip() data = data.split(" ") cmd,*args = data func = beewatch._commands.get(cmd,False) if not func: await self.respond("Unknown command") return kwargs = {"args":args,"command":cmd,"respond":self.respond} task = None try: coro = func(**kwargs) if hasattr(coro,"__await__"): task = await coro except Exception as e: lch.error("api_func raised an error:",exc_info=e) tb = traceback.format_exc() await self.respond(tb,log_msg="traceback of '{}'" .format(e.__cause__)) finally: pass if task: lch.debug("exec: "+task.exception.__cause__) # task joins iself to suppress the "task not joined" warning cur_task = await curio.current_task() await curio.ignore_after(0,cur_task.join) async def respond(self,text,*args,log_msg=False): """ this method is passed to apis so they can give feedback to the user """ await self.send(text,log_msg) #