master_loader.cc 4.93 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <dns/master_loader.h>
16
17
18
19
20
#include <dns/master_lexer.h>
#include <dns/name.h>
#include <dns/rrttl.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
21
#include <dns/rdata.h>
22
23

using std::string;
24
25
26
27
28
29
30
31

namespace isc {
namespace dns {

class MasterLoader::MasterLoaderImpl {
public:
    MasterLoaderImpl(const char* master_file,
                     const Name& zone_origin,
32
33
                     const RRClass& zone_class,
                     const MasterLoaderCallbacks& callbacks,
34
                     const AddRRCallback& add_callback,
35
36
37
38
39
                     MasterLoader::Options options) :
        lexer_(),
        zone_origin_(zone_origin),
        zone_class_(zone_class),
        callbacks_(callbacks),
40
        add_callback_(add_callback),
41
42
43
44
45
46
47
48
49
50
51
        options_(options),
        master_file_(master_file),
        initialized_(false),
        ok_(true)
    {}

    void pushSource(const std::string& filename) {
        std::string error;
        if (!lexer_.pushSource(filename.c_str(), &error)) {
            ok_ = false;
            callbacks_.error("", 0, error);
52
        }
53
54
    }

55
56
57
58
59
    // Get a string token. Handle it as error if it is not string.
    const string getString() {
        return (lexer_.getNextToken(MasterToken::QSTRING).getString());
    }

60
    bool loadIncremental(size_t count_limit) {
61
62
        if (!initialized_) {
            pushSource(master_file_);
63
            initialized_ = true;
64
        }
65
        size_t count = 0;
66
        while (ok_ && count < count_limit) {
67
            // Skip all EOLNs (empty lines) and finish on EOF
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
            bool empty = true;
            do {
                const MasterToken& empty_token(lexer_.getNextToken());
                if (empty_token.getType() == MasterToken::END_OF_FILE) {
                    // TODO: Check if this is the last source, possibly pop
                    return (true);
                }
                empty = empty_token.getType() == MasterToken::END_OF_LINE;
            } while (empty);
            // Return the last token, as it was not empty
            lexer_.ungetToken();

            const string name_string(getString());
            // TODO $ handling
            const Name name(name_string); // TODO: Origin
            // TODO: Some more flexibility. We don't allow omitting anything yet

            // The parameters
            const RRTTL ttl(getString());
            const RRClass rrclass(getString());
            const RRType rrtype(getString());

Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
90
91
92
93
94
95
96
97
98
            // TODO: Origin handling
            const rdata::RdataPtr data(rdata::createRdata(rrtype, rrclass,
                                                          lexer_, NULL,
                                                          options_,
                                                          callbacks_));
            // In case we get NULL, it means there was error creating
            // the Rdata. The errors should have been reported by
            // callbacks_ already, so we just need to not report the RR
            if (data != rdata::RdataPtr()) {
99
                add_callback_(name, rrclass, rrtype, ttl, data);
Michal 'vorner' Vaner's avatar
Michal 'vorner' Vaner committed
100
101
102
103

                // Good, we loaded another one
                ++count;
            };
104
        }
105
106
        // When there was a fatal error and ok is false, we say we are done.
        return (!ok_);
107
108
109
110
111
112
113
    }

private:
    MasterLexer lexer_;
    const Name& zone_origin_;
    const RRClass zone_class_;
    MasterLoaderCallbacks callbacks_;
114
    AddRRCallback add_callback_;
115
    MasterLoader::Options options_;
116
117
118
    const std::string master_file_;
    bool initialized_;
    bool ok_;
119
120
121
122
};

MasterLoader::MasterLoader(const char* master_file,
                           const Name& zone_origin,
123
124
                           const RRClass& zone_class,
                           const MasterLoaderCallbacks& callbacks,
125
                           const AddRRCallback& add_callback,
126
127
128
                           Options options)
{
    impl_ = new MasterLoaderImpl(master_file, zone_origin,
129
                                 zone_class, callbacks, add_callback, options);
130
131
132
133
134
135
136
137
138
139
140
141
142
}

MasterLoader::~MasterLoader() {
    delete impl_;
}

bool
MasterLoader::loadIncremental(size_t count_limit) {
    return (impl_->loadIncremental(count_limit));
}

} // end namespace dns
} // end namespace isc