source: server/lib/gutenbach/server/requests.py @ d04a689

no-cups
Last change on this file since d04a689 was d04a689, checked in by Jessica B. Hamrick <jhamrick@…>, 12 years ago

Clean up import statements; fix import bugs

  • Property mode set to 100644
File size: 10.0 KB
Line 
1import BaseHTTPServer
2import gutenbach.ipp
3import gutenbach.ipp.constants as const
4import logging
5import time
6
7# initialize logger
8logger = logging.getLogger(__name__)
9
10def handler_for(operation):
11    """A decorator method to mark a function with the operation id
12    that it handles.  This value will be stored in
13    'func.ipp_operation'.
14
15    """
16   
17    def f(func):
18        func.ipp_operation = operation
19        return func
20    return f
21
22class IPPRequestHandler(object):
23    """A generic base class for IPP requests.  Provides a dispatch
24    function to conver request operation ids to handler functions.
25
26    """
27   
28    def _ipp_dispatch(self, request):
29        for d in dir(self):
30            if getattr(getattr(self, d), "ipp_operation", None) == request.operation_id:
31                return getattr(self, d)
32        return self.unknown_operation
33
34    def unknown_operation(self, request, response):
35        print "Received UNKNOWN OPERATION %x" % request.operation_id
36        response.operation_id = const.StatusCodes.OPERATION_NOT_SUPPORTED
37
38class PrinterRequestHandler(IPPRequestHandler):
39    """This handles requests that are printer-specific: for example,
40    the printer's name or state.
41
42    """
43   
44    def __init__(self, name):
45        self.name = name
46
47    @handler_for(const.Operations.GET_PRINTER_ATTRIBUTES)
48    def get_printer_attributes(self, request, response):
49        printer_attributes = ipp.AttributeGroup(const.AttributeTags.PRINTER)
50        printer_attributes.append(ipp.Attribute(
51            "printer-uri-supported",
52            [ipp.Value(ipp.Tags.URI, "ipp://localhost:8000/printers/" + self.name)]))
53
54        printer_attributes.append(ipp.Attribute(
55            "uri-authentication-supported",
56            [ipp.Value(ipp.Tags.KEYWORD, "none")]))
57
58        printer_attributes.append(ipp.Attribute(
59            "uri-security-supported",
60            [ipp.Value(ipp.Tags.KEYWORD, "none")]))
61
62        printer_attributes.append(ipp.Attribute(
63            "printer-name",
64            [ipp.Value(ipp.Tags.NAME_WITHOUT_LANGUAGE, self.name)]))
65
66        printer_attributes.append(ipp.Attribute(
67            "printer-state",
68            [ipp.Value(ipp.Tags.ENUM, const.PrinterStates.IDLE)]))
69
70        printer_attributes.append(ipp.Attribute(
71            "printer-state-reasons",
72            [ipp.Value(ipp.Tags.KEYWORD, "none")]))
73
74        printer_attributes.append(ipp.Attribute(
75            "ipp-versions-supported",
76            [ipp.Value(ipp.Tags.KEYWORD, "1.0"),
77             ipp.Value(ipp.Tags.KEYWORD, "1.1")]))
78
79        # XXX: We should query ourself for the supported operations
80        printer_attributes.append(ipp.Attribute(
81            "operations-supported",
82            [ipp.Value(ipp.Tags.ENUM, const.Operations.GET_JOBS)]))
83
84        printer_attributes.append(ipp.Attribute(
85            "charset-configured",
86            [ipp.Value(ipp.Tags.CHARSET, "utf-8")]))
87
88        printer_attributes.append(ipp.Attribute(
89            "charset-supported",
90            [ipp.Value(ipp.Tags.CHARSET, "utf-8")]))
91
92        printer_attributes.append(ipp.Attribute(
93            "natural-language-configured",
94            [ipp.Value(ipp.Tags.NATURAL_LANGUAGE, "en-us")]))
95
96        printer_attributes.append(ipp.Attribute(
97            "generated-natural-language-supported",
98            [ipp.Value(ipp.Tags.NATURAL_LANGUAGE, "en-us")]))
99
100        printer_attributes.append(ipp.Attribute(
101            "document-format-default",
102            [ipp.Value(ipp.Tags.MIME_MEDIA_TYPE, "application/octet-stream")]))
103
104        printer_attributes.append(ipp.Attribute(
105            "document-format-supported",
106            [ipp.Value(ipp.Tags.MIME_MEDIA_TYPE, "application/octet-stream"),
107             ipp.Value(ipp.Tags.MIME_MEDIA_TYPE, "audio/mp3")]))
108
109        printer_attributes.append(ipp.Attribute(
110            "printer-is-accepting-jobs",
111            [ipp.Value(ipp.Tags.BOOLEAN, True)]))
112
113        printer_attributes.append(ipp.Attribute(
114            "queued-job-count",
115            [ipp.Value(ipp.Tags.INTEGER, 1)]))
116
117        printer_attributes.append(ipp.Attribute(
118            "pdl-override-supported",
119            [ipp.Value(ipp.Tags.KEYWORD, "not-attempted")]))
120
121        printer_attributes.append(ipp.Attribute(
122            "printer-up-time",
123            [ipp.Value(ipp.Tags.INTEGER, int(time.time()))]))
124
125        printer_attributes.append(ipp.Attribute(
126            "compression-supported",
127            [ipp.Value(ipp.Tags.KEYWORD, "none")]))
128
129        response.attribute_groups.append(printer_attributes)
130        response.operation_id = const.StatusCodes.OK
131        print "get_printer_attributes called"
132
133class RootRequestHandler(IPPRequestHandler):
134    printers = [PrinterRequestHandler(name="sipbmp3")]
135
136    @handler_for(const.Operations.CUPS_GET_DEFAULT)
137    def cups_get_default(self, request, response):
138        print "get_default called"
139        return self.printers[0].get_printer_attributes(request, response)
140
141    @handler_for(const.Operations.CUPS_GET_PRINTERS)
142    def cups_get_printers(self, request, response):
143        print "get_printers called"
144        response.operation_id = const.StatusCodes.OK
145        # Each printer will append a new printer attribute group.
146        for p in self.printers:
147            p.get_printer_attributes(request, response)
148
149    @handler_for(const.Operations.CUPS_GET_CLASSES)
150    def cups_get_classes(self, request, response):
151        print "get_classes called"
152        response.operation_id = const.StatusCodes.OK
153        # We have no printer classes, so nothing to return.
154
155class GutenbachIPPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
156    def setup(self):
157        self.root = RootRequestHandler()
158        BaseHTTPServer.BaseHTTPRequestHandler.setup(self)
159
160    def handle_one_request(self):
161        self.raw_requestline = self.rfile.readline()
162        if not self.raw_requestline:
163            self.close_connection = 1
164            return
165        if not self.parse_request(): # An error code has been sent, just exit
166            return
167        self.handle_ipp()
168
169    def handle_ipp(self):
170        # Receive a request
171        length = int(self.headers.getheader('content-length', 0))
172        request = ipp.Request(request=self.rfile, length=length)
173        print "Received request:", repr(request)
174
175        # Attributes
176        attributes = [
177            ipp.Attribute(
178                'attributes-charset',
179                [ipp.Value(ipp.Tags.CHARSET, 'utf-8')]),
180            ipp.Attribute(
181                'attributes-natural-language',
182                [ipp.Value(ipp.Tags.NATURAL_LANGUAGE, 'en-us')])
183            ]
184        # Attribute group
185        attribute_group = ipp.AttributeGroup(
186            const.AttributeTags.OPERATION,
187            attributes)
188
189        # Set up the response
190        response_kwargs = {}
191        response_kwargs['version']          = request.version
192        response_kwargs['operation_id']     = const.StatusCodes.INTERNAL_ERROR
193        response_kwargs['request_id']       = request.request_id
194        response_kwargs['attribute_groups'] = [attribute_group]
195        response = ipp.Request(**response_kwargs)
196
197        # Get the handler and pass it the request and response objects
198        handler = self.root._ipp_dispatch(request)
199        handler(request, response)
200        print "Sending response:", repr(response)
201
202        # Send the response across HTTP
203        self.send_response(200, "o hai")
204        self.send_header("Content-Type", "application/ipp")
205        self.send_header("Connection", "close")
206        self.end_headers()
207        self.wfile.write(response.packed_value)
208
209    def get_jobs(self, request, response_kwargs):
210        """get-jobs response"""
211
212        # Job attributes
213        job_attributes = [
214            ipp.Attribute(
215                'job-id',
216                [ipp.Value(ipp.Tags.INTEGER, 12345)]),
217            ipp.Attribute(
218                'job-name',
219                [ipp.Value(ipp.Tags.NAME_WITHOUT_LANGUAGE, 'foo')]),
220            ipp.Attribute(
221                'job-originating-user-name',
222                [ipp.Value(ipp.Tags.NAME_WITHOUT_LANGUAGE, 'jhamrick')]),
223            ipp.Attribute(
224                'job-k-octets',
225                [ipp.Value(ipp.Tags.INTEGER, 1)]),
226            ipp.Attribute(
227                'job-state',
228                [ipp.Value(ipp.Tags.ENUM, const.JobStates.HELD)]),
229            ipp.Attribute(
230                'job-printer-uri',
231                [ipp.Value(ipp.Tags.URI, 'ipp://localhost:8000/printers/foo')])
232            ]
233        # Job attribute group
234        job_attribute_group = ipp.AttributeGroup(
235            const.AttributeTags.JOB,
236            job_attributes)
237
238        # Operation attributions
239        op_attributes = [
240            ipp.Attribute(
241                'attributes-charset',
242                [ipp.Value(ipp.Tags.CHARSET, 'utf-8')]),
243            ipp.Attribute(
244                'attributes-natural-language',
245                [ipp.Value(ipp.Tags.NATURAL_LANGUAGE, 'en-us')])
246            ]
247        # Operation attribution group
248        op_attributes_group = ipp.AttributeGroup(
249            const.AttributeTags.OPERATION,
250            op_attributes)
251
252        # Setup the actual response dictionary
253        response_kwargs['attribute_groups'] = [op_attributes_group,job_attribute_group]
254        response_kwargs['operation_id'] = const.StatusCodes.OK
255
256        return response_kwargs
257
258    ##### Printer Commands
259
260    def print_job(self, request):
261        pass
262
263    def validate_job(self, request):
264        pass
265
266    #def get_jobs(self, request):
267    #    pass
268
269    def print_uri(self, request):
270        pass
271
272    def create_job(self, request):
273        pass
274
275    def pause_printer(self, request):
276        pass
277
278    def resume_printer(self, request):
279        pass
280
281    def set_printer_attributes(self, request):
282        pass
283
284    ##### Job Commands
285
286    def cancel_job(self, request):
287        pass
288
289    def get_job_attributes(self, request):
290        pass
291
292    def send_document(self, request):
293        pass
294
295    def send_uri(self, request):
296        pass
297
298    def set_job_attributes(self, request):
299        pass
300
301    def cups_get_document(self, request):
302        pass
303
304    def restart_job(self, request):
305        pass
306
307    def promote_job(self, request):
308        pass
Note: See TracBrowser for help on using the repository browser.