--- RawServer.py.orig Wed Mar 10 15:09:33 2004 +++ RawServer.py Wed Mar 10 17:54:00 2004 @@ -76,7 +76,7 @@ self.raw_server.poll.register(self.socket, all) class RawServer: - def __init__(self, doneflag, timeout_check_interval, timeout, noisy = True, errorfunc = None): + def __init__(self, doneflag, timeout_check_interval, timeout, noisy = True, errorfunc = None, ipv6_enable = 1): self.timeout_check_interval = timeout_check_interval self.timeout = timeout self.poll = poll() @@ -86,6 +86,8 @@ self.doneflag = doneflag self.noisy = noisy self.errorfunc = errorfunc + self.ipv6_enable = ipv6_enable + self.servers = {} self.funcs = [] self.externally_added = [] self.add_task(self.scan_for_timeouts, timeout_check_interval) @@ -107,27 +109,75 @@ if k.socket is not None: self._close_socket(k) - def bind(self, port, bind = '', reuse = False): - server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if reuse: - server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - server.setblocking(0) - server.bind((bind, port)) - server.listen(5) - self.poll.register(server, POLLIN) - self.server = server + def bind(self, port, bind = '', reuse = False, ipv6_bind_ipv4 = 1): + port=int(port) + addrinfos = [] + self.servers = {} + # if bind != "" thread it as a comma seperated list and bind to all + # addresses (can be IPs or hostnames) else bind to wildcard ipv6 and + # ipv4 address + if bind: + if self.ipv6_enable and socket.has_ipv6: + socktype = socket.AF_UNSPEC + else: + socktype = socket.AF_INET + bind = bind.split(',') + for addr in bind: + addrinfos.extend(socket.getaddrinfo(addr, port, + socktype, socket.SOCK_STREAM)) + else: + # wildcard addresses + if self.ipv6_enable: + addrinfos.append([socket.AF_INET6, None, None, None, ('', port)]) + if not addrinfos or ipv6_bind_ipv4 == 0: + addrinfos.append([socket.AF_INET, None, None, None, ('', port)]) + #iterate thru the addrinfos + for addrinfo in addrinfos: + try: + server = socket.socket(addrinfo[0], socket.SOCK_STREAM) + if reuse: + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.setblocking(0) + server.bind(addrinfo[4]) + self.servers[server.fileno()] = server + server.listen(5) + self.poll.register(server, POLLIN) + except socket.error, e: + for server in self.servers.values(): + try: + server.close() + except: + pass + if self.ipv6_enable and ipv6_bind_ipv4 == 0 and self.servers: + raise socket.error('blocked port (may require ipv6_binds_ipv4 to be set)') + raise socket.error(str(e)) + if not self.servers: + raise socket.error('unable to open server port') def start_connection(self, dns, handler = None): if handler is None: - handler = self.handler - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setblocking(0) - try: - sock.connect_ex(dns) - except socket.error: - raise - except Exception, e: - raise socket.error(str(e)) + handler = self.handler + if self.ipv6_enable and socket.has_ipv6: + socktype = socket.AF_UNSPEC + else: + socktype = socket.AF_INET + try: + addrinfos = socket.getaddrinfo(dns[0], int(dns[1]), socktype, + socket.SOCK_STREAM) + except socket.error, e: + raise + except Exception, e: + raise socket.error(str(e)) + for addrinfo in addrinfos: + try: + sock = socket.socket(addrinfo[0], socket.SOCK_STREAM) + sock.setblocking(0) + sock.connect_ex(addinfo[4]) + break + except: + pass + else: + raise socket.error('unable to connect') self.poll.register(sock, POLLIN) s = SingleSocket(self, sock, handler) self.single_sockets[sock.fileno()] = s @@ -135,14 +185,16 @@ def handle_events(self, events): for sock, event in events: - if sock == self.server.fileno(): + s = self.serves.get(sock) + if s: if event & (POLLHUP | POLLERR) != 0: - self.poll.unregister(self.server) - self.server.close() + self.poll.unregister(s) + s.close() + del self.servers[sock] self.errorfunc('lost server socket') else: try: - newsock, addr = self.server.accept() + newsock, addr = s.accept() newsock.setblocking(0) nss = SingleSocket(self, newsock, self.handler) self.single_sockets[newsock.fileno()] = nss @@ -226,11 +278,19 @@ except: data = StringIO() print_exc(file = data) - self.errorfunc(data.getvalue()) + # self.errorfunc(data.getvalue()) + # this one raises an exception - I don't know why finally: for ss in self.single_sockets.values(): - ss.close() - self.server.close() + try: + ss.close() + except: + pass + for server in self.servers.values(): + try: + server.close() + except: + pass def _close_dead(self): while len(self.dead_from_write) > 0: