From: JINMEI Tatuya Date: Mon, 3 Oct 2011 06:52:55 +0000 (-0700) Subject: [1261] implemented IXFRAdd, IXFREnd and AXFR (currently just raise an X-Git-Tag: perftcpdns_before_epoll~37^2~21^2~13^2~37 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=48bec4c73b92679e91f0cc72fc63bdba9c593e87;p=thirdparty%2Fkea.git [1261] implemented IXFRAdd, IXFREnd and AXFR (currently just raise an exception) classes. --- diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py index 6daf6b833f..2b6552e8c5 100644 --- a/src/bin/xfrin/tests/xfrin_test.py +++ b/src/bin/xfrin/tests/xfrin_test.py @@ -256,7 +256,7 @@ class TestXfrinFirstData(TestXfrinState): self.assertFalse(self.state.handle_rr(self.conn, soa_rrset)) self.assertEqual(type(XfrinAXFR()), type(self.conn.get_xfrstate())) -class TestXfrinIAXFDeleteSOA(TestXfrinState): +class TestXfrinIXFRDeleteSOA(TestXfrinState): def setUp(self): super().setUp() self.state = XfrinIXFRDeleteSOA() @@ -272,9 +272,11 @@ class TestXfrinIAXFDeleteSOA(TestXfrinState): self.assertRaises(XfrinException, self.state.handle_rr, self.conn, self.ns_rrset) -class TestXfrinIAXFDelete(TestXfrinState): +class TestXfrinIXFRDelete(TestXfrinState): def setUp(self): super().setUp() + # We need record the state in 'conn' to check the case where the + # state doesn't change. XfrinIXFRDelete().set_xfrstate(self.conn, XfrinIXFRDelete()) self.state = self.conn.get_xfrstate() @@ -294,9 +296,83 @@ class TestXfrinIAXFDelete(TestXfrinState): self.assertFalse(self.state.handle_rr(self.conn, soa_rrset)) self.assertEqual([], self.conn._diff.get_buffer()) self.assertEqual(1234, self.conn._current_serial) - self.assertEqual(type(XfrinAddSOA()), + self.assertEqual(type(XfrinIXFRAddSOA()), type(self.conn.get_xfrstate())) +class TestXfrinIXFRAddSOA(TestXfrinState): + def setUp(self): + super().setUp() + self.state = XfrinIXFRAddSOA() + + def test_handle_rr(self): + self.assertTrue(self.state.handle_rr(self.conn, soa_rrset)) + self.assertEqual(type(XfrinIXFRAdd()), type(self.conn.get_xfrstate())) + self.assertEqual([('add', soa_rrset)], + self.conn._diff.get_buffer()) + + def test_handle_non_soa(self): + self.assertRaises(XfrinException, self.state.handle_rr, self.conn, + self.ns_rrset) + +class TestXfrinIXFRAdd(TestXfrinState): + def setUp(self): + super().setUp() + # We need record the state in 'conn' to check the case where the + # state doesn't change. + XfrinIXFRAdd().set_xfrstate(self.conn, XfrinIXFRAdd()) + self.conn._current_serial = 1230 + self.state = self.conn.get_xfrstate() + + def test_handle_add_rr(self): + # Non SOA RRs are simply (goting to be) added in this state + self.assertTrue(self.state.handle_rr(self.conn, self.ns_rrset)) + self.assertEqual([('add', self.ns_rrset)], + self.conn._diff.get_buffer()) + # The state shouldn't change + self.assertEqual(type(XfrinIXFRAdd()), type(self.conn.get_xfrstate())) + + def test_handle_end_soa(self): + self.conn._end_serial = 1234 + self.conn._diff.add_data(self.ns_rrset) # put some dummy change + self.assertTrue(self.state.handle_rr(self.conn, soa_rrset)) + self.assertEqual(type(XfrinIXFREnd()), type(self.conn.get_xfrstate())) + # handle_rr should have caused commit, and the buffer should now be + # empty. + self.assertEqual([], self.conn._diff.get_buffer()) + + def test_handle_new_delete(self): + # SOA RR whose serial is the current one means we are going to a new + # difference, starting with removing that SOA. + self.conn._diff.add_data(self.ns_rrset) # put some dummy change + self.assertFalse(self.state.handle_rr(self.conn, self.begin_soa)) + self.assertEqual([], self.conn._diff.get_buffer()) + self.assertEqual(type(XfrinIXFRDeleteSOA()), + type(self.conn.get_xfrstate())) + + def test_handle_out_of_sync(self): + # getting SOA with an inconsistent serial. This is an error. + self.conn._end_serial = 1235 + self.assertRaises(XfrinProtocolError, self.state.handle_rr, + self.conn, soa_rrset) + +class TestXfrinIXFREnd(TestXfrinState): + def setUp(self): + super().setUp() + self.state = XfrinIXFREnd() + + def test_handle_rr(self): + self.assertRaises(XfrinProtocolError, self.state.handle_rr, self.conn, + self.ns_rrset) + +class TestXfrinAXFR(TestXfrinState): + def setUp(self): + super().setUp() + self.state = XfrinAXFR() + + def test_handle_rr(self): + self.assertRaises(XfrinException, self.state.handle_rr, self.conn, + soa_rrset) + class TestXfrinConnection(unittest.TestCase): def setUp(self): if os.path.exists(TEST_DB_FILE): diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in index 82310d0c33..2fc90d8e2d 100755 --- a/src/bin/xfrin/xfrin.py.in +++ b/src/bin/xfrin/xfrin.py.in @@ -192,16 +192,51 @@ class XfrinIXFRDelete(XfrinState): def handle_rr(self, conn, rr): if rr.get_type() == RRType.SOA(): conn._current_serial = get_soa_serial(rr.get_rdata()[0]) - self.set_xfrstate(conn, XfrinAddSOA()) + self.set_xfrstate(conn, XfrinIXFRAddSOA()) return False conn._diff.remove_data(rr) return True -class XfrinAddSOA(XfrinState): - pass +class XfrinIXFRAddSOA(XfrinState): + def handle_rr(self, conn, rr): + if rr.get_type() != RRType.SOA(): + # this shouldn't happen; should this occur it means an internal + # + raise XfrinException(rr.get_type().to_text() + \ + ' RR is given in IXFRAddSOA state') + conn._diff.add_data(rr) + self.set_xfrstate(conn, XfrinIXFRAdd()) + return True + +class XfrinIXFRAdd(XfrinState): + def handle_rr(self, conn, rr): + if rr.get_type() == RRType.SOA(): + soa_serial = get_soa_serial(rr.get_rdata()[0]) + if soa_serial == conn._end_serial: + conn._diff.commit() + self.set_xfrstate(conn, XfrinIXFREnd()) + return True + elif soa_serial != conn._current_serial: + raise XfrinProtocolError('IXFR out of sync: expected ' + \ + 'serial ' + \ + str(conn._current_serial) + \ + ', got ' + str(soa_serial)) + else: + conn._diff.commit() + self.set_xfrstate(conn, XfrinIXFRDeleteSOA()) + return False + conn._diff.add_data(rr) + return True + +class XfrinIXFREnd(XfrinState): + def handle_rr(self, conn, rr): + raise XfrinProtocolError('Extra data after the end of IXFR diffs: ' + \ + rr.to_text()) class XfrinAXFR(XfrinState): - pass + def handle_rr(self, conn, rr): + raise XfrinException('Falling back from IXFR to AXFR not ' + \ + 'supported yet') class XfrinConnection(asyncore.dispatcher): '''Do xfrin in this class. '''