public void DnsSerialization_NameCompression() { DnsMessage message = new DnsMessage(); Dictionary <string, int> namePtrs = new Dictionary <string, int>(); int offset; byte[] packet; string name; message.SetNamePtrs(namePtrs); // Verify that labels greater than 63 characters throw // an exception. try { namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, new String('a', 64) + ".com."); Assert.Fail("Exception expected"); } catch { } // Verify that zero length internal labels throw // an exception. try { namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, "test..com."); Assert.Fail("Exception expected"); } catch { } // Verify that relative domain names throw an exception. try { namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, "test.com"); Assert.Fail("Exception expected"); } catch { } // Verify writing the root domain by itself. namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, "."); Assert.AreEqual(1, offset); Assert.AreEqual(0, packet[0]); Assert.AreEqual(0, namePtrs.Count); // Verify writing a domain with a single label. namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, "a."); Assert.AreEqual(3, offset); Assert.AreEqual(1, packet[0]); Assert.AreEqual('a', (char)packet[1]); Assert.AreEqual(0, packet[2]); Assert.AreEqual(1, namePtrs.Count); Assert.AreEqual(0, namePtrs["a"]); // Verify writing a domain with a three labels. namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, "a.b.c."); Assert.AreEqual(7, offset); Assert.AreEqual(1, packet[0]); Assert.AreEqual('a', (char)packet[1]); Assert.AreEqual(1, packet[2]); Assert.AreEqual('b', (char)packet[3]); Assert.AreEqual(1, packet[4]); Assert.AreEqual('c', (char)packet[5]); Assert.AreEqual(0, packet[6]); Assert.AreEqual(3, namePtrs.Count); Assert.AreEqual(0, namePtrs["a.b.c"]); Assert.AreEqual(2, namePtrs["b.c"]); Assert.AreEqual(4, namePtrs["c"]); // Write the entire three label domain and verify // that only a pointer is written. namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, "a.b.c."); message.WriteName(packet, ref offset, "a.b.c."); Assert.AreEqual(9, offset); Assert.AreEqual(0xC0, packet[7]); Assert.AreEqual(0, packet[8]); // Verify that after writing "a.b.c." and then // writing "z.b.c." that a pointer is written // for the "b.c." portion. namePtrs.Clear(); packet = new byte[512]; offset = 0; message.WriteName(packet, ref offset, "a.b.c."); message.WriteName(packet, ref offset, "z.b.c."); Assert.AreEqual(11, offset); Assert.AreEqual(1, packet[7]); Assert.AreEqual('z', (char)packet[8]); Assert.AreEqual(0xC0, packet[9]); Assert.AreEqual(2, packet[10]); // Verify that we can read the two domains just written. offset = 0; message.ReadName(packet, ref offset, out name); Assert.AreEqual("a.b.c.", name); message.ReadName(packet, ref offset, out name); Assert.AreEqual("z.b.c.", name); }