Changeset e58af05


Ignore:
Timestamp:
Dec 27, 2011, 11:33:55 PM (12 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
ce2abc5
Parents:
7c143c9
git-author:
Jessica B. Hamrick <jhamrick@…> (12/27/11 23:33:55)
git-committer:
Jessica B. Hamrick <jhamrick@…> (12/27/11 23:33:55)
Message:

Implement send-document operation and add threading so that the gutenbach server can play jobs

Location:
server/lib
Files:
1 added
6 edited
1 moved

Legend:

Unmodified
Added
Removed
  • server/lib/gutenbach/ipp/attributes/operation.py

    ree8e6d0 re58af05  
    22    'PrinterUri',
    33    'RequestingUserName',
     4    'IppAttributeFidelity',
     5    'LastDocument'
    46]
    57
     
    79from .. import Value
    810from .. import errors
    9 from .. import CharacterStringTags
     11from .. import CharacterStringTags, IntegerTags
    1012
    1113def PrinterUri(val):
     
    2123def IppAttributeFidelity(val):
    2224    raise errors.ClientErrorAttributes, 'ipp-attribute-fidelity'
     25
     26def LastDocument(val):
     27    return Attribute(
     28        'last-document',
     29        [Value(IntegerTags.BOOLEAN, val)])
  • server/lib/gutenbach/server/__init__.py

    ree8e6d0 re58af05  
    1 from server import GutenbachIPPServer
     1import errors
     2from errors import *
     3__all__ = ['errors']
     4__all__.extend(errors.__all__)
     5
     6from job import Job
     7__all__.append('Job')
     8
     9from printer import GutenbachPrinter
     10__all__.append('GutenbachPrinter')
     11
     12from requests import make_empty_response, GutenbachRequestHandler
     13__all__.append('make_empty_response')
     14__all__.append('GutenbachRequestHandler')
     15
     16from server import GutenbachServer, IPPServer
     17__all__.append('GutenbachServer')
     18__all__.append('IPPServer')
     19
    220import BaseHTTPServer
    321import logging
     
    523import traceback
    624
    7 # configure logging
     25# configure and initialize logging
    826logging.basicConfig(level=logging.DEBUG)
    9 
    10 # initialize logger
    1127logger = logging.getLogger(__name__)
    1228
    13 def error(self, request, client_address):
     29def error(self, request=None, client_address=None):
    1430    logger.fatal(traceback.format_exc())
     31    self.gutenbach_server.request_stop = True
    1532    sys.exit(1)
    1633
    1734def start():
     35    logger.info("Starting Gutenbach server...")
     36    gutenbach = GutenbachServer()
     37    gutenbach.start()
     38
     39    logger.info("Starting IPP server...")
    1840    server_address = ('', 8000)
    19     httpd = BaseHTTPServer.HTTPServer(server_address, GutenbachIPPServer)
     41    httpd = BaseHTTPServer.HTTPServer(server_address, IPPServer)
    2042    httpd.handle_error = error.__get__(httpd)
    21     httpd.serve_forever()
     43    httpd.gutenbach_server = gutenbach
     44    while gutenbach.isAlive():
     45        try:
     46            httpd.handle_request()
     47        except:
     48            error(httpd)
    2249
    23 if __name__ == "__main__":
    24     start()
     50__all__.append('start')
  • server/lib/gutenbach/server/errors.py

    rc16ebf6 re58af05  
     1__all__ = [
     2    'InvalidJobException',
     3    'InvalidPrinterStateException'
     4    ]
     5
    16class InvalidJobException(Exception):
    27    def __init__(self, jobid):
  • server/lib/gutenbach/server/job.py

    ree8e6d0 re58af05  
    1 from exceptions import InvalidJobException, InvalidPrinterStateException
     1from . import InvalidJobException, InvalidPrinterStateException
    22import os
    33import gutenbach.ipp as ipp
     
    2424        This sets the status to 'initializing' and optionally sets the
    2525        document to print to the value of document.
     26
    2627        """
    2728
     
    3334        self.size     = size
    3435
    35         self.status   = ipp.JobStates.PENDING
     36        self.document = None
     37        self.document_name = None
     38
     39        self.status   = ipp.JobStates.HELD
    3640
    3741    def __getattr__(self, attr):
     
    9296
    9397    def play(self):
    94         if self.status != 'active':
    95             raise InvalidJobException(
    96                 "Cannot play an inactive job!")
    97        
    98         self.status = const.JobStates.PROCESSING
     98        logger.info("playing job %s" % str(self))
    9999        # TODO: add external call to music player
    100         print "Playing job %s" % str(self)
     100        self.status = ipp.JobStates.PROCESSING
    101101        self.printer.complete_job(self.jid)
    102102
    103103    def finish(self):
    104         self.status = const.JobStates.COMPLETE
     104        logger.info("finished job %s" % str(self))
     105        self.status = ipp.JobStates.COMPLETE
    105106
    106107    def __repr__(self):
  • server/lib/gutenbach/server/printer.py

    r7c143c9 re58af05  
    11#import alsaaudio as aa
    2 from .exceptions import InvalidJobException, InvalidPrinterStateException
    3 from .job import Job
     2from . import InvalidJobException, InvalidPrinterStateException
     3from . import Job
    44import gutenbach.ipp as ipp
    55import logging
     
    221221        return job
    222222
     223    def send_document(self, jobid, document):
     224        job = self.jobs[jobid]
     225        if job.status != ipp.JobStates.HELD:
     226            raise InvalidPrinterStateException(
     227                "Invalid job state: %d" % job.status)
     228        job.document = document
     229        job.status = ipp.JobStates.PENDING
     230
    223231    def print_job(self, job):
    224232        pass
     
    226234    def complete_job(self, jobid):
    227235        job = self.jobs[self.active_jobs.pop(0)]
    228         if job.jobid != jobid:
    229             raise InvalidJobException(
    230                 "Completed job %d has unexpected job id %d!" % \
    231                 (job.jobid, jobid))
    232        
    233236        self.finished_jobs.append(job)
    234237        job.finish()
    235         return job.jobid
     238        return job.jid
    236239
    237240    def start_job(self, jobid):
    238241        job = self.jobs[self.active_jobs[0]]
    239         if job.jobid != jobid:
    240             raise InvalidJobException(
    241                 "Completed job %d has unexpected job id %d!" % \
    242                 (job.jobid, jobid))
    243 
    244         if job.status == 'playing':
     242        if job.status != ipp.JobStates.PENDING:
    245243            raise InvalidPrinterStateException(
    246                 "Next job in queue (id %d) is " + \
    247                 "already playing!" % jobid)
    248 
     244                "Invalid job state: %s" % job.status)
    249245        job.play()
     246
     247    @property
     248    def next_job(self):
     249        if len(self.active_jobs) == 0:
     250            job = None
     251        else:
     252            job = self.active_jobs[0]
     253        return job       
    250254
    251255    def get_job(self, jobid):
  • server/lib/gutenbach/server/requests.py

    r7c143c9 re58af05  
    1 from gutenbach.server.printer import GutenbachPrinter
    21import gutenbach.ipp as ipp
    32import logging
     
    4039class GutenbachRequestHandler(object):
    4140
    42     def __init__(self):
    43         self.printers = {
    44             "test": GutenbachPrinter(name="test")
    45             }
    46         self.default = "test"
     41    def __init__(self, gutenbach_server):
     42        self.gutenbach_server = gutenbach_server
     43        self.printer = gutenbach_server.printer
    4744
    4845    def generic_handle(self, request):
     
    223220        if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    224221            raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    225         if printer_name not in self.printers:
     222        if printer_name != self.printer.name:
    226223            raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    227         jobs = self.printers[printer_name].get_jobs()
    228224
    229225        # get the job attributes and add them to the response
    230         for job in self.printers[printer_name].get_jobs():
     226        for job in self.printer.get_jobs():
    231227            attrs = job.get_job_attributes(operation)
    232228            response.attribute_groups.append(ipp.AttributeGroup(
     
    295291        if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    296292            raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    297         if printer_name not in self.printers:
     293        if printer_name != self.printer.name:
    298294            raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    299295
    300296        # get attributes from the printer and add to response
    301         job = self.printers[printer_name].create_job(request)
     297        job = self.printer.create_job(request)
    302298        response.attribute_groups.append(ipp.AttributeGroup(
    303299            ipp.AttributeTags.JOB, job.get_job_attributes(operation)))
     
    357353        if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    358354            raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    359         if printer_name not in self.printers:
     355        if printer_name != self.printer.name:
    360356            raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    361         printer = self.printers[printer_name]
     357        printer = self.printer
    362358
    363359        # get attributes from the printer and add to response
     
    377373    @handler_for(ipp.OperationCodes.SEND_DOCUMENT)
    378374    def send_document(self, request, response):
    379         raise ipp.errors.ServerErrorOperationNotSupported
     375        operation = request.attribute_groups[0]
     376
     377        # requested printer uri
     378        if 'printer-uri' in operation:
     379            uri_attr = operation['printer-uri']
     380            printer_name = uri_attr.values[0].value.split("/")[-1]
     381            if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
     382                raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
     383            if printer_name != self.printer.name:
     384                raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
     385        printer = self.printer
     386
     387        if 'job-id' not in operation:
     388            raise ipp.errors.ClientErrorBadRequest("Missing 'job-id' attribute")
     389        job_id_attr = operation['job-id']
     390        job_id = job_id_attr.values[0].value
     391        if job_id_attr != ipp.JobId(job_id_attr.values[0].value):
     392            raise ipp.errors.ClientErrorBadRequest(str(job_id_attr))
     393        if job_id not in printer.jobs:
     394            raise ipp.errors.ClientErrorAttributes(str(job_id_attr))
     395        job = printer.jobs[job_id]
     396
     397        if 'last-document' not in operation:
     398            raise ipp.errors.ClientErrorBadRequest("Missing 'last-document' attribute")
     399        last_attr = operation['last-document']
     400        last = last_attr.values[0].value
     401        if last_attr != ipp.LastDocument(last):
     402            raise ipp.errors.ClientErrorBadRequest(str(last_attr))
     403        if not last:
     404            raise ipp.errors.ServerErrorMultipleJobsNotSupported
     405
     406        printer.send_document(job_id, request.data)
     407        attrs = job.get_job_attributes()
     408        response.attribute_groups.append(ipp.AttributeGroup(
     409            ipp.AttributeTags.JOB, attrs))
    380410
    381411    @handler_for(ipp.OperationCodes.SEND_URI)
     
    385415    @handler_for(ipp.OperationCodes.GET_JOB_ATTRIBUTES)
    386416    def get_job_attributes(self, request, response):
    387        
    388417        operation = request.attribute_groups[0]
    389418
     
    395424        if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    396425            raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    397         if printer_name not in self.printers:
     426        if printer_name != self.printer.name:
    398427            raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    399         printer = self.printers[printer_name]
     428        printer = self.printer
    400429
    401430        if 'job-id' not in operation:
     
    459488
    460489        operation = request.attribute_groups[0]
    461         printer = self.printers[self.default]
     490        printer = self.printer
    462491
    463492        # get attributes from the printer and add to response
     
    479508
    480509        # get attributes from the printer and add to response
    481         for printer in self.printers.values():
    482             response.attribute_groups.append(ipp.AttributeGroup(
    483                 ipp.AttributeTags.PRINTER, printer.get_printer_attributes(operation)))
     510        response.attribute_groups.append(ipp.AttributeGroup(
     511            ipp.AttributeTags.PRINTER, self.printer.get_printer_attributes(operation)))
    484512
    485513    @handler_for(ipp.OperationCodes.CUPS_GET_CLASSES)
  • server/lib/gutenbach/server/server.py

    r7c143c9 re58af05  
    1 from gutenbach.server.requests import GutenbachRequestHandler
     1import gutenbach.ipp as ipp
     2
     3from . import InvalidPrinterStateException, InvalidJobException
     4from . import GutenbachPrinter
     5from . import GutenbachRequestHandler
     6
    27import BaseHTTPServer
    3 import gutenbach.ipp as ipp
    48import logging
    59import sys
    610import traceback
    711import tempfile
     12import threading
     13import time
    814
    915# initialize logger
    1016logger = logging.getLogger(__name__)
    1117
    12 # initialize handler
    13 handler = GutenbachRequestHandler()
     18class GutenbachServer(threading.Thread):
    1419
    15 class GutenbachIPPServer(BaseHTTPServer.BaseHTTPRequestHandler):
     20    def run(self):
     21        self.printer = GutenbachPrinter(name="test")
     22        self.request_stop = False
     23
     24        while not self.request_stop:
     25            job = self.printer.next_job
     26            if job is not None:
     27                try:
     28                    self.printer.start_job(job)
     29                except InvalidPrinterStateException:
     30                    pass
     31                except:
     32                    logger.fatal(traceback.format_exc())
     33                    sys.exit(1)
     34            time.sleep(0.1)
     35
     36class IPPServer(BaseHTTPServer.BaseHTTPRequestHandler):
     37   
    1638    def send_continue(self):
    1739        self.send_response(100, "continue")
     
    83105        # throw a fatal error.
    84106        logger.debug("request: %s" % repr(request))
    85         response = handler.handle(request)
     107        response = GutenbachRequestHandler(self.server.gutenbach_server).handle(request)
    86108        self.send_ok(response)
Note: See TracChangeset for help on using the changeset viewer.