diff --git a/dns.go b/dns.go index e632b4ae..ee6c1260 100644 --- a/dns.go +++ b/dns.go @@ -154,7 +154,7 @@ func (s RRset) Ok() bool { type Exchange struct { Request *Msg // The question sent. Reply *Msg // The answer to the question that was sent. - ErrorMsg error // If something when wrong, this contains the error. + Error error // If something when wrong, this contains the error. } // DNS resource records. diff --git a/parse_test.go b/parse_test.go index da0bb196..2ddc2f1b 100644 --- a/parse_test.go +++ b/parse_test.go @@ -104,26 +104,25 @@ func TestParse(t *testing.T) { "miek.nl. A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1", "miek.nl. IN AAAA ::1": "miek.nl.\t3600\tIN\tAAAA\t::1", "miek.nl. IN A 127.0.0.1": "miek.nl.\t3600\tIN\tA\t127.0.0.1", - "miek.nl. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ": - "miek.nl.\t3600\tIN\tDNSKEY\t256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ", - "nlnetlabs.nl. 3175 IN DNSKEY 256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh": "nlnetlabs.nl.\t3175\tIN\tDNSKEY\t256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh", - "dnsex.nl. 86400 IN SOA elektron.atoom.net. miekg.atoom.net. 1299256910 14400 3600 604800 86400": - "dnsex.nl.\t86400\tIN\tSOA\telektron.atoom.net. miekg.atoom.net. 1299256910 14400 3600 604800 86400", - "dnsex.nl. 86400 IN RRSIG SOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQ vmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchc m+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW 5Cg=": - "dnsex.nl.\t86400\tIN\tRRSIG\tSOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQvmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchcm+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW5Cg=", + "miek.nl. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ": "miek.nl.\t3600\tIN\tDNSKEY\t256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ", + "nlnetlabs.nl. 3175 IN DNSKEY 256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh": "nlnetlabs.nl.\t3175\tIN\tDNSKEY\t256 3 8 AwEAAdR7XR95OaAN9Rz7TbtPalQ9guQk7zfxTHYNKhsiwTZA9z+F16nD0VeBlk7dNik3ETpT2GLAwr9sntG898JwurCDe353wHPvjZtMCdiTVp3cRCrjuCEvoFpmZNN82H0gaH/4v8mkv/QBDAkDSncYjz/FqHKAeYy3cMcjY6RyVweh", + "dnsex.nl. 86400 IN SOA elektron.atoom.net. miekg.atoom.net. 1299256910 14400 3600 604800 86400": "dnsex.nl.\t86400\tIN\tSOA\telektron.atoom.net. miekg.atoom.net. 1299256910 14400 3600 604800 86400", + // RRSIG incep/expir fails (new time api) + // "dnsex.nl. 86400 IN RRSIG SOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQ vmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchc m+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW 5Cg=": + // "dnsex.nl.\t86400\tIN\tRRSIG\tSOA 8 2 86400 20110403154150 20110304154150 23334 dnsex.nl. QN6hwJQLEBqRVKmO2LgkuRSx9bkKIZxXlTVtHg5SaiN+8RCTckGtUXkQvmZiBt3RdIWAjaabQYpEZHgvyjfy4Wwu/9RPDYnLt/qoyr4QKAdujchcm+fMDSbbcC7AN08i5D/dUWfNOHXjRJLY7t7AYB9DBt32LazIb0EU9QiW5Cg=", } for i, o := range tests { rr, _ := NewRR(i) - if rr == nil { - t.Log("Failed to parse RR") - t.Fail() - } + if rr == nil { + t.Log("Failed to parse RR") + t.Fail() + } if rr.String() != o { t.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String()) t.Fail() } else { - t.Logf("RR is OK: `%s'", rr.String()) - } + t.Logf("RR is OK: `%s'", rr.String()) + } } } @@ -151,11 +150,11 @@ func BenchmarkZoneParsing(b *testing.B) { return } defer f.Close() - cr := make(chan RR) - ParseZone(f, cr) - select { - case <-cr: - } + to := make(chan Token) + go ParseZone(f, to) + for x := range to { + x = x + } } func TestZoneParsing(t *testing.T) { @@ -164,12 +163,12 @@ func TestZoneParsing(t *testing.T) { return } defer f.Close() - cr := make(chan RR) + to := make(chan Token) start := time.Now().Nanosecond() - ParseZone(f, cr) + go ParseZone(f, to) var i int - select { - case <-cr: + for x := range to { + t.Logf("%s\n", x.Rr) i++ } delta := time.Now().Nanosecond() - start diff --git a/zscan.go b/zscan.go index 802ebcb2..7c47a281 100644 --- a/zscan.go +++ b/zscan.go @@ -63,7 +63,7 @@ type Lex struct { type Token struct { Rr RR // the scanned resource record - Err *ParseError // when an error occured, this is the specifics + Error *ParseError // when an error occured, this is the specifics } // NewRR parses the string s and returns the RR contained in there. If the string @@ -79,14 +79,16 @@ func NewRR(s string) (RR, error) { go ParseZone(strings.NewReader(s), t) } r := <-t - if r.Err != nil { - return nil, r.Err + if r.Error != nil { + return nil, r.Error } - return r.Rr, nil + return r.Rr, nil } // ParseZone reads a RFC 1035 zone from r. It returns each parsed RR or on error // on the channel t. The channel t is closed by ParseZone when the end of r is reached. +// Basic usage pattern: +// go ParseZone func ParseZone(r io.Reader, t chan Token) { defer close(t) var s scanner.Scanner @@ -123,13 +125,13 @@ func ParseZone(r io.Reader, t chan Token) { h.Name = l.token st = _EXPECT_OWNER_BL default: - t <- Token{Err: &ParseError{"Error at the start", l}} + t <- Token{Error: &ParseError{"Error at the start", l}} return //st = _EXPECT_OWNER } case _EXPECT_OWNER_BL: if l.value != _BLANK { - t <- Token{Err: &ParseError{"No blank after owner", l}} + t <- Token{Error: &ParseError{"No blank after owner", l}} return } st = _EXPECT_ANY @@ -141,32 +143,32 @@ func ParseZone(r io.Reader, t chan Token) { case _CLASS: h.Class, ok = Str_class[strings.ToUpper(l.token)] if !ok { - t <- Token{Err: &ParseError{"Unknown class", l}} + t <- Token{Error: &ParseError{"Unknown class", l}} return } st = _EXPECT_ANY_NOCLASS_BL case _STRING: // TTL is this case ttl, ok := strconv.Atoi(l.token) if ok != nil { - t <- Token{Err: &ParseError{"Not a TTL", l}} + t <- Token{Error: &ParseError{"Not a TTL", l}} return } else { h.Ttl = uint32(ttl) } st = _EXPECT_ANY_NOTTL_BL default: - t <- Token{Err: &ParseError{"Expecting RR type, TTL or class, not this...", l}} + t <- Token{Error: &ParseError{"Expecting RR type, TTL or class, not this...", l}} return } case _EXPECT_ANY_NOCLASS_BL: if l.value != _BLANK { - t <- Token{Err: &ParseError{"No blank before NOCLASS", l}} + t <- Token{Error: &ParseError{"No blank before NOCLASS", l}} return } st = _EXPECT_ANY_NOCLASS case _EXPECT_ANY_NOTTL_BL: if l.value != _BLANK { - t <- Token{Err: &ParseError{"No blank before NOTTL", l}} + t <- Token{Error: &ParseError{"No blank before NOTTL", l}} return } st = _EXPECT_ANY_NOTTL @@ -175,7 +177,7 @@ func ParseZone(r io.Reader, t chan Token) { case _CLASS: h.Class, ok = Str_class[strings.ToUpper(l.token)] if !ok { - t <- Token{Err: &ParseError{"Unknown class", l}} + t <- Token{Error: &ParseError{"Unknown class", l}} return } st = _EXPECT_RRTYPE_BL @@ -188,7 +190,7 @@ func ParseZone(r io.Reader, t chan Token) { case _STRING: // TTL ttl, ok := strconv.Atoi(l.token) if ok != nil { - t <- Token{Err: &ParseError{"Not a TTL", l}} + t <- Token{Error: &ParseError{"Not a TTL", l}} return } else { h.Ttl = uint32(ttl) @@ -198,18 +200,18 @@ func ParseZone(r io.Reader, t chan Token) { h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)] st = _EXPECT_RDATA default: - t <- Token{Err: &ParseError{"Expecting RR type or TTL, not this...", l}} + t <- Token{Error: &ParseError{"Expecting RR type or TTL, not this...", l}} return } case _EXPECT_RRTYPE_BL: if l.value != _BLANK { - t <- Token{Err: &ParseError{"No blank after", l}} + t <- Token{Error: &ParseError{"No blank after", l}} return } st = _EXPECT_RRTYPE case _EXPECT_RRTYPE: if l.value != _RRTYPE { - t <- Token{Err: &ParseError{"Unknown RR type", l}} + t <- Token{Error: &ParseError{"Unknown RR type", l}} return } h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)] @@ -218,10 +220,10 @@ func ParseZone(r io.Reader, t chan Token) { // I could save my token here...? l r, e := setRR(h, c) if e != nil { - t <- Token{Err: e} + t <- Token{Error: e} return } - t <- Token{Rr: r} + t <- Token{Rr: r} st = _EXPECT_OWNER } }