python: Removed debug message in proto.py.
[ashd.git] / python / ashd / proto.py
1 import os, socket
2 import htlib
3
4 class protoerr(Exception):
5     pass
6
7 class req(object):
8     def __init__(self, method, url, ver, rest, headers, fd):
9         self.method = method
10         self.url = url
11         self.ver = ver
12         self.rest = rest
13         self.headers = headers
14         self.sk = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM).makefile('r+')
15         os.close(fd)
16
17     def close(self):
18         self.sk.close()
19
20     def __getitem__(self, header):
21         header = header.lower()
22         for key, val in self.headers:
23             if key.lower() == header:
24                 return val
25         raise KeyError(header)
26
27     def __contains__(self, header):
28         header = header.lower()
29         for key, val in self.headers:
30             if key.lower() == header:
31                 return True
32         return False
33
34     def dup(self):
35         return req(self.method, self.url, self.ver, self.rest, self.headers, os.dup(self.sk.fileno()))
36
37     def match(self, match):
38         if self.rest[:len(match)] == match:
39             self.rest = self.rest[len(match):]
40             return True
41         return False
42
43     def __str__(self):
44         return "\"%s %s %s\"" % (self.method, self.url, self.ver)
45
46     def __enter__(self):
47         return self
48
49     def __exit__(self, *excinfo):
50         self.sk.close()
51         return False
52
53 def recvreq(sock = 0):
54     data, fd = htlib.recvfd(sock)
55     if fd is None:
56         return None
57     try:
58         parts = data.split('\0')[:-1]
59         if len(parts) < 5:
60             raise protoerr("Truncated request")
61         method, url, ver, rest = parts[:4]
62         headers = []
63         i = 4
64         while True:
65             if parts[i] == "": break
66             if len(parts) - i < 3:
67                 raise protoerr("Truncated request")
68             headers.append((parts[i], parts[i + 1]))
69             i += 2
70         return req(method, url, ver, rest, headers, os.dup(fd))
71     finally:
72         os.close(fd)
73
74 def sendreq(sock, req):
75     data = ""
76     data += req.method + '\0'
77     data += req.url + '\0'
78     data += req.ver + '\0'
79     data += req.rest + '\0'
80     for key, val in req.headers:
81         data += key + '\0'
82         data += val + '\0'
83     data += '\0'
84     htlib.sendfd(sock, req.sk.fileno(), data)
85
86 def serveloop(handler, sock = 0):
87     while True:
88         req = recvreq(sock)
89         if req is None:
90             break
91         try:
92             handler(req)
93         finally:
94             req.close()