예제 #1
0
    def remove_request(self, identifier, is_global=False):
        """ Cancel a running request.
            NOT ALLOWED WHILE UPLOADING DATA.
        """
        if self.is_uploading():
            raise Exception("Can't remove while uploading. Sorry :-(")

        if not identifier in self.running_clients:
            print "FCPConnection.remove_request -- unknown identifier: ", \
                  identifier
        params = {'Identifier': identifier, 'Global': is_global}
        self.socket.write_bytes(make_request(REMOVE_REQUEST_DEF, params))
예제 #2
0
    def remove_request(self, identifier, is_global = False):
        """ Cancel a running request.
            NOT ALLOWED WHILE UPLOADING DATA.
        """
        if self.is_uploading():
            raise Exception("Can't remove while uploading. Sorry :-(")

        if not identifier in self.running_clients:
            print "FCPConnection.remove_request -- unknown identifier: ", \
                  identifier
        params = {'Identifier': identifier,
                  'Global': is_global}
        self.socket.write_bytes(make_request(REMOVE_REQUEST_DEF, params))
예제 #3
0
    def handled_redirect(self, msg, client):
        """ INTERNAL: Handle code 27 redirects. """

        # BITCH: This is a design flaw in the FCP 2.0 protocol.
        #        They should have used unique numbers for all error
        #        codes so that client coders don't need to keep track
        #        of the initiating request in order to interpret the
        #        error code.
        if client.in_params.definition[0] == 'ClientGet' and is_code(msg, 27):
            #print "Checking for allowed redirect"
            if client.context.allowed_redirects:
                #print "Handling redirect"
                client.context.allowed_redirects -= 1
                assert client.context.initiating_id
                assert client.context.initiating_id in self.running_clients
                assert client.context.running_id
                if client.context.running_id != client.context.initiating_id:
                    # Remove the context for the intermediate redirect.
                    #print "DELETED: ", client.context.running_id
                    del self.running_clients[client.context.running_id]

                client.context.running_id = make_id()
                client.context.last_uri = msg[1]['RedirectURI']

                # Copy, don't modify params.
                params = {}
                params.update(client.in_params.fcp_params)
                params['URI'] = client.context.last_uri
                params['Identifier'] = client.context.running_id

                # Send new request.
                self.socket.write_bytes(
                    make_request(client.in_params.definition, params))

                #print "MAPPED(1) [%s]->[%s]" % (client.context.running_id,
                #                                str(client))
                self.running_clients[client.context.running_id] = client

                # REDFLAG: change callback to include identifier?
                # Hmmm...fixup identifier in msg?
                if client.message_callback:
                    client.message_callback(client, msg)
                return True

        return False
예제 #4
0
    def handled_redirect(self, msg, client):
        """ INTERNAL: Handle code 27 redirects. """

        # BITCH: This is a design flaw in the FCP 2.0 protocol.
        #        They should have used unique numbers for all error
        #        codes so that client coders don't need to keep track
        #        of the initiating request in order to interpret the
        #        error code.
        if client.in_params.definition[0] == 'ClientGet' and is_code(msg, 27):
            #print "Checking for allowed redirect"
            if client.context.allowed_redirects:
                #print "Handling redirect"
                client.context.allowed_redirects -= 1
                assert client.context.initiating_id
                assert client.context.initiating_id in self.running_clients
                assert client.context.running_id
                if client.context.running_id != client.context.initiating_id:
                    # Remove the context for the intermediate redirect.
                    #print "DELETED: ", client.context.running_id
                    del self.running_clients[client.context.running_id]

                client.context.running_id = make_id()
                client.context.last_uri = msg[1]['RedirectURI']

                # Copy, don't modify params.
                params = {}
                params.update(client.in_params.fcp_params)
                params['URI'] = client.context.last_uri
                params['Identifier'] = client.context.running_id

                # Send new request.
                self.socket.write_bytes(make_request(client.in_params.
                                                     definition, params))

                #print "MAPPED(1) [%s]->[%s]" % (client.context.running_id,
                #                                str(client))
                self.running_clients[client.context.running_id] = client

                # REDFLAG: change callback to include identifier?
                # Hmmm...fixup identifier in msg?
                if client.message_callback:
                    client.message_callback(client, msg)
                return True

        return False
예제 #5
0
    def __init__(self, socket_, wait_for_connect=False, state_callback=None):
        """ Create an FCPConnection from an open IAsyncSocket instance.

            REQUIRES: socket_ ready for writing.
        """
        self.running_clients = {}
        # Delegate handles parsing FCP protocol off the wire.
        self.parser = FCPParser()
        self.parser.msg_callback = self.msg_handler
        self.parser.context_callback = self.get_context

        self.socket = socket_
        if state_callback:
            self.state_callback = state_callback
        else:
            self.state_callback = lambda x, y: None
        self.socket.recv_callback = self.parser.parse_bytes
        self.socket.closed_callback = self.closed_handler

        self.node_hello = None

        # Only used for uploads.
        self.data_source = None

        # Tell the client code that we are trying to connect.
        self.state_callback(self, CONNECTING)

        # Send a ClientHello
        params = {
            'Name': 'FCPConnection[%s]' % make_id(),
            'ExpectedVersion': FCP_VERSION
        }
        self.socket.write_bytes(make_request(HELLO_DEF, params))
        if wait_for_connect:
            # Wait for the reply
            while not self.is_connected():
                if not self.socket.poll():
                    raise IOError("Socket closed")
                time.sleep(POLL_TIME_SECS)
예제 #6
0
    def __init__(self, socket_, wait_for_connect = False,
                 state_callback = None):
        """ Create an FCPConnection from an open IAsyncSocket instance.

            REQUIRES: socket_ ready for writing.
        """
        self.running_clients = {}
        # Delegate handles parsing FCP protocol off the wire.
        self.parser = FCPParser()
        self.parser.msg_callback = self.msg_handler
        self.parser.context_callback = self.get_context

        self.socket = socket_
        if state_callback:
            self.state_callback = state_callback
        else:
            self.state_callback = lambda x, y: None
        self.socket.recv_callback = self.parser.parse_bytes
        self.socket.closed_callback = self.closed_handler

        self.node_hello = None

        # Only used for uploads.
        self.data_source = None

        # Tell the client code that we are trying to connect.
        self.state_callback(self, CONNECTING)

        # Send a ClientHello
        params = {'Name':'FCPConnection[%s]' % make_id(),
                  'ExpectedVersion': FCP_VERSION}
        self.socket.write_bytes(make_request(HELLO_DEF, params))
        if wait_for_connect:
            # Wait for the reply
            while not self.is_connected():
                if not self.socket.poll():
                    raise IOError("Socket closed")
                time.sleep(POLL_TIME_SECS)
예제 #7
0
    def start_request(self, client, data_source=None, set_data_length=True):
        """ Start an FCP request.

            If in_params.async is True this returns immediately, otherwise
            it blocks until the request finishes.

            If client.in_params.send_data is set, trailing data is sent
            after the request message.  If data_source is not None, then
            the data in it is sent.  Otherwise if client.in_params.file is
            not None, the data in the file is sent. Finally if neither of
            the other sources are not None the contents of
            client.in_params.send_data are sent.

            If set_data_length is True the 'DataLength' field is set in the
            requests FCP message.

            If in_params.async it True, this method returns the identifier
            for the request, otherwise, returns the FCP message which
            terminated the request.
        """
        assert not self.is_uploading()
        assert not client.context
        assert not client.response
        assert not 'Identifier' in client.in_params.fcp_params
        identifier = make_id()
        client.in_params.fcp_params['Identifier'] = identifier
        write_string = False
        if client.in_params.send_data:
            assert not self.data_source
            if data_source:
                data_source.initialize()
                if set_data_length:
                    client.in_params.fcp_params['DataLength'] = (
                        data_source.data_length())
                self.data_source = data_source
                self.socket.writable_callback = self.writable_handler
            elif client.in_params.file_name:
                self.data_source = FileDataSource(client.in_params.file_name)
                self.data_source.initialize()
                client.in_params.fcp_params['DataLength'] = (
                    self.data_source.data_length())
                self.socket.writable_callback = self.writable_handler
            else:
                client.in_params.fcp_params['DataLength'] = len(
                    client.in_params.send_data)
                write_string = True

        self.socket.write_bytes(
            make_request(client.in_params.definition,
                         client.in_params.fcp_params,
                         client.in_params.default_fcp_params))

        if write_string:
            self.socket.write_bytes(client.in_params.send_data)

        assert not client.context
        client.context = RequestContext(client.in_params.allowed_redirects,
                                        identifier,
                                        client.in_params.fcp_params.get('URI'))
        if not client.in_params.send_data:
            client.context.file_name = client.in_params.file_name

        #print "MAPPED [%s]->[%s]" % (identifier, str(client))
        self.running_clients[identifier] = client

        if self.data_source:
            self.state_callback(self, UPLOADING)

        if client.in_params. async:
            return identifier

        resp = self.wait_for_terminal(client)
        raise_on_error(resp)
        return client.response
예제 #8
0
    def start_request(self, client, data_source = None, set_data_length = True):
        """ Start an FCP request.

            If in_params.async is True this returns immediately, otherwise
            it blocks until the request finishes.

            If client.in_params.send_data is set, trailing data is sent
            after the request message.  If data_source is not None, then
            the data in it is sent.  Otherwise if client.in_params.file is
            not None, the data in the file is sent. Finally if neither of
            the other sources are not None the contents of
            client.in_params.send_data are sent.

            If set_data_length is True the 'DataLength' field is set in the
            requests FCP message.

            If in_params.async it True, this method returns the identifier
            for the request, otherwise, returns the FCP message which
            terminated the request.
        """
        assert not self.is_uploading()
        assert not client.context
        assert not client.response
        assert not 'Identifier' in client.in_params.fcp_params
        identifier = make_id()
        client.in_params.fcp_params['Identifier'] = identifier
        write_string = False
        if client.in_params.send_data:
            assert not self.data_source
            if data_source:
                data_source.initialize()
                if set_data_length:
                    client.in_params.fcp_params['DataLength'] = (data_source.
                                                                 data_length())
                self.data_source = data_source
                self.socket.writable_callback = self.writable_handler
            elif client.in_params.file_name:
                self.data_source = FileDataSource(client.in_params.file_name)
                self.data_source.initialize()
                client.in_params.fcp_params['DataLength'] = (self.
                                                             data_source.
                                                             data_length())
                self.socket.writable_callback = self.writable_handler
            else:
                client.in_params.fcp_params['DataLength'] = len(client.
                                                                in_params.
                                                                send_data)
                write_string = True

        self.socket.write_bytes(make_request(client.in_params.definition,
                                             client.in_params.fcp_params,
                                             client.in_params.
                                             default_fcp_params))

        if write_string:
            self.socket.write_bytes(client.in_params.send_data)

        assert not client.context
        client.context = RequestContext(client.in_params.allowed_redirects,
                                        identifier,
                                        client.in_params.fcp_params.get('URI'))
        if not client.in_params.send_data:
            client.context.file_name = client.in_params.file_name

        #print "MAPPED [%s]->[%s]" % (identifier, str(client))
        self.running_clients[identifier] = client

        if self.data_source:
            self.state_callback(self, UPLOADING)

        if client.in_params.async:
            return identifier

        resp = self.wait_for_terminal(client)
        raise_on_error(resp)
        return client.response