import requests import json import BaseHTTPServer from threading import Thread class MessageHandler(BaseHTTPServer.BaseHTTPRequestHandler): access_denied_text = """ JunkVision - 403 Forbidden

403 Forbidden

Only LAN is allowed.

Contact BOFHs for access.

""" not_found_text = """ JunkVision - 404 Not Found

404 Not found

""" bad_request_text = """ JunkVision - 400 Bad Request

400 Bad Request

""" def do_GET(self): self.server_version = "JunkVision/0.5" self.sys_version = "" self.protocol_version = "HTTP/1.1" if not self.client_address[0].startswith("10.8.") and self.client_address[0] != "127.0.0.1": self.send_response(403) self.send_default_headers() self.send_header("Content-Type", "text/html; charset=utf-8") self.send_header("Content-Length", "%d" % len(self.access_denied_text)) self.end_headers() self.wfile.write(self.access_denied_text) return data = {} data['json_response'] = self.server.get_default_data() if self.path.startswith("/image/"): try: area = int(self.path.split("/")[2]) except (ValueError, IndexError): self.send_bad_request() # TODO: logging print "Bad request", self.path return img_jpg = self.server.engine.get_image(int(area)) self.send_image(img_jpg) return elif self.path.startswith("/status/"): data['json_response'].append({'type': 'status'}) if self.path == "/status/": for area_id in xrange(len(self.server.engine.get_areas())): data['json_response'].append(self.server.get_status_data(area_id)) else: try: area = int(self.path.split("/")[2]) if area < 0 or area > len(self.server.engine.get_areas()): raise IndexError("Area out of range") data['json_response'].append(self.server.get_status_data(area)) except (ValueError, IndexError): self.send_bad_request() # TODO: logging print "Bad request", self.path return else: self.send_response(404) self.send_default_headers() self.send_header("Content-Type", "text/html; charset=utf-8") self.send_header("Content-Length", "%d" % len(self.not_found_text)) self.end_headers() self.wfile.write(self.not_found_text) return self.send_response(200) self.send_default_headers() self.send_header("Content-Type", "application/json; charset=utf-8") json_text = json.dumps(data) self.send_header("Content-Length", "%d" % len(json_text)) self.send_header("Cache-Control", "max-age=60") self.end_headers() self.wfile.write(json_text) def send_default_headers(self): self.send_header("Connection", "close") self.send_header("Transfer-Encoding", "identity") self.send_header("Allow", "GET") def send_bad_request(self): self.send_response(400) self.send_default_headers() self.send_header("Content-Type", "text/html; charset=utf-8") self.send_header("Content-Length", "%d" % len(self.bad_request_text)) self.end_headers() self.wfile.write(self.bad_request_text) def send_image(self, img): self.send_response(200) self.send_default_headers() # XXX: parametrize? self.send_header("Content-Type", "image/jpeg") self.send_header("Content-Length", "%d" % len(img)) self.send_header("Cache-Control", "no-store") self.end_headers() self.wfile.write(img) class MessageServer(BaseHTTPServer.HTTPServer): def __init__(self, engine): BaseHTTPServer.HTTPServer.__init__(self, ("0.0.0.0", 4580), MessageHandler) self.engine = engine self.camera_id = "Unknown" self.enabled = False def set_camera_id(self, camera_id): self.camera_id = camera_id def set_status_target(self, status_url): self.status_target = status_url def get_default_data(self): return [{"camera_id": self.camera_id}] def get_status_data(self, area_id): return { "area_id": area_id, "area_rect": self.engine.get_areas()[area_id], "last_movement": self.engine.get_movement_time(area_id), "last_percent_mess": self.engine.get_percent_mess(area_id) } def send_status(self, area_id=-1): data = {} data['status'] = self.get_default_data() if area_id < 0: for area_id in engine.get_areas(): data['status'].append(self.get_status_data(area_id)) else: data['status'].append(self.get_status_data(area_id)) json_text = json.dumps(data) headers = [("Content-Type", "application/json; charset=utf-8"), ("Content-Length", "%d" % len(json_text)), ("Server", "JunkVision/0.5")] resp = requests.post(self.status_target, data=json_text, headers=headers) # TODO: logging print resp def start(self): if self.enabled: raise RuntimeError("Message handler is already started!") self.thread = Thread(target=self.run, name="JunkVision MessageHandler") self.enabled = True self.thread.start() def stop(self): self.enabled = False self.thread.join() def run(self): while self.enabled: self.handle_request()