diff -r 2061bf4c30c7 -r daa61fffb811 gmyth-stream/server/lib/request_handler.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/server/lib/request_handler.py Wed Aug 29 14:42:10 2007 +0100 @@ -0,0 +1,470 @@ +#!/usr/bin/env python + +__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza" +__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br" +__license__ = "GPL" +__version__ = "0.3" + +import os +import cgi +import socket +import logging +import urlparse +import threading +import SocketServer +import BaseHTTPServer +import mimetypes + +import lib.utils as utils +import lib.file_handler as files +import lib.transcoder as transcoder + +from log import Log + +__all__ = ("RequestHandler") + +class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): + """Class that implements an HTTP request handler for our server.""" + log = logging.getLogger("gms.request") + def_transcoder = None + transcoders = utils.PluginSet(transcoder.Transcoder) + transcoders_log = Log() + tid_queue = [] + + menu = { + "Log": "/get_log.do", + "Stop": "/stop-transcoder.do", + "Status": "/status.do", + "All Log": "/get_all_log.do", + "Version": "/version.do", + "Shutdown": "/shutdown.do" + } + + @classmethod + def load_plugins_transcoders(cls, directory): + cls.transcoders.load_from_directory(directory) + + if cls.def_transcoder is None and cls.transcoders: + cls.def_transcoder = cls.transcoders[0].name + # load_plugins_transcoders() + + + def do_dispatch(self, body): + self.url = self.path + pieces = urlparse.urlparse(self.path) + self.path = pieces[2] + self.query = cgi.parse_qs(pieces[4]) + + url = { + "/": self.serve_main, + "/shutdown.do": self.serve_shutdown, + "/stop-transcoder.do": self.serve_stop_transcoder, + "/status.do": self.serve_status, + "/version.do": self.serve_version, + "/new_id.do": self.serve_new_id, + "/get_log.do": self.serve_get_log, + "/get_all_log.do": self.serve_get_all_log, + "/stream.do": self.serve_stream, + "/transcode.do": self.serve_transcode, + "/list.do": self.serve_list, + "/get_file_info.do": self.serve_file_info, + } + + try: + url[self.path](body) + except KeyError: + try: + action = self.query.get("action", None) + if action and "stream.do" in action: + self.serve_stream(body) + elif os.path.exists("html/%s" % self.path): + data = open("html/%s" % self.path) + self.wfile.write(data.read()) + else: + self.send_error(404, "File not found") + except Exception, e: + self.log.error(e) + + # do_dispatch() + + + def do_GET(self): + self.do_dispatch(True) + # do_GET() + + + def do_HEAD(self): + self.do_dispatch(False) + # do_HEAD() + + + def _nav_items(self): + ret = "" + for name, url in self.menu.items(): + ret += utils.getHTML("menu", {"name": name, "url": url}) + return ret + # _nav_items() + + + def serve_main(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()})) + # serve_main() + + + def serve_version(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.wfile.write("Version: %s" % __version__) + # serve_version + + + def serve_shutdown(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.wfile.write(utils.getHTML("shutdown")) + self.server.server_close() + # serve_shutdown() + + + def serve_list(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + file_list = [] + files.list_media_files(utils.config.get_transcoded_location(), file_list) + output = files.FileList(map(lambda x, y: x+y, file_list, + ["
"]*len(file_list))) + self.wfile.write(output) + + # serve_list() + + + def serve_stop_all_transcoders(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + if body: + self.server.stop_transcoders() + self.wfile.write(utils.getHTML("stop_all", + {"menu": self._nav_items()})) + # serve_stop_all_transcoders() + + + def serve_stop_selected_transcoders(self, body, tids=[]): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + opts = "" + if body: + transcoders = self.server.get_transcoders() + + for tid in tids: + for t, r in transcoders: + if t.tid == int(tid): + try: + t.stop() + except Exception, e: + self.log.info("Plugin already stopped") + + opts += utils._create_html_item("%s" % t) + + break + + self.wfile.write(utils.getHTML("stop_selected", + {"menu": self._nav_items(), + "opts": opts})) + # serve_stop_selected_transcoders() + + + def serve_stop_transcoder(self, body): + req = self.query.get("request", None) + tid = self.query.get("tid", None) + if req and "all" in req: + self.serve_stop_all_transcoders(body) + elif tid: + self.serve_stop_selected_transcoders(body, tid[0].split(";")) + else: + self.serve_status(body) + # serve_stop_transcoder() + + + def serve_status(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + stopone = "" + running = "" + stopall = "" + + if body: + tl = self.server.get_transcoders() + if not tl and not self.query.get("tid", None) and \ + not self.query.get("running", None): + running = "

No running transcoder.

\n" + + elif not tl and self.query.get("tid", None): + tids = self.query.get("tid") + for tid in tids: + stat = self.transcoders_log.get_status(int(tid)) + self.wfile.write("%s
" % stat) + return True + + elif self.query.get("running", None): + for transcoder, request in tl: + outf = transcoder.params_first("outfile") + tid = transcoder.tid + self.wfile.write("%s:%s
" % (tid, outf)) + return True + + elif self.query.get("tid", None): + req_tid = self.query.get("tid") + for transcoder, request in tl: + if str(transcoder.tid) in req_tid: + self.wfile.write("Status:%s:%s %%" % (\ + transcoder.tid, transcoder.status)) + return True + stat = self.transcoders_log.get_status(int(req_tid[0])) + self.wfile.write("%s
" % stat) + return True + + else: + running = "

Running transcoders:

\n" + stopall = utils._create_html_item("" + "[STOP ALL]" % + self.menu["Stop"]) + + for transcoder, request in tl: + stopone += utils._create_html_item("%s;" + "" + " [STOP] ") % ( + transcoder, self.menu["Stop"], transcoder.tid) + + self.wfile.write(utils.getHTML("status", + {"menu": self._nav_items(), + "running": running, + "stopall": stopall, + "stopone": stopone})) + # serve_status() + + + def _get_transcoder(self): + # get transcoder option: mencoder is the default + request_transcoders = self.query.get("transcoder", ["mencoder"]) + + for t in request_transcoders: + transcoder = self.transcoders.get(t) + if transcoder: + return transcoder + + if not transcoder: + return self.transcoders[self.def_transcoder] + # _get_transcoder() + + + def _get_new_id(self, tid): + self.server.last_tid = utils.create_tid(tid) + self.tid_queue.append(self.server.last_tid) + return self.server.last_tid + # _get_new_id() + + + def serve_new_id(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + self.wfile.write("%s" % self._get_new_id(self.server.last_tid)) + # serve_new_id() + + def serve_get_log(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + if self.query.get("tid", None): + tid = int(self.query.get("tid")[0]) + stat = self.transcoders_log.get_status(tid) + self.wfile.write("Status: %s" % stat) + else: + stat = self.transcoders_log.get_status() + for rtid, status in stat.iteritems(): + self.wfile.write("%s: %s

" % (rtid, status)) + # serve_get_log() + + def serve_get_all_log(self, body): + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + if body: + if self.query.get("tid", None): + tid = int(self.query.get("tid")[0]) + stat = self.transcoders_log.get_status(tid, True) + for status in stat: + self.wfile.write("%s

" % status) + else: + stat = self.transcoders_log.get_status(None, True) + for rtid, history in stat.iteritems(): + for status in history: + self.wfile.write("%s: %s
" % (rtid, status)) + self.wfile.write("

") + # serve_get_all_log() + + + def serve_file_info(self, body): + if body: + + file_dat = self.query.get("file", None) + + if file_dat: + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.send_header('Connection', 'close') + self.end_headers() + + try: + opts = files.TranscodedFile(file_dat[0], self.query).opts + for key in opts.keys(): + self.wfile.write("%s=%s
" % (key, opts.get(key, "None")[0])) + + except Exception, e: + self.send_error(500, str(e)) + return + # serve_file_info() + + def serve_stream(self, body): + args = self.query.get("file", None) + if not args: + self.send_error(404, "File not found") + return + + filename = args[0]; + if not filename: + self.send_error(404, "File not found") + return + + #Only stream files on .transcode dir + filename = os.path.join (utils.config.get_transcoded_location(), + os.path.basename(filename)) + self.log.error("Stream file: %s" % filename) + if not os.path.exists (filename): + self.send_error(404, "File not found") + return + + size = int(os.path.getsize(filename)) + self.send_response(200) + self.send_header("Content-Type", mimetypes.guess_type(filename)[0]) + self.send_header("Cache-Control","no-cache") + self.send_header("Content-Length", size) + self.end_headers() + + media = open(filename) + data_in = " " + total_read = 0 + + test_tid = int(self.query.get("tid", "0")[0]) + if test_tid == 0 or test_tid not in self.tid_queue: + test_tid = self._get_new_id(self.server.last_tid) + + self.transcoders_log.insert(test_tid, "gms.Stream: %s" % filename) + + try: + file_data = "" + while data_in != "": + data_in = media.read(4096) + file_data += data_in + + #total_read += 4096 + self.wfile.write(file_data) + #status = utils.progress_bar(total_read, size, 50) + #msg_status = "Status:%s:%s%%" % (test_tid, status) + #self.transcoders_log._update_status(test_tid, msg_status) + + self.transcoders_log._update_status(test_tid, "OK: Done") + + except Exception, e: + self.log.error("Stream error: %s" %e) + self.transcoders_log._update_status(test_tid, "Error: %s" % e) + # serve_stream() + + def serve_transcode(self, body): + type = self.query.get("type", None)[0] + if type.upper() == "FILE": + self.send_error(404, "Transcode local files not allowed") + return + + transcoder = self._get_transcoder() + try: + obj = transcoder(self.query) + except Exception, e: + self.send_error(500, str(e)) + return + + self.send_response(200) + self.send_header("Content-Type", obj.get_mimetype()) + self.send_header("Cache-Control","no-cache") + + if (obj.name == "gmencoder"): + self.send_header("Transfer-Encoding", "chunked") + + self.end_headers() + + if body: + test_tid = int(self.query.get("tid", "0")[0]) + if test_tid == 0 or test_tid not in self.tid_queue: + test_tid = self._get_new_id(self.server.last_tid) + + if self.query.get("transcoder", None): + self.transcoders_log.insert(test_tid, "gms.%s" % obj.name) + obj.tid = test_tid + obj.log = self.transcoders_log + + self.server.add_transcoders(self, obj) + if obj.start(self.wfile): + self.transcoders_log.info (test_tid, "OK") + else: + self.transcoders_log.info (test_tid, "Fail") + + self.server.del_transcoders(self, obj) + files.TranscodedFile("", self.query) + + # serve_stream() + + + def log_request(self, code='-', size='-'): + self.log.info('"%s" %s %s', self.requestline, str(code), str(size)) + # log_request() + + + def log_error(self, format, *args): + self.log.error("%s: %s" % (self.address_string(), format % args)) + # log_error() + + + def log_message(self, format, *args): + self.log.info("%s: %s" % (self.address_string(), format % args)) + # log_message() + +# RequestHandler