#!/usr/bin/env python ############################################################################# # Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1997, 1998, 1999, 2000 # All Rights Reserved. # # The software contained on this media is the property of the DSTC Pty # Ltd. Use of this software is strictly in accordance with the # license agreement in the accompanying LICENSE.HTML file. If your # distribution of this software does not contain a LICENSE.HTML file # then you have no rights to use this software in any manner and # should contact DSTC at the address below to determine an appropriate # licensing arrangement. # # DSTC Pty Ltd # Level 7, GP South # Staff House Road # University of Queensland # St Lucia, 4072 # Australia # Tel: +61 7 3365 4310 # Fax: +61 7 3365 4311 # Email: enquiries@dstc.edu.au # # This software is being provided "AS IS" without warranty of any # kind. In no event shall DSTC Pty Ltd be liable for damage of any # kind arising out of or in connection with the use or performance of # this software. # # Project: Fnorb # File: $Source: /cvsroot/fnorb/fnorb/orb/Nudger.py,v $ # Version: @(#)$RCSfile: Nudger.py,v $ $Revision: 1.11 $ # ############################################################################# """ Nudger (part of the 'Reactor' pattern). """ # Standard/built-in modules. import socket # Fnorb modules. import CORBA, EventHandler, Reactor class Nudger(EventHandler.EventHandler): """ Nudger (part of the 'Reactor' pattern). """ def __init__(self, host='', port=0): """ Constructor. 'host' is the hostname to use when creating my socket. 'port' is the port number to use when creating my socket. """ try: # Create a socket on which to listen for connection requests. listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listen_socket.bind((host, port)) listen_socket.listen(1) # Get the host name, the IP address and the port number of the # socket. # listen_host = host or socket.gethostname() # Get the fully qualified host name hostname, aliaslist, iplst = socket.gethostbyaddr(socket.gethostname()) aliaslist = [hostname] + aliaslist tmphost = "" for currHost in aliaslist: for char in list(currHost): if char == ".": tmphost = currHost break # If none have a period then use the original hostname listen_host = tmphost or hostname or host (listen_ip_address, listen_port) = listen_socket.getsockname() # Under OSF/1 if you specify '' as the host address then the IP # address returned by 'getsockname' will be '0.0.0.0'! #if listen_ip_address == '0.0.0.0': # listen_ip_address = socket.gethostbyname(listen_host) # Now create a client socket and connect it to the listening # socket. This uses the little-known semantics of the 'connect' # function i.e. the call will succeed even *before* the 'accept' # has been performed on the listening socket! If you don't believe # me read Stevens' Network Programming ;^) self.__client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__client.connect((listen_host, listen_port)) # And finally, we do an 'accept' to complete the connection. (self.__server, address) = listen_socket.accept() # Set the server socket to NON-blocking mode. # Jython sockets have no 'setblocking' method. if hasattr(self.__server, 'setblocking'): self.__server.setblocking(0) except socket.error: raise CORBA.COMM_FAILURE() # System exception. # Get a reference to the active reactor. self.__reactor = Reactor.Reactor_init() # Register our interest in 'read' events with the Reactor. self.__reactor.register_handler(self, Reactor.READ) return def __del__(self): """ Destructor. """ self.handle_close() return ######################################################################### # Nudger interface. ######################################################################### def nudge(self): """ Nudge myself! """ self.__client.send('nudge!') return ######################################################################### # EventHandler interface. ######################################################################### def handle_event(self, mask): """ Callback method to handle all events except close events. """ # Read event. if mask & Reactor.READ: self.__read_event() # Exception event. if mask & Reactor.EXCEPTION: self.__exception_event() return def handle_close(self): """ Callback method to handle close events. """ # Withdraw my Reactor registration. self.__reactor.unregister_handler(self, Reactor.READ) # Clean up my sockets. try: self.__client.close() self.__server.close() except socket.error: pass del self.__client del self.__server return def handle(self): """ Return my underlying I/O handle. In this case, my I/O handle is the file descriptor of my socket. """ return self.__server.fileno() ######################################################################### # Private interface. ######################################################################### def __read_event(self): """ Handle a read event. """ # We do nothing! The sole purpose of the nudger is to trip the # reactor out of a blocking select! self.__server.recv(10) return def __exception_event(self): """ Handle an exception event. """ # Clean up. self.handle_close() return #############################################################################