[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server - HTTPServer.py:1.1.2.14

Shane Hathaway shane@digicool.com
Mon, 7 Jan 2002 10:39:04 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/Server
In directory cvs.zope.org:/tmp/cvs-serv31823

Modified Files:
      Tag: Zope-3x-branch
	HTTPServer.py 
Log Message:
- Made next_channel_cleanup a list so that it can be more easily overridden
  by subclasses.

- Changed the name "channel_type" to "channel_base_class" for clarity.

- Renamed the "tasks" parameter to "task_dispatcher".

- Separated out the default server name computation into a method.

- Removed comments that are better described in interfaces.

- Provided a way to use an alternate socket map.


=== Zope3/lib/python/Zope/Server/HTTPServer.py 1.1.2.13 => 1.1.2.14 ===
 
 if SIMULT_MODE:
-    from dual_mode_channel import simultaneous_mode_channel as channel_type
+    from dual_mode_channel import simultaneous_mode_channel as \
+         channel_base_class
 else:
-    from dual_mode_channel import dual_mode_channel as channel_type
+    from dual_mode_channel import dual_mode_channel as channel_base_class
 
-from dual_mode_channel import OverflowableBuffer
+from dual_mode_channel import AlternateSocketMapMixin, OverflowableBuffer
 from Adjustments import default_adj
 from IHeaderOutput import IHeaderOutput
 from ITask import ITask
@@ -107,10 +108,6 @@
         """
         self.channel.close_when_done()
 
-    # setResponseStatus(), setResponseHeaders(), appendResponseHeaders(),
-    # wroteResponseHeader(), and setAuthUserName() are part of the
-    # IHeaderOutput interface used by Zope.Publisher.HTTP.HTTPResponse.
-
     def setResponseStatus(self, status, reason):
         self.status = status
         self.reason = reason
@@ -412,27 +409,26 @@
 
 
 
-class http_channel (channel_type):
+class http_channel (channel_base_class):
     # Note: this class is very reusable for other protocols like FTP
     # and should probably be turned into an abstract base class
     # when we approach FTP.
 
     task_class = http_task
+    active_channels = {}        # Class-specific channel tracker
+    next_channel_cleanup = [0]  # Class-specific cleanup time
 
-    active_channels = {}      # Class-specific channel tracker
     proto_request = None      # An http_request_data instance
     ready_requests = None     # A list
     last_activity = 0         # Time of last activity
     running_tasks = 0         # boolean
 
-    next_channel_cleanup = 0  # A class variable
-
     #
     # ASYNCHRONOUS METHODS (incl. __init__)
     #
 
-    def __init__(self, server, conn, addr, adj=None):
-        channel_type.__init__(self, server, conn, addr, adj)
+    def __init__(self, server, conn, addr, adj=None, socket_map=None):
+        channel_base_class.__init__(self, server, conn, addr, adj, socket_map)
         self.last_activity = t = self.creation_time
         self.check_maintenance(t)
 
@@ -440,27 +436,26 @@
         """
         This hook keeps track of opened HTTP channels.
         """
-        channel_type.add_channel(self, map)
+        channel_base_class.add_channel(self, map)
         self.active_channels[self._fileno] = self
 
     def del_channel(self, map=None):
         """
         This hook keeps track of closed HTTP channels.
         """
-        channel_type.del_channel(self, map)
+        channel_base_class.del_channel(self, map)
         ac = self.active_channels
         fd = self._fileno
         if ac.has_key(fd):
             del ac[fd]
 
     def check_maintenance(self, now):
-        if now < http_channel.next_channel_cleanup:
+        if now < self.next_channel_cleanup[0]:
             return
-        http_channel.next_channel_cleanup = now + self.adj.cleanup_interval
+        self.next_channel_cleanup[0] = now + self.adj.cleanup_interval
         self.maintenance()
 
     def maintenance(self):
-        # Note that this is an asynchronous call.
         # Kill off dead connections.
         self.kill_zombies()
 
@@ -540,7 +535,6 @@
     #
 
     def end_task(self, close):
-        # Synchronous.
         if close:
             self.close_when_done()
             return
@@ -647,47 +641,52 @@
             )
 
 
-
-class http_server (asyncore.dispatcher):
+class http_server (AlternateSocketMapMixin, asyncore.dispatcher):
 
     channel_class = http_channel
 
     SERVER_IDENT = 'Zope.Server.HTTPServer.http_server'
 
-    def __init__(self, ip, port, tasks=None, adj=None, start=1,
-                 hit_log=None, verbose=0, resolver=None):
-        # Assumes sock is already bound.
+    def __init__(self, ip, port, task_dispatcher=None, adj=None, start=1,
+                 hit_log=None, verbose=0, socket_map=None):
         if adj is None:
             adj = default_adj
         self.adj = adj
-        self.resolver = resolver
+        self.socket_map = socket_map
         asyncore.dispatcher.__init__(self)
         self.port = port
-        self.tasks = tasks
+        self.task_dispatcher = task_dispatcher
         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
         self.set_reuse_addr()
         self.bind((ip, port))
         self.verbose = verbose
-
-        #if hit_log is None:
-        #    hit_log = CommonHitLogger()
         self.hit_log = hit_log
+        self.server_name = self.computeServerName(ip)
 
-        host, port = self.socket.getsockname()
-        if not ip:
-            if verbose:
-                self.log_info('Computing default hostname', 'info')
-            ip = socket.gethostbyname (socket.gethostname())
-        try:
-            self.server_name = socket.gethostbyaddr (ip)[0]
-        except socket.error:
-            if verbose:
-                self.log_info('Cannot do reverse lookup', 'info')
-            self.server_name = ip       # use the IP address as the "hostname"
-        
         if start:
             self.accept_connections()
 
+    def computeServerName(self, ip=''):
+        if ip:
+            server_name = str(ip)
+        else:
+            server_name = str(socket.gethostname())
+        # Convert to a host name if necessary.
+        is_hostname = 0
+        for c in server_name:
+            if c != '.' and not c.isdigit():
+                is_hostname = 1
+                break
+        if not is_hostname:
+            if self.verbose:
+                self.log_info('Computing hostname', 'info')
+            try:
+                server_name = socket.gethostbyaddr(server_name)[0]
+            except socket.error:
+                if self.verbose:
+                    self.log_info('Cannot do reverse lookup', 'info')
+        return server_name
+
     def accept_connections(self):
         self.accepting = 1
         self.socket.listen(self.adj.backlog)  # Circumvent asyncore's NT limit
@@ -721,19 +720,20 @@
                 return
             conn, addr = v
         except socket.error:
-                # linux: on rare occasions we get a bogus socket back from
-                # accept.  socketmodule.c:makesockaddr complains that the
-                # address family is unknown.  We don't want the whole server
-                # to shut down because of this.
-            self.log_info ('warning: server accept() threw an exception',
-                           'warning')
+            # Linux: On rare occasions we get a bogus socket back from
+            # accept.  socketmodule.c:makesockaddr complains that the
+            # address family is unknown.  We don't want the whole server
+            # to shut down because of this.
+            if self.adj.log_socket_errors:
+                self.log_info ('warning: server accept() threw an exception',
+                               'warning')
             return
-        self.channel_class(self, conn, addr, self.adj)
+        self.channel_class(self, conn, addr, self.adj, self.socket_map)
 
     def addTask(self, task):
-        tasks = self.tasks
-        if tasks is not None:
-            self.tasks.addTask(task)
+        td = self.task_dispatcher
+        if td is not None:
+            td.addTask(task)
         else:
             task.service()
 
@@ -744,13 +744,13 @@
 
 if __name__ == '__main__':
     from TaskThreads import ThreadedTaskDispatcher
-    tasks = ThreadedTaskDispatcher()
-    tasks.setThreadCount(4)
-    http_server('', 8080, tasks=tasks)
+    td = ThreadedTaskDispatcher()
+    td.setThreadCount(4)
+    http_server('', 8080, task_dispatcher=td)
     try:
         while 1:
             asyncore.poll(5)
             #print http_channel.active_channels
     except KeyboardInterrupt:
         print 'shutting down...'
-        tasks.shutdown()
+        td.shutdown()