Beispiel #1
0
class STORChannel(FTPDataChannel):
    """Channel for uploading one file from client to server"""

    complete_transfer = 0
    _fileno = None  # provide a default for asyncore.dispatcher._fileno

    def __init__(self, control_channel, finish_args):
        self.finish_args = finish_args
        self.inbuf = OverflowableBuffer(control_channel.adj.inbuf_overflow)
        FTPDataChannel.__init__(self, control_channel)
        # Note that this channel starts in async mode.

    def writable(self):
        return 0

    def handle_connect(self):
        pass

    def received(self, data):
        if data:
            self.inbuf.append(data)

    def handle_close(self):
        """Client closed, indicating EOF."""
        c = self.control_channel
        task = FinishSTORTask(c, self.inbuf, self.finish_args)
        self.complete_transfer = 1
        self.close()
        c.queue_task(task)

    def reportDefault(self):
        if not self.complete_transfer:  # pragma: no cover
            self.report('TRANSFER_ABORTED')
Beispiel #2
0
class STORChannel(FTPDataChannel):
    """Channel for uploading one file from client to server"""

    complete_transfer = 0
    _fileno = None  # provide a default for asyncore.dispatcher._fileno

    def __init__(self, control_channel, finish_args):
        self.finish_args = finish_args
        self.inbuf = OverflowableBuffer(control_channel.adj.inbuf_overflow)
        FTPDataChannel.__init__(self, control_channel)
        # Note that this channel starts in async mode.

    def writable(self):
        return 0

    def handle_connect(self):
        pass

    def received(self, data):
        if data:
            self.inbuf.append(data)

    def handle_close(self):
        """Client closed, indicating EOF."""
        c = self.control_channel
        task = FinishSTORTask(c, self.inbuf, self.finish_args)
        self.complete_transfer = 1
        self.close()
        c.queue_task(task)

    def reportDefault(self):
        if not self.complete_transfer: # pragma: no cover
            self.report('TRANSFER_ABORTED')
    def parse_header(self, header_plus):
        """
        Parses the header_plus block of text (the headers plus the
        first line of the request).
        """
        index = header_plus.find(b'\n')
        if index >= 0:
            first_line = header_plus[:index].rstrip()
            header = header_plus[index + 1:]
        else:
            first_line = header_plus.rstrip()
            header = b''
        if PY3:
            first_line = first_line.decode('latin1')
            header = header.decode('latin1')
        self.first_line = first_line
        self.header = header

        lines = self.get_header_lines()
        headers = self.headers
        for line in lines:
            index = line.find(':')
            if index > 0:
                key = line[:index]
                value = line[index + 1:].strip()
                key1 = key.upper().replace('-', '_')
                # If a header already exists, we append subsequent values
                # seperated by a comma. Applications already need to handle
                # the comma seperated values, as HTTP front ends might do
                # the concatenation for you (behavior specified in RFC2616).
                try:
                    headers[key1] += ', %s' % value
                except KeyError:
                    headers[key1] = value
            # else there's garbage in the headers?

        assert isinstance(self.first_line, str)
        command, uri, version = self.crack_first_line()
        self.command = command or ''
        self.uri = uri or ''
        self.version = version
        self.split_uri()

        if version == '1.1':
            te = headers.get('TRANSFER_ENCODING', '')
            if te == 'chunked':
                from zope.server.http.chunking import ChunkedReceiver
                self.chunked = 1
                buf = OverflowableBuffer(self.adj.inbuf_overflow)
                self.body_rcv = ChunkedReceiver(buf)
        if not self.chunked:
            try:
                cl = int(headers.get('CONTENT_LENGTH', 0))
            except ValueError:
                cl = 0
            self.content_length = cl
            if cl > 0:
                buf = OverflowableBuffer(self.adj.inbuf_overflow)
                self.body_rcv = FixedStreamReceiver(cl, buf)
 def __init__(self, conn, addr, adj=None):
     self.addr = addr
     if adj is None:
         adj = default_adj
     self.adj = adj
     self.outbuf = OverflowableBuffer(adj.outbuf_overflow)
     self.creation_time = time()
     asyncore.dispatcher.__init__(self, conn)
Beispiel #5
0
 def __init__(self, conn, addr, adj=None):
     self.addr = addr
     if adj is None:
         adj = default_adj
     self.adj = adj
     self.outbuf = OverflowableBuffer(adj.outbuf_overflow)
     self.creation_time = time()
     asyncore.dispatcher.__init__(self, conn)
Beispiel #6
0
 def __init__(self, control_channel, finish_args):
     self.finish_args = finish_args
     self.inbuf = OverflowableBuffer(control_channel.adj.inbuf_overflow)
     FTPDataChannel.__init__(self, control_channel)
class DualModeChannel(asyncore.dispatcher, object):
    """Channel that switches between asynchronous and synchronous mode.

    Call set_sync() before using a channel in a thread other than
    the thread handling the main loop.

    Call set_async() to give the channel back to the thread handling
    the main loop.
    """

    # will_close is set to True to close the socket.
    will_close = False

    # boolean: async or sync mode
    async_mode = True

    last_activity = 0

    def __init__(self, conn, addr, adj=None):
        self.addr = addr
        if adj is None:
            adj = default_adj
        self.adj = adj
        self.outbuf = OverflowableBuffer(adj.outbuf_overflow)
        self.creation_time = time()
        asyncore.dispatcher.__init__(self, conn)

    #
    # ASYNCHRONOUS METHODS
    #

    def handle_close(self):
        self.close()

    def writable(self):
        if not self.async_mode:
            return 0
        return self.will_close or self.outbuf

    def handle_write(self):
        if not self.async_mode:
            return
        if self.outbuf:
            try:
                self._flush_some()
            except socket.error:
                self.handle_comm_error()
        elif self.will_close:
            self.close()
        self.last_activity = time()

    def readable(self):
        if not self.async_mode:
            return 0
        return not self.will_close

    def handle_read(self):
        if not self.async_mode or self.will_close:
            return
        try:
            data = self.recv(self.adj.recv_bytes)
        except socket.error:
            self.handle_comm_error()
            return
        self.last_activity = time()
        self.received(data)

    def received(self, data):
        """
        Override to receive data in async mode.
        """

    def handle_comm_error(self):
        """
        Designed for handling communication errors that occur
        during asynchronous operations *only*.  Probably should log
        this, but in a different place.
        """
        self.handle_error()

    def set_sync(self):
        """Switches to synchronous mode.

        The main thread will stop calling received().
        """
        self.async_mode = False

    #
    # SYNCHRONOUS METHODS
    #

    def flush(self, block=True):
        """Sends pending data.

        If block is set, this pauses the application.  If it is turned
        off, only the amount of data that can be sent without blocking
        is sent.
        """
        if not block:
            while self._flush_some():
                pass
            return
        blocked = False
        try:
            while self.outbuf:
                # We propagate errors to the application on purpose.
                if not blocked:
                    self.socket.setblocking(1)
                    blocked = True
                self._flush_some()
        finally:
            if blocked:
                self.socket.setblocking(0)

    def set_async(self):
        """Switches to asynchronous mode.

        The main thread will begin calling received() again.
        """
        self.async_mode = True
        self.pull_trigger()
        self.last_activity = time()

    #
    # METHODS USED IN BOTH MODES
    #

    def write(self, data):
        wrote = 0
        if isinstance(data, bytes):
            if data:
                self.outbuf.append(data)
                wrote = len(data)
        else:
            for v in data:
                if v:
                    self.outbuf.append(v)
                    wrote += len(v)

        while len(self.outbuf) >= self.adj.send_bytes:
            # Send what we can without blocking.
            # We propagate errors to the application on purpose
            # (to stop the application if the connection closes).
            if not self._flush_some():
                break

        return wrote

    def pull_trigger(self):
        """Wakes up the main loop.
        """
        the_trigger.pull_trigger()

    def _flush_some(self):
        """Flushes data.

        Returns 1 if some data was sent."""
        outbuf = self.outbuf
        if outbuf and self.connected:
            chunk = outbuf.get(self.adj.send_bytes)
            num_sent = self.send(chunk)
            if num_sent:
                outbuf.skip(num_sent, 1)
                return 1
        return 0

    def close_when_done(self):
        # Flush all possible.
        while self._flush_some():
            pass
        self.will_close = True
        if not self.async_mode:
            # For safety, don't close the socket until the
            # main thread calls handle_write().
            self.async_mode = True
            self.pull_trigger()

    def close(self):
        # Always close in asynchronous mode.  If the connection is
        # closed in a thread, the main loop can end up with a bad file
        # descriptor.
        assert self.async_mode
        self.connected = False
        try:
            asyncore.dispatcher.close(self)
        except AttributeError:  # pragma: no cover (tox coverage environment is python 3)
            # On Python 2.7, this is not idempotent. If we were
            # already closed (or never fully opened) it will
            # raise a AttributeError because it tries to call close()
            # on self.socket, which is None
            pass
Beispiel #8
0
 def __init__(self, control_channel, finish_args):
     self.finish_args = finish_args
     self.inbuf = OverflowableBuffer(control_channel.adj.inbuf_overflow)
     FTPDataChannel.__init__(self, control_channel)
Beispiel #9
0
class DualModeChannel(asyncore.dispatcher):
    """Channel that switches between asynchronous and synchronous mode.

    Call set_sync() before using a channel in a thread other than
    the thread handling the main loop.

    Call set_async() to give the channel back to the thread handling
    the main loop.
    """

    # will_close is set to True to close the socket.
    will_close = False

    # boolean: async or sync mode
    async_mode = True

    def __init__(self, conn, addr, adj=None):
        self.addr = addr
        if adj is None:
            adj = default_adj
        self.adj = adj
        self.outbuf = OverflowableBuffer(adj.outbuf_overflow)
        self.creation_time = time()
        asyncore.dispatcher.__init__(self, conn)

    #
    # ASYNCHRONOUS METHODS
    #

    def handle_close(self):
        self.close()

    def writable(self):
        if not self.async_mode:
            return 0
        return self.will_close or self.outbuf

    def handle_write(self):
        if not self.async_mode:
            return
        if self.outbuf:
            try:
                self._flush_some()
            except socket.error:
                self.handle_comm_error()
        elif self.will_close:
            self.close()
        self.last_activity = time()

    def readable(self):
        if not self.async_mode:
            return 0
        return not self.will_close

    def handle_read(self):
        if not self.async_mode or self.will_close:
            return
        try:
            data = self.recv(self.adj.recv_bytes)
        except socket.error:
            self.handle_comm_error()
            return
        self.last_activity = time()
        self.received(data)

    def received(self, data):
        """
        Override to receive data in async mode.
        """
        pass

    def handle_comm_error(self):
        """
        Designed for handling communication errors that occur
        during asynchronous operations *only*.  Probably should log
        this, but in a different place.
        """
        self.handle_error()

    def set_sync(self):
        """Switches to synchronous mode.

        The main thread will stop calling received().
        """
        self.async_mode = False

    #
    # SYNCHRONOUS METHODS
    #

    def flush(self, block=True):
        """Sends pending data.

        If block is set, this pauses the application.  If it is turned
        off, only the amount of data that can be sent without blocking
        is sent.
        """
        if not block:
            while self._flush_some():
                pass
            return
        blocked = False
        try:
            while self.outbuf:
                # We propagate errors to the application on purpose.
                if not blocked:
                    self.socket.setblocking(1)
                    blocked = True
                self._flush_some()
        finally:
            if blocked:
                self.socket.setblocking(0)

    def set_async(self):
        """Switches to asynchronous mode.

        The main thread will begin calling received() again.
        """
        self.async_mode = True
        self.pull_trigger()
        self.last_activity = time()

    #
    # METHODS USED IN BOTH MODES
    #

    def write(self, data):
        wrote = 0
        if isinstance(data, str):
            if data:
                self.outbuf.append(data)
                wrote = len(data)
        else:
            for v in data:
                if v:
                    self.outbuf.append(v)
                    wrote += len(v)

        while len(self.outbuf) >= self.adj.send_bytes:
            # Send what we can without blocking.
            # We propagate errors to the application on purpose
            # (to stop the application if the connection closes).
            if not self._flush_some():
                break

        return wrote

    def pull_trigger(self):
        """Wakes up the main loop.
        """
        the_trigger.pull_trigger()

    def _flush_some(self):
        """Flushes data.

        Returns 1 if some data was sent."""
        outbuf = self.outbuf
        if outbuf and self.connected:
            chunk = outbuf.get(self.adj.send_bytes)
            num_sent = self.send(chunk)
            if num_sent:
                outbuf.skip(num_sent, 1)
                return 1
        return 0

    def close_when_done(self):
        # Flush all possible.
        while self._flush_some():
            pass
        self.will_close = True
        if not self.async_mode:
            # For safety, don't close the socket until the
            # main thread calls handle_write().
            self.async_mode = True
            self.pull_trigger()

    def close(self):
        # Always close in asynchronous mode.  If the connection is
        # closed in a thread, the main loop can end up with a bad file
        # descriptor.
        assert self.async_mode
        self.connected = False
        asyncore.dispatcher.close(self)