__init__.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #! /usr/bin/env python3.5
  2. # Copyright 2017 Digital
  3. #
  4. # This file is part of BeeWatch.
  5. #
  6. # BeeWatch is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # BeeWatch is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with BeeWatch. If not, see <http://www.gnu.org/licenses/>.
  18. import curio
  19. import blinker
  20. import logging
  21. import logging.handlers
  22. import digilib.network
  23. import os
  24. import queue
  25. import select
  26. import socket
  27. import sys
  28. import threading
  29. import time
  30. import traceback
  31. import digilib.pin
  32. import digilib.network
  33. import beewatch
  34. # import beewatch.server
  35. import beewatch.pinapi
  36. log = logging.getLogger(__name__+"")
  37. # lapi = logging.getLogger(__name__+".api")
  38. # lschat = logging.getLogger(__name__+".schat")
  39. lch = logging.getLogger(__name__+".chandler")
  40. lserver = logging.getLogger(__name__+".server")
  41. class ConnHandlerBeeWatch(digilib.network.ConnHandler):
  42. """
  43. ConnHandlerBeeWatch is the connection handler for the BeeWatch server.
  44. It parses commands to api calls.
  45. Todo
  46. ----
  47. Implement a permission system
  48. """
  49. def __init__(self, socket, addr, server):
  50. super(ConnHandlerBeeWatch, self).__init__(socket, addr, server)
  51. async def handle(self, data):
  52. """
  53. The handle method parses commands and responds if a command was not
  54. found. It executes synchronous and asynchronous methods correctly and
  55. logs the traceback if an exception occured.
  56. """
  57. data = data.strip()
  58. data = data.split(" ")
  59. cmd,*args = data
  60. func = beewatch._commands.get(cmd,False)
  61. if not func:
  62. await self.respond("Unknown command")
  63. return
  64. kwargs = {"args":args,"command":cmd,"respond":self.respond}
  65. task = None
  66. try:
  67. coro = func(**kwargs)
  68. if hasattr(coro,"__await__"):
  69. task = await coro
  70. except Exception as e:
  71. lch.error("api_func raised an error:",exc_info=e)
  72. tb = traceback.format_exc()
  73. await self.respond(tb,log_msg="traceback of '{}'"
  74. .format(e.__cause__))
  75. finally:
  76. pass
  77. if task:
  78. lch.debug("exec: "+task.exception.__cause__)
  79. # task joins iself to suppress the "task not joined" warning
  80. cur_task = await curio.current_task()
  81. await curio.ignore_after(0,cur_task.wait)
  82. async def respond(self,text,*args,log_msg=False):
  83. """
  84. this method is passed to apis so they can give feedback to the user
  85. """
  86. await self.send(text,log_msg)
  87. class BeeWatchServer(digilib.network.Server):
  88. """
  89. BeeWatchServer opens a secured connection to the outside world (or a file socket).
  90. BeeWatchServer inherits from digilib.network.Server. It connects to the gpio control socket and adds protetction by requireing user authentification.
  91. Warning
  92. -------
  93. as these features aren't implemented yet, the connection is *not* secure at all
  94. Todo
  95. ----
  96. actually implement these features, right now BeeWatchServer does only debug stuff
  97. Parameters are identical to `digilib.network.Server` if not specified in the following list:
  98. Parameters
  99. ----------
  100. *args:
  101. passed to :obj:`digilib.network.Server`
  102. handler_class:
  103. Same as in `digilib.network.Server` but defaults to :obj:`ConnHandlerBeeWatch`.
  104. **kwargs:
  105. passed to :obj:`digilib.network.Server`
  106. """
  107. def __init__(
  108. self,
  109. *args,
  110. handler_class=ConnHandlerBeeWatch,
  111. **kwargs
  112. ):
  113. super(BeeWatchServer, self).__init__(
  114. *args,
  115. handler_class=handler_class,
  116. **kwargs,
  117. )
  118. def make_socket(self) -> socket.socket :
  119. s = super(BeeWatchServer,self).make_socket()
  120. # only for debugging because I'm impatient and don't want to wait
  121. lch.warning("setting sokopt SO_REUSEADDR to 1. DEBUGGING ONLY")
  122. s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  123. return s
  124. #