summaryrefslogtreecommitdiffstats
path: root/src/lib/dns/rdata/generic/mx_15.cc
blob: bbe8abcacbda153fd4c5f2710f58dc4c02917b6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <config.h>

#include <string>

#include <boost/lexical_cast.hpp>

#include <exceptions/exceptions.h>

#include <util/buffer.h>
#include <dns/name.h>
#include <dns/messagerenderer.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>

#include <dns/rdata/generic/detail/lexer_util.h>

using namespace std;
using boost::lexical_cast;
using namespace isc::util;
using isc::dns::rdata::generic::detail::createNameFromLexer;

// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE

MX::MX(InputBuffer& buffer, size_t) :
    preference_(buffer.readUint16()), mxname_(buffer)
{
    // we don't need rdata_len for parsing.  if necessary, the caller will
    // check consistency.
}

/// \brief Constructor from string.
///
/// The given string must represent a valid MX RDATA.  There can be extra
/// space characters at the beginning or end of the text (which are simply
/// ignored), but other extra text, including a new line, will make the
/// construction fail with an exception.
///
/// The EXCHANGE name must be absolute since there's no parameter that
/// specifies the origin name; if it is not absolute, \c MissingNameOrigin
/// exception will be thrown. It must not be represented as a quoted
/// string.
///
/// See the construction that takes \c MasterLexer for other fields.
///
/// \throw Others Exception from the Name and RRTTL constructors.
/// \throw InvalidRdataText Other general syntax errors.
MX::MX(const std::string& mx_str) :
    // Fill in dummy name and replace them soon below.
    preference_(0), mxname_(Name::ROOT_NAME())
{
    try {
        std::istringstream ss(mx_str);
        MasterLexer lexer;
        lexer.pushSource(ss);

        constructFromLexer(lexer, NULL);

        if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
            isc_throw(InvalidRdataText, "extra input text for MX: "
                      << mx_str);
        }
    } catch (const MasterLexer::LexerError& ex) {
        isc_throw(InvalidRdataText, "Failed to construct MX from '" <<
                  mx_str << "': " << ex.what());
    }
}

/// \brief Constructor with a context of MasterLexer.
///
/// The \c lexer should point to the beginning of valid textual representation
/// of an MX RDATA.  The EXCHANGE field can be non-absolute if \c origin
/// is non-NULL, in which case \c origin is used to make it absolute.
/// It must not be represented as a quoted string.
///
/// The PREFERENCE field must be a valid decimal representation of an
/// unsigned 16-bit integer.
///
/// \throw MasterLexer::LexerError General parsing error such as missing field.
/// \throw Other Exceptions from the Name and RRTTL constructors if
/// construction of textual fields as these objects fail.
///
/// \param lexer A \c MasterLexer object parsing a master file for the
/// RDATA to be created
/// \param origin If non NULL, specifies the origin of EXCHANGE when it
/// is non-absolute.
MX::MX(MasterLexer& lexer, const Name* origin,
       MasterLoader::Options, MasterLoaderCallbacks&) :
    preference_(0), mxname_(Name::ROOT_NAME())
{
    constructFromLexer(lexer, origin);
}

void
MX::constructFromLexer(MasterLexer& lexer, const Name* origin) {
    const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber();
    if (num > 65535) {
        isc_throw(InvalidRdataText, "Invalid MX preference: " << num);
    }
    preference_ = static_cast<uint16_t>(num);

    mxname_ = createNameFromLexer(lexer, origin);
}

MX::MX(uint16_t preference, const Name& mxname) :
    preference_(preference), mxname_(mxname)
{}

MX::MX(const MX& other) :
    Rdata(), preference_(other.preference_), mxname_(other.mxname_)
{}

void
MX::toWire(OutputBuffer& buffer) const {
    buffer.writeUint16(preference_);
    mxname_.toWire(buffer);
}

void
MX::toWire(AbstractMessageRenderer& renderer) const {
    renderer.writeUint16(preference_);
    renderer.writeName(mxname_);
}

string
MX::toText() const {
    return (lexical_cast<string>(preference_) + " " + mxname_.toText());
}

int
MX::compare(const Rdata& other) const {
    const MX& other_mx = dynamic_cast<const MX&>(other);

    if (preference_ < other_mx.preference_) {
        return (-1);
    } else if (preference_ > other_mx.preference_) {
        return (1);
    }

    return (compareNames(mxname_, other_mx.mxname_));
}

const Name&
MX::getMXName() const {
    return (mxname_);
}

uint16_t
MX::getMXPref() const {
    return (preference_);
}

// END_RDATA_NAMESPACE
// END_ISC_NAMESPACE