Changeset 7c143c9 for server


Ignore:
Timestamp:
Dec 27, 2011, 10:20:10 PM (12 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
e58af05
Parents:
ee8e6d0
git-author:
Jessica B. Hamrick <jhamrick@…> (12/27/11 22:20:10)
git-committer:
Jessica B. Hamrick <jhamrick@…> (12/27/11 22:20:10)
Message:

Add support for chunking, i.e. receiving file data

Location:
server/lib/gutenbach
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • server/lib/gutenbach/ipp/core/request.py

    r793432f r7c143c9  
    33from .constants import AttributeTags
    44from .value import Value
     5from .errors import ClientErrorBadRequest
    56import sys
    67import struct
    78import logging
     9import tempfile
    810
    911# initialize logger
     
    8385        # that file handle
    8486        if request is not None:
     87            # minimum length is
     88            if length < 9:
     89                raise ClientErrorBadRequest("length (%d) < 9" % length)
     90           
    8591            # read the version-number (two signed chars)
    8692            self.version        = struct.unpack('>bb', request.read(2))
     
    105111            # read in the next byte
    106112            next_byte = struct.unpack('>b', request.read(1))[0]
    107             length -=1
     113            length -= 1
    108114            logger.debug("next byte : 0x%X" % next_byte)
    109115
     
    179185            # once we hit the end-of-attributes tag, the only thing
    180186            # left is the data, so go ahead and read all of it
    181             assert length >= 0
    182             self.data = request.read(length)
    183             logger.debug("data : %s" % self.data)
     187            if length < 0:
     188                raise ClientErrorBadRequest("length (%d) < 0" % length)
     189           
     190            self.data = tempfile.TemporaryFile()
     191            self.data.write(request.read(length))
     192            self.data.seek(0)
     193           
     194            logger.debug("data : %d bytes" % length)
    184195
    185196        # otherwise, just set the class variables to the keyword
     
    228239        end_of_attributes_tag = struct.pack('>b', AttributeTags.END)
    229240
    230         # convert the data to binary
    231         if self.data is not None:
    232             data = ''.join([struct.pack('>b', x) for x in self.data])
    233         else:
    234             data = ''
    235 
    236241        # append everything together and return it
    237         return preattributes + attribute_groups + end_of_attributes_tag + data
     242        return preattributes + attribute_groups + end_of_attributes_tag, self.data
    238243
    239244    def __repr__(self):
  • server/lib/gutenbach/server/printer.py

    ree8e6d0 r7c143c9  
    6767        self.jobs = {}
    6868
    69         self._next_jobid = 0
     69        # cups ignores jobs with id 0, so we have to start at 1
     70        self._next_jobid = 1
    7071
    7172    def __getattr__(self, attr):
     
    218219        self.jobs[job_id] = job
    219220        self.active_jobs.append(job_id)
    220         print self.active_jobs
    221221        return job
    222222
  • server/lib/gutenbach/server/requests.py

    ree8e6d0 r7c143c9  
    4141
    4242    def __init__(self):
    43         print "init"
    4443        self.printers = {
    4544            "test": GutenbachPrinter(name="test")
     
    8988        # actually get the handler
    9089        handler = getattr(self, handler_name)
    91         logger.info("Handling request of type '%s'" % handler_name)
     90        logger.info("request is '%s'" % handler_name)
    9291
    9392        # try to handle the request
     
    116115
    117116    def unknown_operation(self, request, response):
    118         logger.warning("Received unknown operation 0x%x" % request.operation_id)
     117        logger.warning("unknown operation 0x%x" % request.operation_id)
    119118        response = make_empty_response(request)
    120119        response.operation_id = ipp.StatusCodes.OPERATION_NOT_SUPPORTED
  • server/lib/gutenbach/server/server.py

    ree8e6d0 r7c143c9  
    55import sys
    66import traceback
     7import tempfile
    78
    89# initialize logger
     
    1314
    1415class GutenbachIPPServer(BaseHTTPServer.BaseHTTPRequestHandler):
     16    def send_continue(self):
     17        self.send_response(100, "continue")
     18        self.send_header("Content-Type", "application/ipp")
     19        self.end_headers()
     20
     21    def send_ok(self, response):
     22        logger.debug(repr(response))
     23        binary, data_file = response.packed_value
     24           
     25        self.send_response(200, "ok")
     26        self.send_header("Content-Type", "application/ipp")
     27        self.send_header("Connection", "close")
     28        self.end_headers()
     29       
     30        self.wfile.write(binary)
     31        if data_file is not None:
     32            data = data_file.read(1024)
     33            while data != '':
     34                self.wfile.write(data)
     35                data = data_file.read(1024)
     36
     37    def log_request(self, code=0, size=0):
     38        logger.info("response (%s)" % code)
     39
     40    def log_message(self, fmt, *args):
     41        logger.info(fmt % args)
     42
     43    def read_chunks(self):
     44        size = sys.maxint
     45        totalsize = 0
     46
     47        with tempfile.SpooledTemporaryFile() as tmp:
     48            while size > 0:
     49                a, b = self.rfile.read(2)
     50                size = a + b
     51                while not (a == "\r" and b == "\n"):
     52                    a = b
     53                    b = self.rfile.read(1)
     54                    size += b
     55                size = int(size[:-2], base=16)
     56                totalsize += size
     57                chunk = self.rfile.read(size)
     58                clrf = self.rfile.read(2)
     59                assert clrf == "\r\n"
     60                tmp.write(chunk)
     61
     62            tmp.seek(0)
     63            request = ipp.Request(request=tmp, length=totalsize)
     64
     65        return request
     66               
    1567    def do_POST(self):
    16         # Receive a request
    1768        length = int(self.headers.getheader('content-length', 0))
    18         if length == 0:
    19             logger.warning("content-length == 0")
    20             return
    21         request = ipp.Request(request=self.rfile, length=length)
     69        expect = self.headers.getheader('expect', None)
     70        encoding = self.headers.getheader('transfer-encoding', None)
     71
     72        logger.info("request %s (%d bytes)" % (self.command, length))
     73        logger.debug(str(self.headers))
     74
     75        # Parse the request
     76        if length == 0 and encoding == "chunked":
     77            request = self.read_chunks()
     78        else:
     79            request = ipp.Request(request=self.rfile, length=length)
    2280
    2381        # Get the handler and pass it the request and response
    2482        # objects.  It will fill in values for the response object or
    2583        # throw a fatal error.
    26         logger.debug("Received request: %s" % repr(request))
    27         try:
    28             response = handler.handle(request)
    29         except:
    30             logger.fatal(traceback.format_exc())
    31             sys.exit(1)
    32 
    33         # Send the response across HTTP
    34         logger.debug("Sending response: %s" % repr(response))
    35         try:
    36             binary = response.packed_value
    37         except:
    38             logger.fatal(traceback.format_exc())
    39             sys.exit(1)
    40            
    41         self.send_response(200, "Gutenbach IPP Response")
    42         self.send_header("Content-Type", "application/ipp")
    43         self.send_header("Connection", "close")
    44         self.end_headers()
    45         self.wfile.write(binary)
     84        logger.debug("request: %s" % repr(request))
     85        response = handler.handle(request)
     86        self.send_ok(response)
Note: See TracChangeset for help on using the changeset viewer.