#!/usr/bin/env python ############################################################################# # Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1997, 1998, 1999 # 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/GIOPClientWorker.py,v $ # Version: @(#)$RCSfile: GIOPClientWorker.py,v $ $Revision: 1.6 $ # ############################################################################# """ GIOPClientWorker classes. """ # Fnorb modules. import CORBA, GIOP, OctetStream, Util ############################################################################# # GIOPClientWorker factory. ############################################################################# def GIOPClientWorkerFactory_init(): """ Return the GIOPClientWorker factory. This is a factory function for the GIOPClientWorkerFactory class (the GIOPClientWorker factory is a singleton (ie. there can only be one instance per process)). """ try: factory = GIOPClientWorkerFactory() except GIOPClientWorkerFactory, factory: pass return factory class GIOPClientWorkerFactory: """ Factory for GIOPClientWorker instances. The factory is a singleton (ie. there can only be one instance per process). """ __instance = None def __init__(self): """ Constructor. """ # The factory is a singleton (ie. there can only be one instance per # process). if GIOPClientWorkerFactory.__instance is not None: raise GIOPClientWorkerFactory.__instance GIOPClientWorkerFactory.__instance = self return ######################################################################### # GIOPClientWorkerFactory interface. ######################################################################### def create_worker(self, protocol, address, giop_version): """ Create a new GIOP client worker. """ # Find out what threading-model we are using. model = CORBA.ORB_init()._fnorb_threading_model() # Reactive. if model == Util.REACTIVE: from GIOPClientWorkerReactive import GIOPClientWorkerReactive worker = GIOPClientWorkerReactive(protocol, address, giop_version) # Multi-threaded. else: from GIOPClientWorkerThreaded import GIOPClientWorkerThreaded worker = GIOPClientWorkerThreaded(protocol, address, giop_version) return worker class GIOPClientWorker: """ Abstract base class for GIOPClient workers. """ def send(self, request_id, message): """ Send an operation request to the remote object. """ pass def recv(self, request_id): """ Wait for a specific reply. """ pass def poll(self, request_id): """ Poll for a reply to a specific request. """ pass def peek(self, request_id): """ Peek at the reply for the specified request. This method does *not* delete the reply from the client's queue. """ pass def delete_reply(self, request_id): """ Delete the reply with the specified request id. """ pass def next_request_id(self): """ Return the next request id. """ pass def is_closed(self): """ Has the worker received a close event? """ pass def close_connection(self): """ Close down the connection. """ pass ######################################################################### # Protected interface (this is purely for code re-use between the # reactive and threaded workers). ######################################################################### def _message_received(self, message): """ Called when a complete GIOP message has been received. """ # Communicate the TCS-W into the message message.set_tcs_w(self._get_connection().get_tcs_w()) # Get a cursor for the message. cursor = message.cursor() # Get the GIOP message header. giop_header = message.header() # Make sure that the header has the right magic if giop_header.magic != Util.MAGIC: # Send a 'MessageError' to the server. self._message_error() return # Ensure that we are talking to the correct version of GIOP. if (giop_header.GIOP_version.major != self._giop_version.major or giop_header.GIOP_version.minor != self._giop_version.minor): # Send a 'MessageError' to the server. self._message_error() return # Handle each GIOP message type. # # Reply. if giop_header.message_type == GIOP.Reply.value(): # Select the type code for the reply header. if giop_header.GIOP_version.minor == 0: tc = CORBA.typecode('IDL:omg.org/GIOP/ReplyHeader_1_0:1.0') elif giop_header.GIOP_version.minor == 1: tc = CORBA.typecode('IDL:omg.org/GIOP/ReplyHeader_1_1:1.0') elif giop_header.GIOP_version.minor == 2: tc = CORBA.typecode('IDL:omg.org/GIOP/ReplyHeader_1_2:1.0') else: assert 0, 'Internal error - GIOP minor code unknown' # Unmarshal the reply header. reply_header = tc._fnorb_unmarshal_value(cursor) # Reply received. self._reply_received(reply_header, cursor) # Fragment elif giop_header.message_type == GIOP.Fragment.value(): if giop_header.GIOP_version.minor == 0: # Fragments not supported in GIOP 1.0 self._message_error() elif giop_header.GIOP_version.minor == 1: # Fragments in GIOP 1.1 had no fragment header header = None elif giop_header.GIOP_version.minor == 2: tc = CORBA.typecode('IDL:omg.org/GIOP/FragmentHeader_1_2:1.0') header = tc._fnorb_unmarshal_value(cursor) else: assert 0, 'Internal error' self._fragment_received(header, cursor) # CloseConnection. elif giop_header.message_type == GIOP.CloseConnection.value(): self.close_connection() # MessageError. elif giop_header.message_type == GIOP.MessageError.value(): raise CORBA.COMM_FAILURE() # System exception. # Some unknown message type. else: # Send a 'MessageError' to the server. self._message_error() return def _message_error(self): """ Send a 'MessageError' message to the remote object. """ # Create the 'MessageError' message. message = OctetStream.GIOPMessage(self._giop_version, type=GIOP.MessageError) # Send it! self.send(self.next_request_id(), message) return #############################################################################