Commit 5e529dcf authored by Amos Latteier's avatar Amos Latteier

Synched with latest medusa sources from CVS. The main changes are the...

Synched with latest medusa sources from CVS. The main changes are the structure of asyncore.socket_map which now maps fds to channels which should provide a slight performance improvement.
parent 09bb46b6
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
# $Id: asynchat.py,v 1.9 1999/07/19 17:43:47 amos Exp $ # $Id: asynchat.py,v 1.10 2000/01/14 02:35:56 amos Exp $
# Author: Sam Rushing <rushing@nightmare.com> # Author: Sam Rushing <rushing@nightmare.com>
# ====================================================================== # ======================================================================
...@@ -219,7 +219,7 @@ class async_chat (asyncore.dispatcher): ...@@ -219,7 +219,7 @@ class async_chat (asyncore.dispatcher):
def discard_buffers (self): def discard_buffers (self):
# Emergencies only! # Emergencies only!
self.ac_in_buffer = '' self.ac_in_buffer = ''
self.ac_out_buffer == '' self.ac_out_buffer = ''
while self.producer_fifo: while self.producer_fifo:
self.producer_fifo.pop() self.producer_fifo.pop()
......
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
# $Id: asyncore.py,v 1.6 1999/07/26 07:06:36 amos Exp $ # $Id: asyncore.py,v 1.7 2000/01/14 02:35:56 amos Exp $
# Author: Sam Rushing <rushing@nightmare.com> # Author: Sam Rushing <rushing@nightmare.com>
# ====================================================================== # ======================================================================
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# ====================================================================== # ======================================================================
import exceptions
import select import select
import socket import socket
import string import string
...@@ -41,60 +42,83 @@ if os.name == 'nt': ...@@ -41,60 +42,83 @@ if os.name == 'nt':
else: else:
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN
socket_map = {} try:
socket_map
except NameError:
socket_map = {}
class ExitNow (exceptions.Exception):
pass
DEBUG = 0
def poll (timeout=0.0): def poll (timeout=0.0):
global DEBUG
if socket_map: if socket_map:
r = []; w = []; e = [] r = []; w = []; e = []
for s in socket_map.keys(): for fd, obj in socket_map.items():
if s.readable(): if obj.readable():
r.append (s) r.append (fd)
if s.writable(): if obj.writable():
w.append (s) w.append (fd)
r,w,e = select.select (r,w,e, timeout)
(r,w,e) = select.select (r,w,e, timeout) if DEBUG:
print r,w,e
for x in r: for fd in r:
try: try:
x.handle_read_event() obj = socket_map[fd]
try:
obj.handle_read_event()
except ExitNow:
raise ExitNow
except: except:
x.handle_error() obj.handle_error()
for x in w: except KeyError:
pass
for fd in w:
try: try:
x.handle_write_event() obj = socket_map[fd]
try:
obj.handle_write_event()
except ExitNow:
raise ExitNow
except: except:
x.handle_error() obj.handle_error()
except KeyError:
pass
def poll2 (timeout=0.0): def poll2 (timeout=0.0):
import poll import poll
# timeout is in milliseconds # timeout is in milliseconds
timeout = int(timeout*1000) timeout = int(timeout*1000)
if socket_map: if socket_map:
fd_map = {}
for s in socket_map.keys():
fd_map[s.fileno()] = s
l = [] l = []
for fd, s in fd_map.items(): for fd, obj in socket_map.items():
flags = 0 flags = 0
if s.readable(): if obj.readable():
flags = poll.POLLIN flags = poll.POLLIN
if s.writable(): if obj.writable():
flags = flags | poll.POLLOUT flags = flags | poll.POLLOUT
if flags: if flags:
l.append (fd, flags) l.append (fd, flags)
r = poll.poll (l, timeout) r = poll.poll (l, timeout)
for fd, flags in r: for fd, flags in r:
s = fd_map[fd] try:
obj = socket_map[fd]
try: try:
if (flags & poll.POLLIN): if (flags & poll.POLLIN):
s.handle_read_event() obj.handle_read_event()
if (flags & poll.POLLOUT): if (flags & poll.POLLOUT):
s.handle_write_event() obj.handle_write_event()
if (flags & poll.POLLERR): except ExitNow:
s.handle_expt_event() raise ExitNow
except: except:
s.handle_error() obj.handle_error()
except KeyError:
pass
def loop (timeout=30.0, use_poll=0): def loop (timeout=30.0, use_poll=0):
...@@ -143,23 +167,25 @@ class dispatcher: ...@@ -143,23 +167,25 @@ class dispatcher:
return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar) return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar)
def add_channel (self): def add_channel (self):
self.log_info ('adding channel %s' % self) #self.log_info ('adding channel %s' % self)
socket_map [self] = 1 socket_map [self._fileno] = self
def del_channel (self): def del_channel (self):
if socket_map.has_key (self): fd = self._fileno
self.log_info ('closing channel %d:%s' % (self.fileno(), self)) if socket_map.has_key (fd):
del socket_map [self] #self.log_info ('closing channel %d:%s' % (fd, self))
del socket_map [fd]
def create_socket (self, family, type): def create_socket (self, family, type):
self.family_and_type = family, type self.family_and_type = family, type
self.socket = socket.socket (family, type) self.socket = socket.socket (family, type)
self.socket.setblocking(0) self.socket.setblocking(0)
self._fileno = self.socket.fileno()
self.add_channel() self.add_channel()
def set_socket (self, socket): def set_socket (self, sock):
# This is done so we can be called safely from __init__ self.__dict__['socket'] = sock
self.__dict__['socket'] = socket self._fileno = sock.fileno()
self.add_channel() self.add_channel()
def set_reuse_addr (self): def set_reuse_addr (self):
...@@ -261,7 +287,6 @@ class dispatcher: ...@@ -261,7 +287,6 @@ class dispatcher:
# cheap inheritance, used to pass all other attribute # cheap inheritance, used to pass all other attribute
# references to the underlying socket object. # references to the underlying socket object.
# NOTE: this may be removed soon for performance reasons.
def __getattr__ (self, attr): def __getattr__ (self, attr):
return getattr (self.socket, attr) return getattr (self.socket, attr)
...@@ -270,11 +295,11 @@ class dispatcher: ...@@ -270,11 +295,11 @@ class dispatcher:
# and 'log_info' is for informational, warning and error logging. # and 'log_info' is for informational, warning and error logging.
def log (self, message): def log (self, message):
print 'log:', message sys.stderr.write ('log: %s\n' % str(message))
def log_info (self, message, type='info'): def log_info (self, message, type='info'):
if __debug__ or type != 'info': if __debug__ or type != 'info':
print '%s: %s' %(type, message) print '%s: %s' % (type, message)
def handle_read_event (self): def handle_read_event (self):
if self.accepting: if self.accepting:
...@@ -398,7 +423,7 @@ def compact_traceback (): ...@@ -398,7 +423,7 @@ def compact_traceback ():
def close_all (): def close_all ():
global socket_map global socket_map
for x in socket_map.keys(): for x in socket_map.values():
x.socket.close() x.socket.close()
socket_map.clear() socket_map.clear()
...@@ -449,6 +474,7 @@ if os.name == 'posix': ...@@ -449,6 +474,7 @@ if os.name == 'posix':
self.set_file (fd) self.set_file (fd)
def set_file (self, fd): def set_file (self, fd):
self._fileno = fd
self.socket = file_wrapper (fd) self.socket = file_wrapper (fd)
self.add_channel() self.add_channel()
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# If you are interested in using this software in a commercial context, # If you are interested in using this software in a commercial context,
# or in purchasing support, please contact the author. # or in purchasing support, please contact the author.
RCS_ID = '$Id: ftp_server.py,v 1.8 1999/11/15 21:53:56 amos Exp $' RCS_ID = '$Id: ftp_server.py,v 1.9 2000/01/14 02:35:56 amos Exp $'
# An extensible, configurable, asynchronous FTP server. # An extensible, configurable, asynchronous FTP server.
# #
...@@ -336,6 +336,7 @@ class ftp_channel (asynchat.async_chat): ...@@ -336,6 +336,7 @@ class ftp_channel (asynchat.async_chat):
self.current_mode = t self.current_mode = t
self.respond ('200 Type set to %s.' % self.type_map[t]) self.respond ('200 Type set to %s.' % self.type_map[t])
def cmd_quit (self, line): def cmd_quit (self, line):
'terminate session' 'terminate session'
self.respond ('221 Goodbye.') self.respond ('221 Goodbye.')
...@@ -848,12 +849,15 @@ class xmit_channel (asynchat.async_chat): ...@@ -848,12 +849,15 @@ class xmit_channel (asynchat.async_chat):
self.client_addr = client_addr self.client_addr = client_addr
asynchat.async_chat.__init__ (self) asynchat.async_chat.__init__ (self)
def readable (self): # def __del__ (self):
return 0 # print 'xmit_channel.__del__()'
def log(self, *args): def log (*args):
pass pass
def readable (self):
return not self.connected
def writable (self): def writable (self):
return 1 return 1
...@@ -1054,13 +1058,7 @@ if os.name == 'posix': ...@@ -1054,13 +1058,7 @@ if os.name == 'posix':
self.log_info('FTP server shutting down. (received SIGINT)', 'warning') self.log_info('FTP server shutting down. (received SIGINT)', 'warning')
# close everything down on SIGINT. # close everything down on SIGINT.
# of course this should be a cleaner shutdown. # of course this should be a cleaner shutdown.
sm = socket.socket_map asyncore.close_all()
socket.socket_map = {}
for sock in sm.values():
try:
sock.close()
except:
pass
if __name__ == '__main__': if __name__ == '__main__':
test (sys.argv[1]) test (sys.argv[1])
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# interested in using this software in a commercial context, or in # interested in using this software in a commercial context, or in
# purchasing support, please contact the author. # purchasing support, please contact the author.
RCS_ID = '$Id: http_server.py,v 1.13 1999/11/15 21:53:56 amos Exp $' RCS_ID = '$Id: http_server.py,v 1.14 2000/01/14 02:35:56 amos Exp $'
# python modules # python modules
import os import os
...@@ -385,7 +385,7 @@ class http_channel (asynchat.async_chat): ...@@ -385,7 +385,7 @@ class http_channel (asynchat.async_chat):
def kill_zombies (self): def kill_zombies (self):
now = int (time.time()) now = int (time.time())
for channel in asyncore.socket_map.keys(): for channel in asyncore.socket_map.values():
if channel.__class__ == self.__class__: if channel.__class__ == self.__class__:
if (now - channel.creation_time) > channel.zombie_timeout: if (now - channel.creation_time) > channel.zombie_timeout:
channel.close() channel.close()
...@@ -461,27 +461,18 @@ class http_channel (asynchat.async_chat): ...@@ -461,27 +461,18 @@ class http_channel (asynchat.async_chat):
return return
request = lines[0] request = lines[0]
try:
command, uri, version = crack_request (request) command, uri, version = crack_request (request)
except:
# deal with broken HTTP requests
try:
# maybe there were spaces in the URL
parts=string.split(request)
command, uri, version = crack_request(
'%s %s %s' % (parts[0], parts[1], parts[-1]))
except:
self.log_info('Bad HTTP request: %s' % request, 'error')
r = http_request (self, request,
None, None, None, join_headers(lines[1:]))
r.error(400)
return
header = join_headers (lines[1:]) header = join_headers (lines[1:])
r = http_request (self, request, command, uri, version, header) r = http_request (self, request, command, uri, version, header)
self.request_counter.increment() self.request_counter.increment()
self.server.total_requests.increment() self.server.total_requests.increment()
if command is None:
self.log_info('Bad HTTP request: %s' % request, 'error')
r.error(400)
return
# -------------------------------------------------- # --------------------------------------------------
# handler selection and dispatch # handler selection and dispatch
# -------------------------------------------------- # --------------------------------------------------
...@@ -612,7 +603,14 @@ class http_server (asyncore.dispatcher): ...@@ -612,7 +603,14 @@ class http_server (asyncore.dispatcher):
# accept. socketmodule.c:makesockaddr complains that the # accept. socketmodule.c:makesockaddr complains that the
# address family is unknown. We don't want the whole server # address family is unknown. We don't want the whole server
# to shut down because of this. # to shut down because of this.
self.log_info('Server accept() threw an exception', 'warning') self.log_info ('warning: server accept() threw an exception', 'warning')
return
except TypeError:
# unpack non-sequence. this can happen when a read event
# fires on a listening socket, but when we call accept()
# we get EWOULDBLOCK, so dispatcher.accept() returns None.
# Seen on FreeBSD3.
self.log_info ('warning: server accept() threw EWOULDBLOCK', 'warning')
return return
self.channel_class (self, conn, addr) self.channel_class (self, conn, addr)
...@@ -689,6 +687,8 @@ def crack_request (r): ...@@ -689,6 +687,8 @@ def crack_request (r):
else: else:
version = None version = None
return string.lower (REQUEST.group (1)), REQUEST.group(2), version return string.lower (REQUEST.group (1)), REQUEST.group(2), version
else:
return None, None, None
class fifo: class fifo:
def __init__ (self, list=None): def __init__ (self, list=None):
......
...@@ -5,14 +5,13 @@ ...@@ -5,14 +5,13 @@
# python REPL channel. # python REPL channel.
# #
RCS_ID = '$Id: monitor.py,v 1.5 1999/07/21 17:15:53 klm Exp $' RCS_ID = '$Id: monitor.py,v 1.6 2000/01/14 02:35:56 amos Exp $'
import md5 import md5
import socket import socket
import string import string
import sys import sys
import time import time
import traceback
VERSION = string.split(RCS_ID)[2] VERSION = string.split(RCS_ID)[2]
...@@ -32,7 +31,7 @@ class monitor_channel (asynchat.async_chat): ...@@ -32,7 +31,7 @@ class monitor_channel (asynchat.async_chat):
self.set_terminator ('\r\n') self.set_terminator ('\r\n')
self.data = '' self.data = ''
# local bindings specific to this channel # local bindings specific to this channel
self.local_env = {} self.local_env = sys.modules['__main__'].__dict__.copy()
self.push ('Python ' + sys.version + '\r\n') self.push ('Python ' + sys.version + '\r\n')
self.push (sys.copyright+'\r\n') self.push (sys.copyright+'\r\n')
self.push ('Welcome to %s\r\n' % self) self.push ('Welcome to %s\r\n' % self)
...@@ -94,7 +93,6 @@ class monitor_channel (asynchat.async_chat): ...@@ -94,7 +93,6 @@ class monitor_channel (asynchat.async_chat):
result = eval (co, self.local_env) result = eval (co, self.local_env)
method = 'eval' method = 'eval'
if result is not None: if result is not None:
self.log_info(repr(result))
print repr(result) print repr(result)
self.local_env['_'] = result self.local_env['_'] = result
except SyntaxError: except SyntaxError:
...@@ -121,11 +119,8 @@ class monitor_channel (asynchat.async_chat): ...@@ -121,11 +119,8 @@ class monitor_channel (asynchat.async_chat):
except: except:
method = 'exception' method = 'exception'
self.multi_line = [] self.multi_line = []
t, v, tb = sys.exc_info()
(file, fun, line), t, v, tbinfo = asyncore.compact_traceback() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback()
self.log_info('%s %s %s' %(t, v, tbinfo), 'warning') self.log_info('%s %s %s' %(t, v, tbinfo), 'warning')
traceback.print_exception(t, v, tb)
del tb
finally: finally:
sys.stdout = oldout sys.stdout = oldout
sys.stderr = olderr sys.stderr = olderr
...@@ -229,7 +224,6 @@ class secure_monitor_channel (monitor_channel): ...@@ -229,7 +224,6 @@ class secure_monitor_channel (monitor_channel):
self.push ('Python ' + sys.version + '\r\n') self.push ('Python ' + sys.version + '\r\n')
self.push (sys.copyright+'\r\n') self.push (sys.copyright+'\r\n')
self.push ('Welcome to %s\r\n' % self) self.push ('Welcome to %s\r\n' % self)
self.push ("[Hint: try 'from __main__ import *']\r\n")
self.prompt() self.prompt()
self.data = '' self.data = ''
else: else:
......
...@@ -60,7 +60,7 @@ class monitor_client (asynchat.async_chat): ...@@ -60,7 +60,7 @@ class monitor_client (asynchat.async_chat):
def handle_close (self): def handle_close (self):
# close all the channels, which will make the standard main # close all the channels, which will make the standard main
# loop exit. # loop exit.
map (lambda x: x.close(), asyncore.socket_map.keys()) map (lambda x: x.close(), asyncore.socket_map.values())
def log (self, *ignore): def log (self, *ignore):
pass pass
......
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING = "$Id: select_trigger.py,v 1.8 1999/10/29 15:11:58 brian Exp $" VERSION_STRING = "$Id: select_trigger.py,v 1.9 2000/01/14 02:35:56 amos Exp $"
import asyncore import asyncore
import asynchat import asynchat
...@@ -82,15 +82,15 @@ if os.name == 'posix': ...@@ -82,15 +82,15 @@ if os.name == 'posix':
thunk() thunk()
except: except:
(file, fun, line), t, v, tbinfo = asyncore.compact_traceback() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback()
self.log_info( print 'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo)
'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo),
'error')
self.thunks = [] self.thunks = []
finally: finally:
self.lock.release() self.lock.release()
else: else:
# win32-safe version
class trigger (asyncore.dispatcher): class trigger (asyncore.dispatcher):
address = ('127.9.9.9', 19999) address = ('127.9.9.9', 19999)
...@@ -99,22 +99,8 @@ else: ...@@ -99,22 +99,8 @@ else:
a = socket.socket (socket.AF_INET, socket.SOCK_STREAM) a = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
w = socket.socket (socket.AF_INET, socket.SOCK_STREAM) w = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
# set TCP_NODELAY to true to avoid buffering
w.setsockopt(socket.IPPROTO_TCP, 1, 1)
# tricky: get a pair of connected sockets # tricky: get a pair of connected sockets
host='127.9.9.9' a.bind (self.address)
port=19999
while 1:
try:
self.address=(host, port)
a.bind(self.address)
break
except:
if port <= 19950:
raise 'Bind Error', 'Cannot bind trigger!'
port=port - 1
a.listen (1) a.listen (1)
w.setblocking (0) w.setblocking (0)
try: try:
...@@ -161,9 +147,7 @@ else: ...@@ -161,9 +147,7 @@ else:
thunk() thunk()
except: except:
(file, fun, line), t, v, tbinfo = asyncore.compact_traceback() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback()
self.log_info( print 'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo)
'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo),
'error')
self.thunks = [] self.thunks = []
finally: finally:
self.lock.release() self.lock.release()
......
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
# $Id: asynchat.py,v 1.9 1999/07/19 17:43:47 amos Exp $ # $Id: asynchat.py,v 1.10 2000/01/14 02:35:56 amos Exp $
# Author: Sam Rushing <rushing@nightmare.com> # Author: Sam Rushing <rushing@nightmare.com>
# ====================================================================== # ======================================================================
...@@ -219,7 +219,7 @@ class async_chat (asyncore.dispatcher): ...@@ -219,7 +219,7 @@ class async_chat (asyncore.dispatcher):
def discard_buffers (self): def discard_buffers (self):
# Emergencies only! # Emergencies only!
self.ac_in_buffer = '' self.ac_in_buffer = ''
self.ac_out_buffer == '' self.ac_out_buffer = ''
while self.producer_fifo: while self.producer_fifo:
self.producer_fifo.pop() self.producer_fifo.pop()
......
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
# $Id: asyncore.py,v 1.6 1999/07/26 07:06:36 amos Exp $ # $Id: asyncore.py,v 1.7 2000/01/14 02:35:56 amos Exp $
# Author: Sam Rushing <rushing@nightmare.com> # Author: Sam Rushing <rushing@nightmare.com>
# ====================================================================== # ======================================================================
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# ====================================================================== # ======================================================================
import exceptions
import select import select
import socket import socket
import string import string
...@@ -41,60 +42,83 @@ if os.name == 'nt': ...@@ -41,60 +42,83 @@ if os.name == 'nt':
else: else:
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN
socket_map = {} try:
socket_map
except NameError:
socket_map = {}
class ExitNow (exceptions.Exception):
pass
DEBUG = 0
def poll (timeout=0.0): def poll (timeout=0.0):
global DEBUG
if socket_map: if socket_map:
r = []; w = []; e = [] r = []; w = []; e = []
for s in socket_map.keys(): for fd, obj in socket_map.items():
if s.readable(): if obj.readable():
r.append (s) r.append (fd)
if s.writable(): if obj.writable():
w.append (s) w.append (fd)
r,w,e = select.select (r,w,e, timeout)
(r,w,e) = select.select (r,w,e, timeout) if DEBUG:
print r,w,e
for x in r: for fd in r:
try: try:
x.handle_read_event() obj = socket_map[fd]
try:
obj.handle_read_event()
except ExitNow:
raise ExitNow
except: except:
x.handle_error() obj.handle_error()
for x in w: except KeyError:
pass
for fd in w:
try: try:
x.handle_write_event() obj = socket_map[fd]
try:
obj.handle_write_event()
except ExitNow:
raise ExitNow
except: except:
x.handle_error() obj.handle_error()
except KeyError:
pass
def poll2 (timeout=0.0): def poll2 (timeout=0.0):
import poll import poll
# timeout is in milliseconds # timeout is in milliseconds
timeout = int(timeout*1000) timeout = int(timeout*1000)
if socket_map: if socket_map:
fd_map = {}
for s in socket_map.keys():
fd_map[s.fileno()] = s
l = [] l = []
for fd, s in fd_map.items(): for fd, obj in socket_map.items():
flags = 0 flags = 0
if s.readable(): if obj.readable():
flags = poll.POLLIN flags = poll.POLLIN
if s.writable(): if obj.writable():
flags = flags | poll.POLLOUT flags = flags | poll.POLLOUT
if flags: if flags:
l.append (fd, flags) l.append (fd, flags)
r = poll.poll (l, timeout) r = poll.poll (l, timeout)
for fd, flags in r: for fd, flags in r:
s = fd_map[fd] try:
obj = socket_map[fd]
try: try:
if (flags & poll.POLLIN): if (flags & poll.POLLIN):
s.handle_read_event() obj.handle_read_event()
if (flags & poll.POLLOUT): if (flags & poll.POLLOUT):
s.handle_write_event() obj.handle_write_event()
if (flags & poll.POLLERR): except ExitNow:
s.handle_expt_event() raise ExitNow
except: except:
s.handle_error() obj.handle_error()
except KeyError:
pass
def loop (timeout=30.0, use_poll=0): def loop (timeout=30.0, use_poll=0):
...@@ -143,23 +167,25 @@ class dispatcher: ...@@ -143,23 +167,25 @@ class dispatcher:
return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar) return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar)
def add_channel (self): def add_channel (self):
self.log_info ('adding channel %s' % self) #self.log_info ('adding channel %s' % self)
socket_map [self] = 1 socket_map [self._fileno] = self
def del_channel (self): def del_channel (self):
if socket_map.has_key (self): fd = self._fileno
self.log_info ('closing channel %d:%s' % (self.fileno(), self)) if socket_map.has_key (fd):
del socket_map [self] #self.log_info ('closing channel %d:%s' % (fd, self))
del socket_map [fd]
def create_socket (self, family, type): def create_socket (self, family, type):
self.family_and_type = family, type self.family_and_type = family, type
self.socket = socket.socket (family, type) self.socket = socket.socket (family, type)
self.socket.setblocking(0) self.socket.setblocking(0)
self._fileno = self.socket.fileno()
self.add_channel() self.add_channel()
def set_socket (self, socket): def set_socket (self, sock):
# This is done so we can be called safely from __init__ self.__dict__['socket'] = sock
self.__dict__['socket'] = socket self._fileno = sock.fileno()
self.add_channel() self.add_channel()
def set_reuse_addr (self): def set_reuse_addr (self):
...@@ -261,7 +287,6 @@ class dispatcher: ...@@ -261,7 +287,6 @@ class dispatcher:
# cheap inheritance, used to pass all other attribute # cheap inheritance, used to pass all other attribute
# references to the underlying socket object. # references to the underlying socket object.
# NOTE: this may be removed soon for performance reasons.
def __getattr__ (self, attr): def __getattr__ (self, attr):
return getattr (self.socket, attr) return getattr (self.socket, attr)
...@@ -270,11 +295,11 @@ class dispatcher: ...@@ -270,11 +295,11 @@ class dispatcher:
# and 'log_info' is for informational, warning and error logging. # and 'log_info' is for informational, warning and error logging.
def log (self, message): def log (self, message):
print 'log:', message sys.stderr.write ('log: %s\n' % str(message))
def log_info (self, message, type='info'): def log_info (self, message, type='info'):
if __debug__ or type != 'info': if __debug__ or type != 'info':
print '%s: %s' %(type, message) print '%s: %s' % (type, message)
def handle_read_event (self): def handle_read_event (self):
if self.accepting: if self.accepting:
...@@ -398,7 +423,7 @@ def compact_traceback (): ...@@ -398,7 +423,7 @@ def compact_traceback ():
def close_all (): def close_all ():
global socket_map global socket_map
for x in socket_map.keys(): for x in socket_map.values():
x.socket.close() x.socket.close()
socket_map.clear() socket_map.clear()
...@@ -449,6 +474,7 @@ if os.name == 'posix': ...@@ -449,6 +474,7 @@ if os.name == 'posix':
self.set_file (fd) self.set_file (fd)
def set_file (self, fd): def set_file (self, fd):
self._fileno = fd
self.socket = file_wrapper (fd) self.socket = file_wrapper (fd)
self.add_channel() self.add_channel()
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# If you are interested in using this software in a commercial context, # If you are interested in using this software in a commercial context,
# or in purchasing support, please contact the author. # or in purchasing support, please contact the author.
RCS_ID = '$Id: ftp_server.py,v 1.8 1999/11/15 21:53:56 amos Exp $' RCS_ID = '$Id: ftp_server.py,v 1.9 2000/01/14 02:35:56 amos Exp $'
# An extensible, configurable, asynchronous FTP server. # An extensible, configurable, asynchronous FTP server.
# #
...@@ -336,6 +336,7 @@ class ftp_channel (asynchat.async_chat): ...@@ -336,6 +336,7 @@ class ftp_channel (asynchat.async_chat):
self.current_mode = t self.current_mode = t
self.respond ('200 Type set to %s.' % self.type_map[t]) self.respond ('200 Type set to %s.' % self.type_map[t])
def cmd_quit (self, line): def cmd_quit (self, line):
'terminate session' 'terminate session'
self.respond ('221 Goodbye.') self.respond ('221 Goodbye.')
...@@ -848,12 +849,15 @@ class xmit_channel (asynchat.async_chat): ...@@ -848,12 +849,15 @@ class xmit_channel (asynchat.async_chat):
self.client_addr = client_addr self.client_addr = client_addr
asynchat.async_chat.__init__ (self) asynchat.async_chat.__init__ (self)
def readable (self): # def __del__ (self):
return 0 # print 'xmit_channel.__del__()'
def log(self, *args): def log (*args):
pass pass
def readable (self):
return not self.connected
def writable (self): def writable (self):
return 1 return 1
...@@ -1054,13 +1058,7 @@ if os.name == 'posix': ...@@ -1054,13 +1058,7 @@ if os.name == 'posix':
self.log_info('FTP server shutting down. (received SIGINT)', 'warning') self.log_info('FTP server shutting down. (received SIGINT)', 'warning')
# close everything down on SIGINT. # close everything down on SIGINT.
# of course this should be a cleaner shutdown. # of course this should be a cleaner shutdown.
sm = socket.socket_map asyncore.close_all()
socket.socket_map = {}
for sock in sm.values():
try:
sock.close()
except:
pass
if __name__ == '__main__': if __name__ == '__main__':
test (sys.argv[1]) test (sys.argv[1])
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# interested in using this software in a commercial context, or in # interested in using this software in a commercial context, or in
# purchasing support, please contact the author. # purchasing support, please contact the author.
RCS_ID = '$Id: http_server.py,v 1.13 1999/11/15 21:53:56 amos Exp $' RCS_ID = '$Id: http_server.py,v 1.14 2000/01/14 02:35:56 amos Exp $'
# python modules # python modules
import os import os
...@@ -385,7 +385,7 @@ class http_channel (asynchat.async_chat): ...@@ -385,7 +385,7 @@ class http_channel (asynchat.async_chat):
def kill_zombies (self): def kill_zombies (self):
now = int (time.time()) now = int (time.time())
for channel in asyncore.socket_map.keys(): for channel in asyncore.socket_map.values():
if channel.__class__ == self.__class__: if channel.__class__ == self.__class__:
if (now - channel.creation_time) > channel.zombie_timeout: if (now - channel.creation_time) > channel.zombie_timeout:
channel.close() channel.close()
...@@ -461,27 +461,18 @@ class http_channel (asynchat.async_chat): ...@@ -461,27 +461,18 @@ class http_channel (asynchat.async_chat):
return return
request = lines[0] request = lines[0]
try:
command, uri, version = crack_request (request) command, uri, version = crack_request (request)
except:
# deal with broken HTTP requests
try:
# maybe there were spaces in the URL
parts=string.split(request)
command, uri, version = crack_request(
'%s %s %s' % (parts[0], parts[1], parts[-1]))
except:
self.log_info('Bad HTTP request: %s' % request, 'error')
r = http_request (self, request,
None, None, None, join_headers(lines[1:]))
r.error(400)
return
header = join_headers (lines[1:]) header = join_headers (lines[1:])
r = http_request (self, request, command, uri, version, header) r = http_request (self, request, command, uri, version, header)
self.request_counter.increment() self.request_counter.increment()
self.server.total_requests.increment() self.server.total_requests.increment()
if command is None:
self.log_info('Bad HTTP request: %s' % request, 'error')
r.error(400)
return
# -------------------------------------------------- # --------------------------------------------------
# handler selection and dispatch # handler selection and dispatch
# -------------------------------------------------- # --------------------------------------------------
...@@ -612,7 +603,14 @@ class http_server (asyncore.dispatcher): ...@@ -612,7 +603,14 @@ class http_server (asyncore.dispatcher):
# accept. socketmodule.c:makesockaddr complains that the # accept. socketmodule.c:makesockaddr complains that the
# address family is unknown. We don't want the whole server # address family is unknown. We don't want the whole server
# to shut down because of this. # to shut down because of this.
self.log_info('Server accept() threw an exception', 'warning') self.log_info ('warning: server accept() threw an exception', 'warning')
return
except TypeError:
# unpack non-sequence. this can happen when a read event
# fires on a listening socket, but when we call accept()
# we get EWOULDBLOCK, so dispatcher.accept() returns None.
# Seen on FreeBSD3.
self.log_info ('warning: server accept() threw EWOULDBLOCK', 'warning')
return return
self.channel_class (self, conn, addr) self.channel_class (self, conn, addr)
...@@ -689,6 +687,8 @@ def crack_request (r): ...@@ -689,6 +687,8 @@ def crack_request (r):
else: else:
version = None version = None
return string.lower (REQUEST.group (1)), REQUEST.group(2), version return string.lower (REQUEST.group (1)), REQUEST.group(2), version
else:
return None, None, None
class fifo: class fifo:
def __init__ (self, list=None): def __init__ (self, list=None):
......
...@@ -5,14 +5,13 @@ ...@@ -5,14 +5,13 @@
# python REPL channel. # python REPL channel.
# #
RCS_ID = '$Id: monitor.py,v 1.5 1999/07/21 17:15:53 klm Exp $' RCS_ID = '$Id: monitor.py,v 1.6 2000/01/14 02:35:56 amos Exp $'
import md5 import md5
import socket import socket
import string import string
import sys import sys
import time import time
import traceback
VERSION = string.split(RCS_ID)[2] VERSION = string.split(RCS_ID)[2]
...@@ -32,7 +31,7 @@ class monitor_channel (asynchat.async_chat): ...@@ -32,7 +31,7 @@ class monitor_channel (asynchat.async_chat):
self.set_terminator ('\r\n') self.set_terminator ('\r\n')
self.data = '' self.data = ''
# local bindings specific to this channel # local bindings specific to this channel
self.local_env = {} self.local_env = sys.modules['__main__'].__dict__.copy()
self.push ('Python ' + sys.version + '\r\n') self.push ('Python ' + sys.version + '\r\n')
self.push (sys.copyright+'\r\n') self.push (sys.copyright+'\r\n')
self.push ('Welcome to %s\r\n' % self) self.push ('Welcome to %s\r\n' % self)
...@@ -94,7 +93,6 @@ class monitor_channel (asynchat.async_chat): ...@@ -94,7 +93,6 @@ class monitor_channel (asynchat.async_chat):
result = eval (co, self.local_env) result = eval (co, self.local_env)
method = 'eval' method = 'eval'
if result is not None: if result is not None:
self.log_info(repr(result))
print repr(result) print repr(result)
self.local_env['_'] = result self.local_env['_'] = result
except SyntaxError: except SyntaxError:
...@@ -121,11 +119,8 @@ class monitor_channel (asynchat.async_chat): ...@@ -121,11 +119,8 @@ class monitor_channel (asynchat.async_chat):
except: except:
method = 'exception' method = 'exception'
self.multi_line = [] self.multi_line = []
t, v, tb = sys.exc_info()
(file, fun, line), t, v, tbinfo = asyncore.compact_traceback() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback()
self.log_info('%s %s %s' %(t, v, tbinfo), 'warning') self.log_info('%s %s %s' %(t, v, tbinfo), 'warning')
traceback.print_exception(t, v, tb)
del tb
finally: finally:
sys.stdout = oldout sys.stdout = oldout
sys.stderr = olderr sys.stderr = olderr
...@@ -229,7 +224,6 @@ class secure_monitor_channel (monitor_channel): ...@@ -229,7 +224,6 @@ class secure_monitor_channel (monitor_channel):
self.push ('Python ' + sys.version + '\r\n') self.push ('Python ' + sys.version + '\r\n')
self.push (sys.copyright+'\r\n') self.push (sys.copyright+'\r\n')
self.push ('Welcome to %s\r\n' % self) self.push ('Welcome to %s\r\n' % self)
self.push ("[Hint: try 'from __main__ import *']\r\n")
self.prompt() self.prompt()
self.data = '' self.data = ''
else: else:
......
...@@ -60,7 +60,7 @@ class monitor_client (asynchat.async_chat): ...@@ -60,7 +60,7 @@ class monitor_client (asynchat.async_chat):
def handle_close (self): def handle_close (self):
# close all the channels, which will make the standard main # close all the channels, which will make the standard main
# loop exit. # loop exit.
map (lambda x: x.close(), asyncore.socket_map.keys()) map (lambda x: x.close(), asyncore.socket_map.values())
def log (self, *ignore): def log (self, *ignore):
pass pass
......
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
VERSION_STRING = "$Id: select_trigger.py,v 1.8 1999/10/29 15:11:58 brian Exp $" VERSION_STRING = "$Id: select_trigger.py,v 1.9 2000/01/14 02:35:56 amos Exp $"
import asyncore import asyncore
import asynchat import asynchat
...@@ -82,15 +82,15 @@ if os.name == 'posix': ...@@ -82,15 +82,15 @@ if os.name == 'posix':
thunk() thunk()
except: except:
(file, fun, line), t, v, tbinfo = asyncore.compact_traceback() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback()
self.log_info( print 'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo)
'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo),
'error')
self.thunks = [] self.thunks = []
finally: finally:
self.lock.release() self.lock.release()
else: else:
# win32-safe version
class trigger (asyncore.dispatcher): class trigger (asyncore.dispatcher):
address = ('127.9.9.9', 19999) address = ('127.9.9.9', 19999)
...@@ -99,22 +99,8 @@ else: ...@@ -99,22 +99,8 @@ else:
a = socket.socket (socket.AF_INET, socket.SOCK_STREAM) a = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
w = socket.socket (socket.AF_INET, socket.SOCK_STREAM) w = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
# set TCP_NODELAY to true to avoid buffering
w.setsockopt(socket.IPPROTO_TCP, 1, 1)
# tricky: get a pair of connected sockets # tricky: get a pair of connected sockets
host='127.9.9.9' a.bind (self.address)
port=19999
while 1:
try:
self.address=(host, port)
a.bind(self.address)
break
except:
if port <= 19950:
raise 'Bind Error', 'Cannot bind trigger!'
port=port - 1
a.listen (1) a.listen (1)
w.setblocking (0) w.setblocking (0)
try: try:
...@@ -161,9 +147,7 @@ else: ...@@ -161,9 +147,7 @@ else:
thunk() thunk()
except: except:
(file, fun, line), t, v, tbinfo = asyncore.compact_traceback() (file, fun, line), t, v, tbinfo = asyncore.compact_traceback()
self.log_info( print 'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo)
'exception in trigger thunk: (%s:%s %s)' % (t, v, tbinfo),
'error')
self.thunks = [] self.thunks = []
finally: finally:
self.lock.release() self.lock.release()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment