bunches of changes
[python-rwhoisd.git] / rwhoisd / RwhoisServer.py
1 #! /usr/bin/python
2
3 import sys, socket, SocketServer
4
5 import config, Session
6 import QueryParser, QueryProcessor, DirectiveProcessor, Rwhois
7
8
9 # server-wide variables
10
11 query_processor     = None
12 directive_processor = None
13
14 class RwhoisTCPServer(SocketServer.ThreadingTCPServer):
15     def __init__(self, server_address, RequestHandlerClass):
16         self.allow_reuse_address = True
17         SocketServer.TCPServer.__init__(self, server_address,
18                                         RequestHandlerClass)
19
20     def verify_request(self, request, client_address):
21         # implement access control here
22         return True
23
24 class RwhoisHandler(SocketServer.StreamRequestHandler):
25
26     def readline(self):
27         """Read a line of input from the client."""
28         # a simple way of doing this
29         # return self.rfile.readline()
30
31         data = self.request.recv(1024)
32         if not data: return None
33
34         lines = data.splitlines(True)
35
36         # ugh. this totally defeats any pipelining, not that rwhois
37         # clients should be doing that.
38         if len(lines) > 1 and config.verbose:
39             print "%s discarding additional input lines: %r" \
40                   % (self.client_address, lines)
41         return lines[0]
42         
43     def handle(self):
44
45         print repr(self.request)
46         self.quit_flag = False
47
48         # output a banner
49         self.wfile.write(config.banner_string);
50         self.wfile.write("\r\n");
51
52         # get a session.
53         session = Session.Context()
54         session.rfile = self.rfile
55         session.wfile = self.wfile
56
57         if config.verbose:
58             print "%s accepted connection" % (self.client_address,)
59
60         c = 0
61         while 1:
62             line = self.readline()
63             if not line: break
64
65             line = line.strip()
66             # we can skip blank lines.
67             if not line:
68                 continue
69             
70             if line.startswith("-"):
71                 self.handle_directive(session, line)
72             else:
73                 self.handle_query(session, line)
74                 if not session.holdconnect:
75                     self.quit_flag = True
76
77             self.wfile.flush()
78
79             # check to see if we were asked to quit
80             if self.quit_flag: break
81
82         if config.verbose:
83             print "%s disconnected" %  (self.client_address,)
84
85     def handle_directive(self, session, line):
86         if config.verbose:
87             print "%s directive %s" % (self.client_address, line)
88         if (line.startswith("-quit")):
89             self.quit_flag = True
90             self.wfile.write(Rwhois.ok())
91             return
92         directive_processor.process_directive(session, line)
93
94     def handle_query(self, session, line):
95         if config.verbose:
96             print "%s query %s" % (self.client_address, line)
97         query_processor.process_query(session, line)
98
99
100 def usage(pname):
101     print """\
102 usage: %s [-v] schema_file data_file [data_file ...]
103        -v: verbose """ % pname
104     sys.exit(64)
105     
106 def init(argv):
107     import MemDB
108     import getopt
109
110     pname = argv[0]
111     opts, argv = getopt.getopt(argv[1:], 'v')
112     for o, a in opts:
113         if o == "-v":
114             config.verbose = True
115     
116     if len(argv) < 2: usage(pname)
117     schema_file = argv[0]
118     data_files  = argv[1:]
119
120
121     db = MemDB.MemDB()
122
123     db.init_schema(schema_file)
124     for df in data_files:
125         db.load_data(df)
126     db.index_data()
127
128     QueryParser.db = db
129
130     global query_processor, directive_processor
131     
132     query_processor     = QueryProcessor.QueryProcessor(db)
133     directive_processor = DirectiveProcessor.DirectiveProcessor(db)
134
135 def serve():
136     # initialize the TCP server
137     server = RwhoisTCPServer((config.server_address, config.port),
138                              RwhoisHandler)
139
140     # and handle incoming connections
141     if config.verbose:
142         if not config.server_address:
143             print "listening on port %d" % config.port
144         else:
145             print "listening on %s port %d" % \
146                   (config.server_address, config.port)
147     server.serve_forever()
148
149     sys.exit(0)
150
151 if __name__ == "__main__":
152
153     init(sys.argv)
154     serve()
155