gmyth-stream/server/0.3/lib/request_handler.py
author morphbr
Tue May 29 21:24:48 2007 +0100 (2007-05-29)
branchtrunk
changeset 718 3fbcd3d9b2d1
child 723 f5f7abc760aa
permissions -rw-r--r--
[svn r724] * GMyth-Streamer version 0.3 released
- Improved Log architecture;
- Creation of a history for the transcoder's actions
- Creation of an id for each transcoder instanciated
- Also wrapps default actions for python's default logger

- Created new functions to make use of this new Log architecture;
- serve_new_id
- serve_get_log
- serve_get_all_log

- _Lot_ of small bug fixes;

- Inserted header for all files;

- Splited files with too many lines (more than 1 class per file)
in more files;
morphbr@718
     1
#!/usr/bin/env python
morphbr@718
     2
morphbr@718
     3
__author__ = "Gustavo Sverzut Barbieri / Artur Duque de Souza"
morphbr@718
     4
__author_email__ = "barbieri@gmail.com / artur.souza@indt.org.br"
morphbr@718
     5
__license__ = "GPL"
morphbr@718
     6
__version__ = "0.4"
morphbr@718
     7
morphbr@718
     8
import os
morphbr@718
     9
import threading
morphbr@718
    10
import SocketServer
morphbr@718
    11
import BaseHTTPServer
morphbr@718
    12
import socket
morphbr@718
    13
import urlparse
morphbr@718
    14
import cgi
morphbr@718
    15
import lib.utils as utils
morphbr@718
    16
import logging
morphbr@718
    17
morphbr@718
    18
from log import Log
morphbr@718
    19
import lib.transcoder as transcoder
morphbr@718
    20
morphbr@718
    21
__all__ = ("RequestHandler")
morphbr@718
    22
morphbr@718
    23
class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
morphbr@718
    24
    """Class that implements an HTTP request handler for our server."""
morphbr@718
    25
    log = logging.getLogger("gms.request")
morphbr@718
    26
    def_transcoder = None
morphbr@718
    27
    transcoders = utils.PluginSet(transcoder.Transcoder)
morphbr@718
    28
    transcoders_log = Log()
morphbr@718
    29
    tid_queue = []
morphbr@718
    30
morphbr@718
    31
    menu = {
morphbr@718
    32
        "Log": "/get_log.do",
morphbr@718
    33
        "Stop": "/stop-transcoder.do",
morphbr@718
    34
        "Status": "/status.do",
morphbr@718
    35
        "All Log": "/get_all_log.do",
morphbr@718
    36
        "Version": "/version.do",
morphbr@718
    37
        "Shutdown": "/shutdown.do"
morphbr@718
    38
        }
morphbr@718
    39
morphbr@718
    40
    @classmethod
morphbr@718
    41
    def load_plugins_transcoders(cls, directory):
morphbr@718
    42
        cls.transcoders.load_from_directory(directory)
morphbr@718
    43
morphbr@718
    44
        if cls.def_transcoder is None and cls.transcoders:
morphbr@718
    45
            cls.def_transcoder = cls.transcoders[0].name
morphbr@718
    46
    # load_plugins_transcoders()
morphbr@718
    47
morphbr@718
    48
morphbr@718
    49
    def do_dispatch(self, body):
morphbr@718
    50
        self.url = self.path
morphbr@718
    51
morphbr@718
    52
        pieces = urlparse.urlparse(self.path)
morphbr@718
    53
        self.path = pieces[2]
morphbr@718
    54
        self.query = cgi.parse_qs(pieces[4])
morphbr@718
    55
morphbr@718
    56
        if self.path == "/":
morphbr@718
    57
            self.serve_main(body)
morphbr@718
    58
        elif self.path == "/shutdown.do":
morphbr@718
    59
            self.serve_shutdown(body)
morphbr@718
    60
        elif self.path == "/stop-transcoder.do":
morphbr@718
    61
            self.serve_stop_transcoder(body)
morphbr@718
    62
        elif self.path == "/status.do":
morphbr@718
    63
            self.serve_status(body)
morphbr@718
    64
        elif self.path == "/version.do":
morphbr@718
    65
            self.serve_version(body)
morphbr@718
    66
        elif self.path == "/new_id.do":
morphbr@718
    67
            self.serve_new_id(body)
morphbr@718
    68
        elif self.path == "/get_log.do":
morphbr@718
    69
            self.serve_get_log(body)
morphbr@718
    70
        elif self.path == "/get_all_log.do":
morphbr@718
    71
            self.serve_get_all_log(body)
morphbr@718
    72
        elif self.path == "/stream.do":
morphbr@718
    73
            self.serve_stream(body)
morphbr@718
    74
        else:
morphbr@718
    75
            action = self.query.get("action", None)
morphbr@718
    76
            if action and "stream.do" in action:
morphbr@718
    77
                self.serve_stream(body)
morphbr@718
    78
            else:
morphbr@718
    79
                self.send_error(404, "File not found")
morphbr@718
    80
    # do_dispatch()
morphbr@718
    81
morphbr@718
    82
morphbr@718
    83
    def do_GET(self):
morphbr@718
    84
        self.do_dispatch(True)
morphbr@718
    85
    # do_GET()
morphbr@718
    86
morphbr@718
    87
morphbr@718
    88
    def do_HEAD(self):
morphbr@718
    89
        self.do_dispatch(False)
morphbr@718
    90
    # do_HEAD()
morphbr@718
    91
morphbr@718
    92
morphbr@718
    93
    def _nav_items(self):
morphbr@718
    94
        ret = ""
morphbr@718
    95
        for name, url in self.menu.items():
morphbr@718
    96
            ret += utils.getHTML("menu", {"name": name, "url": url})
morphbr@718
    97
morphbr@718
    98
        return ret
morphbr@718
    99
    # _nav_items()
morphbr@718
   100
morphbr@718
   101
    def serve_main(self, body):
morphbr@718
   102
        self.send_response(200)
morphbr@718
   103
        self.send_header("Content-Type", "text/html")
morphbr@718
   104
        self.send_header('Connection', 'close')
morphbr@718
   105
        self.end_headers()
morphbr@718
   106
        if body:
morphbr@718
   107
            self.wfile.write(utils.getHTML("index", {"menu": self._nav_items()}))
morphbr@718
   108
    # serve_main()
morphbr@718
   109
morphbr@718
   110
    def serve_version(self, body):
morphbr@718
   111
        self.send_response(200)
morphbr@718
   112
        self.send_header("Content-Type", "text/html")
morphbr@718
   113
        self.send_header('Connection', 'close')
morphbr@718
   114
        self.end_headers()
morphbr@718
   115
        if body:
morphbr@718
   116
            self.wfile.write("Version: %s" %  __version__)
morphbr@718
   117
morphbr@718
   118
morphbr@718
   119
    def serve_shutdown(self, body):
morphbr@718
   120
        self.send_response(200)
morphbr@718
   121
        self.send_header("Content-Type", "text/html")
morphbr@718
   122
        self.send_header('Connection', 'close')
morphbr@718
   123
        self.end_headers()
morphbr@718
   124
        if body:
morphbr@718
   125
            self.wfile.write(utils.getHTML("shutdown"))
morphbr@718
   126
        self.server.server_close()
morphbr@718
   127
    # serve_shutdown()
morphbr@718
   128
morphbr@718
   129
morphbr@718
   130
    def serve_stop_all_transcoders(self, body):
morphbr@718
   131
        self.send_response(200)
morphbr@718
   132
        self.send_header("Content-Type", "text/html")
morphbr@718
   133
        self.send_header('Connection', 'close')
morphbr@718
   134
        self.end_headers()
morphbr@718
   135
        if body:
morphbr@718
   136
            self.server.stop_transcoders()
morphbr@718
   137
            self.wfile.write(utils.getHTML("stop_all", {"menu": self._nav_items()}))
morphbr@718
   138
    # serve_stop_all_transcoders()
morphbr@718
   139
morphbr@718
   140
morphbr@718
   141
    def serve_stop_selected_transcoders(self, body, tids=[]):
morphbr@718
   142
        self.send_response(200)
morphbr@718
   143
        self.send_header("Content-Type", "text/html")
morphbr@718
   144
        self.send_header('Connection', 'close')
morphbr@718
   145
        self.end_headers()
morphbr@718
   146
        opts = ""
morphbr@718
   147
        if body:
morphbr@718
   148
            transcoders = self.server.get_transcoders()
morphbr@718
   149
morphbr@718
   150
            for tid in tids:
morphbr@718
   151
                for t, r in transcoders:
morphbr@718
   152
                    if t.tid == int(tid):
morphbr@718
   153
                        try:
morphbr@718
   154
                            t.stop()
morphbr@718
   155
                        except Exception, e:
morphbr@718
   156
                            self.log.info("Plugin already stopped")
morphbr@718
   157
morphbr@718
   158
                        opts += utils._create_html_item("%s" % t)
morphbr@718
   159
morphbr@718
   160
                        break
morphbr@718
   161
morphbr@718
   162
                self.wfile.write(utils.getHTML("stop_selected",
morphbr@718
   163
                                               {"menu": self._nav_items(),
morphbr@718
   164
                                                "opts": opts}))
morphbr@718
   165
    # serve_stop_selected_transcoders()
morphbr@718
   166
morphbr@718
   167
morphbr@718
   168
    def serve_stop_transcoder(self, body):
morphbr@718
   169
        req = self.query.get("request", None)
morphbr@718
   170
        tid = self.query.get("tid", None)
morphbr@718
   171
        if req and "all" in req:
morphbr@718
   172
            self.serve_stop_all_transcoders(body)
morphbr@718
   173
        elif tid:
morphbr@718
   174
            self.serve_stop_selected_transcoders(body, tid[0].split(";"))
morphbr@718
   175
        else:
morphbr@718
   176
            self.serve_status(body)
morphbr@718
   177
    # serve_stop_transcoder()
morphbr@718
   178
morphbr@718
   179
morphbr@718
   180
    def serve_status(self, body):
morphbr@718
   181
        self.send_response(200)
morphbr@718
   182
        self.send_header("Content-Type", "text/html")
morphbr@718
   183
        self.send_header('Connection', 'close')
morphbr@718
   184
        self.end_headers()
morphbr@718
   185
        stopone = ""
morphbr@718
   186
morphbr@718
   187
        if body:
morphbr@718
   188
            tl = self.server.get_transcoders()
morphbr@718
   189
            if not tl:
morphbr@718
   190
                running = "<p>No running transcoder.</p>\n"
morphbr@718
   191
                stopall = ""
morphbr@718
   192
                stopone = ""
morphbr@718
   193
morphbr@718
   194
            elif self.query.get("tid", None):
morphbr@718
   195
                req_tid = int(self.query.get("tid")[0])
morphbr@718
   196
                for transcoder, request in tl:
morphbr@718
   197
                    if transcoder.tid == req_tid:
morphbr@718
   198
                        self.wfile.write("Status: %s %%" % transcoder.status)
morphbr@718
   199
                        return True
morphbr@718
   200
morphbr@718
   201
                return False
morphbr@718
   202
morphbr@718
   203
            else:
morphbr@718
   204
                running = "<p>Running transcoders:</p>\n"
morphbr@718
   205
                stopall = utils._create_html_item("<a href='%s?request=all'>"
morphbr@718
   206
                                                 "[STOP ALL]</a>" %
morphbr@718
   207
                                                 self.menu["Stop"])
morphbr@718
   208
morphbr@718
   209
                for transcoder, request in tl:
morphbr@718
   210
                    stopone += utils._create_html_item("%s;"
morphbr@718
   211
                                                       "<a href='%s?tid=%s'>"
morphbr@718
   212
                                                       " [STOP] </a>") % (
morphbr@718
   213
                        transcoder, self.menu["Stop"], transcoder.tid)
morphbr@718
   214
morphbr@718
   215
            self.wfile.write(utils.getHTML("status",
morphbr@718
   216
                                           {"menu": self._nav_items(),
morphbr@718
   217
                                            "running": running,
morphbr@718
   218
                                            "stopall": stopall,
morphbr@718
   219
                                            "stopone": stopone}))
morphbr@718
   220
    # serve_status()
morphbr@718
   221
morphbr@718
   222
morphbr@718
   223
    def _get_transcoder(self):
morphbr@718
   224
        # get transcoder option: mencoder is the default
morphbr@718
   225
        request_transcoders = self.query.get("transcoder", ["mencoder"])
morphbr@718
   226
morphbr@718
   227
        for t in request_transcoders:
morphbr@718
   228
            transcoder = self.transcoders.get(t)
morphbr@718
   229
            if transcoder:
morphbr@718
   230
                return transcoder
morphbr@718
   231
morphbr@718
   232
        if not transcoder:
morphbr@718
   233
            return self.transcoders[self.def_transcoder]
morphbr@718
   234
    # _get_transcoder()
morphbr@718
   235
morphbr@718
   236
morphbr@718
   237
    def _get_new_id(self, tid):
morphbr@718
   238
        self.server.last_tid = utils.create_tid(tid)
morphbr@718
   239
        self.tid_queue.append(self.server.last_tid)
morphbr@718
   240
        return self.server.last_tid
morphbr@718
   241
    # _get_new_id()
morphbr@718
   242
morphbr@718
   243
morphbr@718
   244
    def serve_new_id(self, body):
morphbr@718
   245
        self.send_response(200)
morphbr@718
   246
        self.send_header("Content-Type", "text/html")
morphbr@718
   247
        self.send_header('Connection', 'close')
morphbr@718
   248
        self.end_headers()
morphbr@718
   249
morphbr@718
   250
        if body:
morphbr@718
   251
            self.wfile.write("%s" % self._get_new_id(self.server.last_tid))
morphbr@718
   252
    # serve_new_id()
morphbr@718
   253
morphbr@718
   254
    def serve_get_log(self, body):
morphbr@718
   255
        self.send_response(200)
morphbr@718
   256
        self.send_header("Content-Type", "text/html")
morphbr@718
   257
        self.send_header('Connection', 'close')
morphbr@718
   258
        self.end_headers()
morphbr@718
   259
morphbr@718
   260
        if body:
morphbr@718
   261
            if self.query.get("tid", None):
morphbr@718
   262
                tid = int(self.query.get("tid")[0])
morphbr@718
   263
                stat = self.transcoders_log.get_status(tid)
morphbr@718
   264
                self.wfile.write("%s" % stat)
morphbr@718
   265
            else:
morphbr@718
   266
                stat = self.transcoders_log.get_status()
morphbr@718
   267
                for rtid, status in stat.iteritems():
morphbr@718
   268
                    self.wfile.write("<b>%s</b>: %s<br><br>" % (rtid, status))
morphbr@718
   269
    # serve_get_log()
morphbr@718
   270
morphbr@718
   271
    def serve_get_all_log(self, body):
morphbr@718
   272
        self.send_response(200)
morphbr@718
   273
        self.send_header("Content-Type", "text/html")
morphbr@718
   274
        self.send_header('Connection', 'close')
morphbr@718
   275
        self.end_headers()
morphbr@718
   276
morphbr@718
   277
        if body:
morphbr@718
   278
            if self.query.get("tid", None):
morphbr@718
   279
                tid = int(self.query.get("tid")[0])
morphbr@718
   280
                stat = self.transcoders_log.get_status(tid, True)
morphbr@718
   281
                for status in stat:
morphbr@718
   282
                    self.wfile.write("%s<br><br>" % status)
morphbr@718
   283
            else:
morphbr@718
   284
                stat = self.transcoders_log.get_status(None, True)
morphbr@718
   285
                for rtid, history in stat.iteritems():
morphbr@718
   286
                    for status in history:
morphbr@718
   287
                        self.wfile.write("<b>%s</b>: %s<br>" % (rtid, status))
morphbr@718
   288
                    self.wfile.write("<br><br>")
morphbr@718
   289
    # serve_get_all_log()
morphbr@718
   290
morphbr@718
   291
    def serve_stream(self, body):
morphbr@718
   292
        transcoder = self._get_transcoder()
morphbr@718
   293
        try:
morphbr@718
   294
            obj = transcoder(self.query)
morphbr@718
   295
        except Exception, e:
morphbr@718
   296
            self.send_error(500, str(e))
morphbr@718
   297
            return
morphbr@718
   298
morphbr@718
   299
        self.send_response(200)
morphbr@718
   300
        self.send_header("Content-Type", obj.get_mimetype())
morphbr@718
   301
        self.send_header('Connection', 'close')
morphbr@718
   302
        self.end_headers()
morphbr@718
   303
morphbr@718
   304
        if body:
morphbr@718
   305
            test_tid = int(self.query.get("tid", "0")[0])
morphbr@718
   306
            if test_tid == 0 or test_tid not in self.tid_queue:
morphbr@718
   307
                test_tid = self._get_new_id(self.server.last_tid)
morphbr@718
   308
morphbr@718
   309
            self.transcoders_log.insert(test_tid, "gms.%s" % obj.name)
morphbr@718
   310
            obj.tid = test_tid
morphbr@718
   311
            obj.log = self.transcoders_log
morphbr@718
   312
morphbr@718
   313
            self.server.add_transcoders(self, obj)
morphbr@718
   314
            obj.start(self.wfile)
morphbr@718
   315
            self.server.del_transcoders(self, obj)
morphbr@718
   316
    # serve_stream()
morphbr@718
   317
morphbr@718
   318
morphbr@718
   319
    def log_request(self, code='-', size='-'):
morphbr@718
   320
        self.log.info('"%s" %s %s', self.requestline, str(code), str(size))
morphbr@718
   321
    # log_request()
morphbr@718
   322
morphbr@718
   323
morphbr@718
   324
    def log_error(self, format, *args):
morphbr@718
   325
        self.log.error("%s: %s" % (self.address_string(), format % args))
morphbr@718
   326
    # log_error()
morphbr@718
   327
morphbr@718
   328
morphbr@718
   329
    def log_message(self, format, *args):
morphbr@718
   330
        self.log.info("%s: %s" % (self.address_string(), format % args))
morphbr@718
   331
    # log_message()
morphbr@718
   332
# RequestHandler