Branch data Line data Source code
1 : : // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #include <Python.h>
16 : :
17 : : #include <util/buffer.h>
18 : :
19 : : #include <dns/messagerenderer.h>
20 : : #include <util/python/pycppwrapper_util.h>
21 : :
22 : : #include "pydnspp_common.h"
23 : : #include "messagerenderer_python.h"
24 : :
25 : : using namespace isc::dns;
26 : : using namespace isc::dns::python;
27 : : using namespace isc::util;
28 : : using namespace isc::util::python;
29 : :
30 : : namespace {
31 : : // The s_* Class simply covers one instantiation of the object.
32 : : //
33 : : // since we don't use *Buffer in the python version (but work with
34 : : // the already existing bytearray type where we use these custom buffers
35 : : // in C++, we need to keep track of one here.
36 : : class s_MessageRenderer : public PyObject {
37 : : public:
38 : : s_MessageRenderer();
39 : : MessageRenderer* cppobj;
40 : : };
41 : :
42 : : int MessageRenderer_init(s_MessageRenderer* self);
43 : : void MessageRenderer_destroy(s_MessageRenderer* self);
44 : :
45 : : PyObject* MessageRenderer_getData(s_MessageRenderer* self);
46 : : PyObject* MessageRenderer_getLength(s_MessageRenderer* self);
47 : : PyObject* MessageRenderer_isTruncated(s_MessageRenderer* self);
48 : : PyObject* MessageRenderer_getLengthLimit(s_MessageRenderer* self);
49 : : PyObject* MessageRenderer_getCompressMode(s_MessageRenderer* self);
50 : : PyObject* MessageRenderer_setTruncated(s_MessageRenderer* self);
51 : : PyObject* MessageRenderer_setLengthLimit(s_MessageRenderer* self, PyObject* args);
52 : : PyObject* MessageRenderer_setCompressMode(s_MessageRenderer* self, PyObject* args);
53 : : PyObject* MessageRenderer_clear(s_MessageRenderer* self);
54 : :
55 : : PyMethodDef MessageRenderer_methods[] = {
56 : : { "get_data", reinterpret_cast<PyCFunction>(MessageRenderer_getData), METH_NOARGS,
57 : : "Returns the data as a bytes() object" },
58 : : { "get_length", reinterpret_cast<PyCFunction>(MessageRenderer_getLength), METH_NOARGS,
59 : : "Returns the length of the data" },
60 : : { "is_truncated", reinterpret_cast<PyCFunction>(MessageRenderer_isTruncated), METH_NOARGS,
61 : : "Returns True if the data is truncated" },
62 : : { "get_length_limit", reinterpret_cast<PyCFunction>(MessageRenderer_getLengthLimit), METH_NOARGS,
63 : : "Returns the length limit of the data" },
64 : : { "get_compress_mode", reinterpret_cast<PyCFunction>(MessageRenderer_getCompressMode), METH_NOARGS,
65 : : "Returns the current compression mode" },
66 : : { "set_truncated", reinterpret_cast<PyCFunction>(MessageRenderer_setTruncated), METH_NOARGS,
67 : : "Sets truncated to true" },
68 : : { "set_length_limit", reinterpret_cast<PyCFunction>(MessageRenderer_setLengthLimit), METH_VARARGS,
69 : : "Sets the length limit of the data to the given number" },
70 : : { "set_compress_mode", reinterpret_cast<PyCFunction>(MessageRenderer_setCompressMode), METH_VARARGS,
71 : : "Sets the compression mode of the MessageRenderer" },
72 : : { "clear", reinterpret_cast<PyCFunction>(MessageRenderer_clear),
73 : : METH_NOARGS,
74 : : "Clear the internal buffer and other internal resources." },
75 : : { NULL, NULL, 0, NULL }
76 : : };
77 : :
78 : : int
79 : 459 : MessageRenderer_init(s_MessageRenderer* self) {
80 [ + - ]: 459 : self->cppobj = new MessageRenderer;
81 : 459 : return (0);
82 : : }
83 : :
84 : : void
85 : 459 : MessageRenderer_destroy(s_MessageRenderer* self) {
86 [ + - ]: 459 : delete self->cppobj;
87 : 459 : self->cppobj = NULL;
88 : 459 : Py_TYPE(self)->tp_free(self);
89 : 459 : }
90 : :
91 : : PyObject*
92 : 430 : MessageRenderer_getData(s_MessageRenderer* self) {
93 : : return (Py_BuildValue("y#",
94 : : self->cppobj->getData(),
95 : 430 : self->cppobj->getLength()));
96 : : }
97 : :
98 : : PyObject*
99 : 316 : MessageRenderer_getLength(s_MessageRenderer* self) {
100 : 316 : return (Py_BuildValue("I", self->cppobj->getLength()));
101 : : }
102 : :
103 : : PyObject*
104 : 7 : MessageRenderer_isTruncated(s_MessageRenderer* self) {
105 [ + + ]: 7 : if (self->cppobj->isTruncated()) {
106 : 3 : Py_RETURN_TRUE;
107 : : } else {
108 : 7 : Py_RETURN_FALSE;
109 : : }
110 : : }
111 : :
112 : : PyObject*
113 : 6 : MessageRenderer_getLengthLimit(s_MessageRenderer* self) {
114 : 6 : return (Py_BuildValue("I", self->cppobj->getLengthLimit()));
115 : : }
116 : :
117 : : PyObject*
118 : 6 : MessageRenderer_getCompressMode(s_MessageRenderer* self) {
119 : 6 : return (Py_BuildValue("I", self->cppobj->getCompressMode()));
120 : : }
121 : :
122 : : PyObject*
123 : 1 : MessageRenderer_setTruncated(s_MessageRenderer* self) {
124 : 1 : self->cppobj->setTruncated();
125 : 1 : Py_RETURN_NONE;
126 : : }
127 : :
128 : : PyObject*
129 : 159 : MessageRenderer_setLengthLimit(s_MessageRenderer* self,
130 : : PyObject* args)
131 : : {
132 : : long lengthlimit;
133 [ + + ]: 159 : if (!PyArg_ParseTuple(args, "l", &lengthlimit)) {
134 : 1 : PyErr_Clear();
135 : : PyErr_SetString(PyExc_TypeError,
136 : 1 : "No valid type in set_length_limit argument");
137 : 1 : return (NULL);
138 : : }
139 [ + + ]: 158 : if (lengthlimit < 0) {
140 : : PyErr_SetString(PyExc_ValueError,
141 : 1 : "MessageRenderer length limit out of range");
142 : 1 : return (NULL);
143 : : }
144 : 157 : self->cppobj->setLengthLimit(lengthlimit);
145 : 159 : Py_RETURN_NONE;
146 : : }
147 : :
148 : : PyObject*
149 : 140 : MessageRenderer_setCompressMode(s_MessageRenderer* self,
150 : : PyObject* args)
151 : : {
152 : : int mode;
153 [ + + ]: 140 : if (!PyArg_ParseTuple(args, "i", &mode)) {
154 : : return (NULL);
155 : : }
156 : :
157 [ + + ]: 139 : if (mode == MessageRenderer::CASE_INSENSITIVE) {
158 : 1 : self->cppobj->setCompressMode(MessageRenderer::CASE_INSENSITIVE);
159 : : // If we return NULL it is seen as an error, so use this for
160 : : // None returns, it also applies to CASE_SENSITIVE.
161 : 1 : Py_RETURN_NONE;
162 [ + - ]: 138 : } else if (mode == MessageRenderer::CASE_SENSITIVE) {
163 : 138 : self->cppobj->setCompressMode(MessageRenderer::CASE_SENSITIVE);
164 : 138 : Py_RETURN_NONE;
165 : : } else {
166 : : PyErr_SetString(PyExc_TypeError,
167 : : "MessageRenderer compress mode must be MessageRenderer.CASE_INSENSITIVE"
168 : 0 : "or MessageRenderer.CASE_SENSITIVE");
169 : 140 : return (NULL);
170 : : }
171 : : }
172 : :
173 : : PyObject*
174 : 30 : MessageRenderer_clear(s_MessageRenderer* self) {
175 : 30 : self->cppobj->clear();
176 : 30 : Py_RETURN_NONE;
177 : : }
178 : : } // end of unnamed namespace
179 : :
180 : : namespace isc {
181 : : namespace dns {
182 : : namespace python {
183 : : PyTypeObject messagerenderer_type = {
184 : : PyVarObject_HEAD_INIT(NULL, 0)
185 : : "pydnspp.MessageRenderer",
186 : : sizeof(s_MessageRenderer), // tp_basicsize
187 : : 0, // tp_itemsize
188 : : (destructor)MessageRenderer_destroy,// tp_dealloc
189 : : NULL, // tp_print
190 : : NULL, // tp_getattr
191 : : NULL, // tp_setattr
192 : : NULL, // tp_reserved
193 : : NULL, // tp_repr
194 : : NULL, // tp_as_number
195 : : NULL, // tp_as_sequence
196 : : NULL, // tp_as_mapping
197 : : NULL, // tp_hash
198 : : NULL, // tp_call
199 : : NULL, // tp_str
200 : : NULL, // tp_getattro
201 : : NULL, // tp_setattro
202 : : NULL, // tp_as_buffer
203 : : Py_TPFLAGS_DEFAULT, // tp_flags
204 : : "The MessageRenderer class encapsulates implementation details "
205 : : "of rendering a DNS message into a buffer in wire format. "
206 : : "In effect, it's simply responsible for name compression at least in the "
207 : : "current implementation. A MessageRenderer class object manages the "
208 : : "positions of names rendered in a buffer and uses that information to render "
209 : : "subsequent names with compression.",
210 : : NULL, // tp_traverse
211 : : NULL, // tp_clear
212 : : NULL, // tp_richcompare
213 : : 0, // tp_weaklistoffset
214 : : NULL, // tp_iter
215 : : NULL, // tp_iternext
216 : : MessageRenderer_methods, // tp_methods
217 : : NULL, // tp_members
218 : : NULL, // tp_getset
219 : : NULL, // tp_base
220 : : NULL, // tp_dict
221 : : NULL, // tp_descr_get
222 : : NULL, // tp_descr_set
223 : : 0, // tp_dictoffset
224 : : (initproc)MessageRenderer_init, // tp_init
225 : : NULL, // tp_alloc
226 : : PyType_GenericNew, // tp_new
227 : : NULL, // tp_free
228 : : NULL, // tp_is_gc
229 : : NULL, // tp_bases
230 : : NULL, // tp_mro
231 : : NULL, // tp_cache
232 : : NULL, // tp_subclasses
233 : : NULL, // tp_weaklist
234 : : NULL, // tp_del
235 : : 0 // tp_version_tag
236 : : };
237 : :
238 : : // If we need a createMessageRendererObject(), should we copy? can we?
239 : : // copy the existing buffer into a new one, then create a new renderer with
240 : : // that buffer?
241 : :
242 : : bool
243 : 0 : PyMessageRenderer_Check(PyObject* obj) {
244 [ # # ]: 0 : if (obj == NULL) {
245 [ # # ]: 0 : isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
246 : : }
247 [ # # ][ # # ]: 0 : return (PyObject_TypeCheck(obj, &messagerenderer_type));
248 : : }
249 : :
250 : : MessageRenderer&
251 : 465 : PyMessageRenderer_ToMessageRenderer(PyObject* messagerenderer_obj) {
252 [ - + ]: 465 : if (messagerenderer_obj == NULL) {
253 [ # # ]: 0 : isc_throw(PyCPPWrapperException,
254 : : "obj argument NULL in MessageRenderer PyObject conversion");
255 : : }
256 : 465 : s_MessageRenderer* messagerenderer = static_cast<s_MessageRenderer*>(messagerenderer_obj);
257 : 465 : return (*messagerenderer->cppobj);
258 : : }
259 : :
260 : :
261 : : } // namespace python
262 : : } // namespace dns
263 : 1176 : } // namespace isc
|