Beispiel #1
0
 def test_invalid_tid(self):
     bad_tid_dgram = ACKDatagram(123)
     yield self.ws.datagramReceived(bad_tid_dgram.to_wire(),
                                    ('127.0.0.1', 1111))
     err_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value()))
     self.assertEqual(err_dgram.errorcode, ERR_TID_UNKNOWN)
     self.addCleanup(self.ws.cancel)
Beispiel #2
0
 def test_non_rq_datagram(self):
     tftp = TFTP(DummyBackend(), _clock=self.clock)
     tftp.transport = self.transport
     ack_datagram = ACKDatagram(14)
     tftp.datagramReceived(ack_datagram.to_wire(), ('127.0.0.1', 1111))
     self.failIf(self.transport.disconnecting)
     self.failIf(self.transport.value())
Beispiel #3
0
    def test_option_normal(self):
        self.ws.startProtocol()
        self.clock.advance(0.1)
        oack_datagram = OACKDatagram(self.options).to_wire()
        self.assertEqual(self.transport.value(), oack_datagram)
        self.clock.advance(3)
        self.assertEqual(self.transport.value(), oack_datagram * 2)

        self.transport.clear()
        self.ws.datagramReceived(
            DATADatagram(1, b'foobarbaz').to_wire(), ('127.0.0.1', 65465))
        self.clock.pump((1, ) * 3)
        self.assertEqual(self.transport.value(), ACKDatagram(1).to_wire())
        self.assertEqual(self.ws.session.block_size, 9)

        self.transport.clear()
        self.ws.datagramReceived(
            DATADatagram(2, b'smthng').to_wire(), ('127.0.0.1', 65465))
        self.clock.pump((1, ) * 3)
        self.assertEqual(self.transport.value(), ACKDatagram(2).to_wire())
        self.clock.pump((1, ) * 10)
        self.writer.finish()
        self.assertEqual(
            self.writer.file_path.open('r').read(), b'foobarbazsmthng')
        self.assertTrue(self.transport.disconnecting)
 def cb(res):
     self.clock.advance(0.1)
     ack_datagram_1 = ACKDatagram(1)
     self.assertEqual(self.transport.value(), ack_datagram_1.to_wire())
     self.assertEqual(self.target.open('r').read(), 'foobar')
     self.failIf(self.transport.disconnecting)
     self.addCleanup(self.ws.cancel)
    def test_option_normal(self):
        self.ws.startProtocol()
        self.ws.datagramReceived(OACKDatagram({'blksize':'12'}).to_wire(), ('127.0.0.1', 65465))
        self.clock.advance(0.1)
        self.assertEqual(self.ws.session.block_size, WriteSession.block_size)
        self.assertEqual(self.transport.value(), ACKDatagram(0).to_wire())

        self.transport.clear()
        self.ws.datagramReceived(OACKDatagram({'blksize':'9'}).to_wire(), ('127.0.0.1', 65465))
        self.clock.advance(0.1)
        self.assertEqual(self.ws.session.block_size, WriteSession.block_size)
        self.assertEqual(self.transport.value(), ACKDatagram(0).to_wire())

        self.transport.clear()
        self.ws.datagramReceived(DATADatagram(1, 'foobarbaz').to_wire(), ('127.0.0.1', 65465))
        self.clock.advance(3)
        self.failUnless(self.ws.session.started)
        self.clock.advance(0.1)
        self.assertEqual(self.ws.session.block_size, 9)
        self.assertEqual(self.transport.value(), ACKDatagram(1).to_wire())

        self.transport.clear()
        self.ws.datagramReceived(DATADatagram(2, 'asdfghjkl').to_wire(), ('127.0.0.1', 65465))
        self.clock.advance(3)
        self.assertEqual(self.transport.value(), ACKDatagram(2).to_wire())
        self.writer.finish()
        self.assertEqual(self.writer.file_path.open('r').read(), 'foobarbazasdfghjkl')

        self.transport.clear()
        self.ws.datagramReceived(OACKDatagram({'blksize':'12'}).to_wire(), ('127.0.0.1', 65465))
        self.clock.advance(0.1)
        self.assertEqual(self.ws.session.block_size, 9)
        self.assertEqual(self.transport.value(), ACKDatagram(0).to_wire())
 def test_non_rq_datagram(self):
     tftp = TFTP(DummyBackend(), _clock=self.clock)
     tftp.transport = self.transport
     ack_datagram = ACKDatagram(14)
     tftp.datagramReceived(ack_datagram.to_wire(), ("127.0.0.1", 1111))
     self.failIf(self.transport.disconnecting)
     self.failIf(self.transport.value())
Beispiel #7
0
 def cb(res):
     self.clock.advance(0.1)
     ack_datagram_1 = ACKDatagram(1)
     self.assertEqual(self.transport.value(), ack_datagram_1.to_wire())
     self.assertEqual(self.target.open('r').read(), 'foobar')
     self.failIf(self.transport.disconnecting)
     self.addCleanup(self.ws.cancel)
Beispiel #8
0
    def test_invalid_tid(self):
        self.ws.startProtocol()
        bad_tid_dgram = ACKDatagram(123)
        self.ws.datagramReceived(bad_tid_dgram.to_wire(), ('127.0.0.1', 1111))

        err_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value()))
        self.assertEqual(err_dgram.errorcode, ERR_TID_UNKNOWN)
        self.addCleanup(self.ws.cancel)
Beispiel #9
0
 def test_local_origin_read_session_handshake_success(self):
     self.clock.advance(1)
     ack_datagram = ACKDatagram(0)
     self.rs.datagramReceived(ack_datagram.to_wire(), ('127.0.0.1', 65465))
     self.clock.advance(2)
     self.assertTrue(self.transport.value())
     self.assertFalse(self.transport.disconnecting)
     self.addCleanup(self.rs.cancel)
 def test_local_origin_read_session_handshake_success(self):
     self.clock.advance(1)
     ack_datagram = ACKDatagram(0)
     self.rs.datagramReceived(ack_datagram.to_wire(), ("127.0.0.1", 65465))
     self.clock.advance(2)
     self.failUnless(self.transport.value())
     self.failIf(self.transport.disconnecting)
     self.failIf(self.wd.active())
     self.addCleanup(self.rs.cancel)
Beispiel #11
0
 def test_ack(self):
     # Zero-length payload
     self.assertRaises(WireProtocolError, ACKDatagram.from_wire, '')
     # One byte payload
     self.assertRaises(WireProtocolError, ACKDatagram.from_wire, '\x00')
     # Full-length payload
     self.assertEqual(ACKDatagram.from_wire('\x00\x0a').blocknum, 10)
     self.assertEqual(ACKDatagram.from_wire('\x00\x0a').to_wire(), '\x00\x04\x00\x0a')
     # Extra data in payload
     self.assertRaises(WireProtocolError, ACKDatagram.from_wire, '\x00\x10foobarz')
 def test_ack(self):
     # Zero-length payload
     self.assertRaises(WireProtocolError, ACKDatagram.from_wire, b'')
     # One byte payload
     self.assertRaises(WireProtocolError, ACKDatagram.from_wire, b'\x00')
     # Full-length payload
     self.assertEqual(ACKDatagram.from_wire(b'\x00\x0a').blocknum, 10)
     self.assertEqual(
         ACKDatagram.from_wire(b'\x00\x0a').to_wire(), b'\x00\x04\x00\x0a')
     # Extra data in payload
     self.assertRaises(WireProtocolError, ACKDatagram.from_wire,
                       b'\x00\x10foobarz')
Beispiel #13
0
    def tftp_OACK(self, datagram):
        """Handle the OACK datagram

        @param datagram: OACK datagram
        @type datagram: L{OACKDatagram}

        """
        if not self.session.started:
            self.resultant_options = self.processOptions(datagram.options)
            self.timeout_watchdog.cancel()
            return self.transport.write(ACKDatagram(0).to_wire())
        else:
            log.msg("Duplicate OACK received, send back ACK and ignore")
            self.transport.write(ACKDatagram(0).to_wire())
Beispiel #14
0
    def test_ACK_backoff(self):
        self.rs.block_size = 5
        self.rs.blocknum = 1

        ack_datagram = ACKDatagram(1)
        d = self.rs.datagramReceived(ack_datagram)

        def cb(ign):

            self.clock.pump((1, ) * 4)
            # Sent two times - initial send and a retransmit after first timeout
            self.assertEqual(self.transport.value(),
                             DATADatagram(2, self.test_data[:5]).to_wire() * 2)

            # Sent three times - initial send and two retransmits
            self.clock.pump((1, ) * 5)
            self.assertEqual(self.transport.value(),
                             DATADatagram(2, self.test_data[:5]).to_wire() * 3)

            # Sent still three times - initial send, two retransmits and the last wait
            self.clock.pump((1, ) * 10)
            self.assertEqual(self.transport.value(),
                             DATADatagram(2, self.test_data[:5]).to_wire() * 3)

            self.assertTrue(self.transport.disconnecting)

        d.addCallback(cb)
        self.clock.advance(2.5)
        return d
Beispiel #15
0
    def test_option_normal(self):
        self.rs.startProtocol()
        self.rs.datagramReceived(
            OACKDatagram({
                b'blksize': b'9'
            }).to_wire(), ('127.0.0.1', 65465))
        self.clock.advance(0.1)
        self.assertEqual(self.rs.session.block_size, 9)
        self.clock.pump((1, ) * 3)
        self.assertEqual(self.transport.value(),
                         DATADatagram(1, self.test_data[:9]).to_wire())

        self.rs.datagramReceived(
            OACKDatagram({
                b'blksize': b'12'
            }).to_wire(), ('127.0.0.1', 65465))
        self.clock.advance(0.1)
        self.assertEqual(self.rs.session.block_size, 9)

        self.transport.clear()
        self.rs.datagramReceived(
            ACKDatagram(1).to_wire(), ('127.0.0.1', 65465))
        self.clock.pump((1, ) * 3)
        self.assertEqual(self.transport.value(),
                         DATADatagram(2, self.test_data[9:18]).to_wire())

        self.addCleanup(self.rs.cancel)
Beispiel #16
0
 def test_ACK_invalid_blocknum(self):
     ack_datagram = ACKDatagram(3)
     yield self.rs.datagramReceived(ack_datagram)
     self.assertFalse(self.transport.disconnecting)
     err_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value()))
     self.assertTrue(isinstance(err_dgram, ERRORDatagram))
     self.addCleanup(self.rs.cancel)
Beispiel #17
0
 def test_ACK_stale_blocknum(self):
     self.rs.blocknum = 2
     ack_datagram = ACKDatagram(1)
     yield self.rs.datagramReceived(ack_datagram)
     self.failIf(self.transport.disconnecting)
     self.failIf(self.transport.value(),
                 "Stale ACK datagram, we should not write anything back")
     self.addCleanup(self.rs.cancel)
Beispiel #18
0
        def cb(ign):
            self.clock.advance(0.1)
            ack_datagram = ACKDatagram(1)

            self.clock.pump((1,) * 5)
            # Sent two times - initial send and a retransmit after first timeout
            self.assertEqual(self.transport.value(), ack_datagram.to_wire() * 2)

            # Sent three times - initial send and two retransmits
            self.clock.pump((1,) * 4)
            self.assertEqual(self.transport.value(), ack_datagram.to_wire() * 3)

            # Sent still three times - initial send, two retransmits and the last wait
            self.clock.pump((1,) * 4)
            self.assertEqual(self.transport.value(), ack_datagram.to_wire() * 3)

            self.failUnless(self.transport.disconnecting)
Beispiel #19
0
        def cb(ign):
            self.clock.advance(0.1)
            ack_datagram = ACKDatagram(2)
            # This datagram doesn't trigger any sends
            self.rs.datagramReceived(ack_datagram)

            self.assertEqual(self.transport.value(), DATADatagram(2, self.test_data).to_wire())
            self.failUnless(self.rs.completed,
                        "Data length is less, than blocksize, time to stop")
Beispiel #20
0
 def test_local_origin_write_session_handshake_success(self):
     self.ws.session.block_size = 6
     self.ws.startProtocol()
     self.clock.advance(1)
     data_datagram = DATADatagram(1, b'foobar')
     self.ws.datagramReceived(data_datagram.to_wire(), ('127.0.0.1', 65465))
     self.clock.pump((1,)*3)
     self.assertEqual(self.transport.value(), ACKDatagram(1).to_wire())
     self.assertFalse(self.transport.disconnecting)
     self.addCleanup(self.ws.cancel)
    def test_remote_origin_write_bootstrap(self):
        # Initial ACK
        ack_datagram_0 = ACKDatagram(0)
        self.clock.advance(0.1)
        self.assertEqual(self.transport.value(), ack_datagram_0.to_wire())
        self.failIf(self.transport.disconnecting)

        # Normal exchange
        self.transport.clear()
        d = self.ws.datagramReceived(DATADatagram(1, 'foobar').to_wire(), ('127.0.0.1', 65465))
        def cb(res):
            self.clock.advance(0.1)
            ack_datagram_1 = ACKDatagram(1)
            self.assertEqual(self.transport.value(), ack_datagram_1.to_wire())
            self.assertEqual(self.target.open('r').read(), 'foobar')
            self.failIf(self.transport.disconnecting)
            self.addCleanup(self.ws.cancel)
        d.addCallback(cb)
        self.clock.advance(3)
        return d
Beispiel #22
0
        def cb(ign):
            self.clock.advance(0.1)
            ack_datagram = ACKDatagram(1)

            self.clock.pump((1, ) * 5)
            # Sent two times - initial send and a retransmit after first timeout
            self.assertEqual(self.transport.value(),
                             ack_datagram.to_wire() * 2)

            # Sent three times - initial send and two retransmits
            self.clock.pump((1, ) * 4)
            self.assertEqual(self.transport.value(),
                             ack_datagram.to_wire() * 3)

            # Sent still three times - initial send, two retransmits and the last wait
            self.clock.pump((1, ) * 4)
            self.assertEqual(self.transport.value(),
                             ack_datagram.to_wire() * 3)

            self.assertTrue(self.transport.disconnecting)
Beispiel #23
0
    def test_remote_origin_write_bootstrap(self):
        # Initial ACK
        ack_datagram_0 = ACKDatagram(0)
        self.clock.advance(0.1)
        self.assertEqual(self.transport.value(), ack_datagram_0.to_wire())
        self.failIf(self.transport.disconnecting)

        # Normal exchange
        self.transport.clear()
        d = self.ws.datagramReceived(DATADatagram(1, 'foobar').to_wire(), ('127.0.0.1', 65465))
        def cb(res):
            self.clock.advance(0.1)
            ack_datagram_1 = ACKDatagram(1)
            self.assertEqual(self.transport.value(), ack_datagram_1.to_wire())
            self.assertEqual(self.target.open('r').read(), 'foobar')
            self.failIf(self.transport.disconnecting)
            self.addCleanup(self.ws.cancel)
        d.addCallback(cb)
        self.clock.advance(3)
        return d
Beispiel #24
0
 def test_failed_read(self):
     self.reader.finish()
     self.rs.reader = FailingReader()
     self.rs.blocknum = 1
     ack_datagram = ACKDatagram(1)
     yield self.rs.datagramReceived(ack_datagram)
     self.flushLoggedErrors()
     self.clock.advance(0.1)
     err_datagram = TFTPDatagramFactory(*split_opcode(self.transport.value()))
     self.failUnless(isinstance(err_datagram, ERRORDatagram))
     self.failUnless(self.transport.disconnecting)
    def test_option_normal(self):
        self.rs.startProtocol()
        self.clock.advance(0.1)
        oack_datagram = OACKDatagram(self.options).to_wire()
        self.assertEqual(self.transport.value(), oack_datagram)
        self.clock.advance(3)
        self.assertEqual(self.transport.value(), oack_datagram * 2)

        self.transport.clear()
        self.rs.datagramReceived(ACKDatagram(0).to_wire(), ('127.0.0.1', 65465))
        self.clock.pump((1,)*3)
        self.assertEqual(self.transport.value(), DATADatagram(1, self.test_data[:9]).to_wire())

        self.addCleanup(self.rs.cancel)
Beispiel #26
0
    def startProtocol(self):
        """Connect the transport, respond with an initial ACK or OACK (depending on
        if we were initialized with options or not).

        """
        self.transport.connect(*self.remote)
        if self.options:
            self.resultant_options = self.processOptions(self.options)
            bytes = OACKDatagram(self.resultant_options).to_wire()
        else:
            bytes = ACKDatagram(0).to_wire()
        self.timeout_watchdog = timedCaller(chain((0, ), self.timeout),
                                            partial(self.transport.write,
                                                    bytes),
                                            self.timedOut,
                                            clock=self._clock)
Beispiel #27
0
 def test_ACK(self):
     self.rs.block_size = 5
     self.rs.blocknum = 1
     ack_datagram = ACKDatagram(1)
     d = self.rs.datagramReceived(ack_datagram)
     def cb(ign):
         self.clock.advance(0.1)
         self.failIf(self.transport.disconnecting)
         data_datagram = TFTPDatagramFactory(*split_opcode(self.transport.value()))
         self.assertEqual(data_datagram.data, 'line1')
         self.failIf(self.rs.completed,
                     "Got enough bytes from the reader, there is no reason to stop")
     d.addCallback(cb)
     self.clock.advance(2.5)
     self.addCleanup(self.rs.cancel)
     return d
Beispiel #28
0
    def startProtocol(self):
        """Connect the transport, respond with an initial ACK or OACK (depending on
        if we were initialized with options or not).

        """
        self.transport.connect(*self.remote)
        if self.options:
            self.resultant_options = self.processOptions(self.options)
            bytes = OACKDatagram(self.resultant_options).to_wire()
        else:
            bytes = ACKDatagram(0).to_wire()
        self.timeout_watchdog = SequentialCall.run(
            self.timeout[:-1],
            callable=self.transport.write, callable_args=[bytes, ],
            on_timeout=lambda: self._clock.callLater(self.timeout[-1], self.timedOut),
            run_now=True,
            _clock=self._clock
        )
Beispiel #29
0
    def tftp_DATA(self, datagram):
        """Handle incoming DATA TFTP datagram

        @type datagram: L{DATADatagram}

        """
        next_blocknum = self.blocknum + 1
        if datagram.blocknum < next_blocknum:
            self.transport.write(ACKDatagram(datagram.blocknum).to_wire())
        elif datagram.blocknum == next_blocknum:
            if self.completed:
                self.transport.write(ERRORDatagram.from_code(
                    ERR_ILLEGAL_OP, "Transfer already finished").to_wire())
            else:
                return self.nextBlock(datagram)
        else:
            self.transport.write(ERRORDatagram.from_code(
                ERR_ILLEGAL_OP, "Block number mismatch").to_wire())
Beispiel #30
0
    def blockWriteSuccess(self, ign, datagram):
        """The write was successful, respond with ACK for current block number

        If this is the last chunk (received data length < block size), the protocol
        will keep running until the end of current timeout period, so we can respond
        to any duplicates.

        @type datagram: L{DATADatagram}

        """
        bytes = ACKDatagram(datagram.blocknum).to_wire()
        self.timeout_watchdog = timedCaller((0, ) + self.timeout,
                                            partial(self.sendData, bytes),
                                            self.timedOut,
                                            clock=self._clock)
        if len(datagram.data) < self.block_size:
            self.completed = True
            self.writer.finish()
    def test_remote_origin_read_bootstrap(self):
        # First datagram
        self.rs.session.block_size = 5
        self.rs.startProtocol()
        self.clock.pump((1,)*3)

        data_datagram_1 = DATADatagram(1, self.test_data[:5])

        self.assertEqual(self.transport.value(), data_datagram_1.to_wire())
        self.failIf(self.transport.disconnecting)

        # Normal exchange continues
        self.transport.clear()
        self.rs.datagramReceived(ACKDatagram(1).to_wire(), ('127.0.0.1', 65465))
        self.clock.pump((1,)*3)
        data_datagram_2 = DATADatagram(2, self.test_data[5:10])
        self.assertEqual(self.transport.value(), data_datagram_2.to_wire())
        self.failIf(self.transport.disconnecting)
        self.addCleanup(self.rs.cancel)
Beispiel #32
0
    def blockWriteSuccess(self, ign, datagram):
        """The write was successful, respond with ACK for current block number

        If this is the last chunk (received data length < block size), the protocol
        will keep running until the end of current timeout period, so we can respond
        to any duplicates.

        @type datagram: L{DATADatagram}

        """
        bytes = ACKDatagram(datagram.blocknum).to_wire()
        self.timeout_watchdog = SequentialCall.run(self.timeout[:-1],
            callable=self.sendData, callable_args=[bytes, ],
            on_timeout=lambda: self._clock.callLater(self.timeout[-1], self.timedOut),
            run_now=True,
            _clock=self._clock
        )
        if len(datagram.data) < self.block_size:
            self.completed = True
            self.writer.finish()
Beispiel #33
0
    def test_ACK_finished(self):
        self.rs.block_size = 512
        self.rs.blocknum = 1

        # Send a terminating datagram
        ack_datagram = ACKDatagram(1)
        d = self.rs.datagramReceived(ack_datagram)
        def cb(ign):
            self.clock.advance(0.1)
            ack_datagram = ACKDatagram(2)
            # This datagram doesn't trigger any sends
            self.rs.datagramReceived(ack_datagram)

            self.assertEqual(self.transport.value(), DATADatagram(2, self.test_data).to_wire())
            self.failUnless(self.rs.completed,
                        "Data length is less, than blocksize, time to stop")
        self.addCleanup(self.rs.cancel)
        d.addCallback(cb)
        self.clock.advance(3)
        return d
Beispiel #34
0
    def blockWriteSuccess(self, ign, datagram):
        """The write was successful, respond with ACK for current block number

        If this is the last chunk (received data length < block size), the protocol
        will keep running until the end of current timeout period, so we can respond
        to any duplicates.

        @type datagram: L{DATADatagram}

        """
        bytes = ACKDatagram(datagram.blocknum).to_wire()
        if len(datagram.data) < self.block_size:
            self._clock.callLater(0, self.sendData, bytes)
            self.timeout_watchdog = SequentialCall.run(
                self.timeout[:-1],
                callable=lambda: None,
                on_timeout=lambda: self._clock.callLater(
                    self.timeout[-1], self.timedOut),
                run_now=False,
                _clock=self._clock)
            self.completed = True
            self.writer.finish()
            # TODO: If self.tsize is not None, compare it with the actual
            # count of bytes written. Log if there's a mismatch. Should it
            # also emit an error datagram?
        else:
            self.timeout_watchdog = SequentialCall.run(
                self.timeout[:-1],
                callable=self.sendData,
                callable_args=[
                    bytes,
                ],
                on_timeout=lambda: self._clock.callLater(
                    self.timeout[-1], self.timedOut),
                run_now=True,
                _clock=self._clock)