Example #1
0
    def _send(self, message, dest_id=0, dest_seq=0):
        """_send(message, dest_id=0, dest_seq=0)

        Sends a message of raw bytes without checking whether they're bytes.
        Optionally, dest_id and dest_seq represent the message that
        this message  replies to. These are used for the request/reply
        pattern.

        Returns the package that will be send (or None). The context
        will set _source_id on the package right before
        sending it away.

        """

        # Check if still open
        if self._closed:
            className = self.__class__.__name__
            raise IOError("Cannot send from closed %s %i." %
                          (className, id(self)))

        if message:
            # If send_locked, wait at most one second
            if self._is_send_locked:
                self._send_condition.acquire()
                try:
                    self._send_condition.wait(1.0)  # wait for notify
                finally:
                    self._send_condition.release()
                    if time.time() > self._is_send_locked:
                        self._is_send_locked = 0
            # Push it on the queue as a package
            slot = self._slot_out_h
            cid = self._context._id
            p = Package(message, slot, cid, 0, dest_id, dest_seq, 0)
            self._context._send_package(p)
            # Return package
            return p
        else:
            return None
Example #2
0
    def connect(self, address, timeout=1.0, name=''):
        """ connect(self, address, timeout=1.0, name='')
        
        Setup a connection with another context, by connection to a 
        hosting context. An error is raised when the connection could
        not be made.
        
        Returns a Connection instance that represents the
        connection to the other context. These connection objects 
        can also be obtained via the Context.connections property.
        
        Parameters
        ----------
        address : str
            Should be of the shape hostname:port. The port should be an
            integer number between 1024 and 2**16. If port does not 
            represent a number, a valid port number is created using a 
            hash function.
        max_tries : int
            The number of ports to try; starting from the given port, 
            subsequent ports are tried until a free port is available. 
            The final port can be obtained using the 'port' property of
            the returned Connection instance.
        name : string
            The name for the created Connection instance. It can
            be used as a key in the connections property.
        
        Notes on hostname
        -----------------
        The hostname can be:
          * The IP address, or the string hostname of this computer. 
          * 'localhost': the connection is only visible from this computer. 
            Also some low level networking layers are bypassed, which results
            in a faster connection. The other context should also host as
            'localhost'.
          * 'publichost': the connection is visible by other computers on the 
            same network. Optionally an integer index can be appended if
            the machine has multiple IP addresses (see socket.gethostbyname_ex).
        
        """

        # Trigger cleanup of closed connections
        self.connections

        # Split address in protocol, real hostname and port number
        protocol, hostname, port = split_address(address)

        # Based on protocol, instantiate connection class (currently only tcp)
        if False:  #protocol == 'itc':
            connection = ItcConnection(self, name)
        else:
            connection = TcpConnection(self, name)

        # Create new connection and connect it
        connection._connect(hostname, port, timeout)

        # Save connection instance
        self._connections_lock.acquire()
        try:
            # Push packages from startup queue
            while self._startupQueue:
                connection._inject_package(self._startupQueue.pop())
            # Add connection object to list of connections
            self._connections.append(connection)
        finally:
            self._connections_lock.release()

        # Send message in the network to signal a new connection
        bb = 'NEW_CONNECTION'.encode('utf-8')
        p = Package(bb, SLOT_CONTEXT, self._id, 0, 0, 0, 0)
        self._send_package(p)

        # Return Connection instance
        return connection