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 <dns/opcode.h>
18 : : #include <util/python/pycppwrapper_util.h>
19 : :
20 : : #include "pydnspp_common.h"
21 : : #include "opcode_python.h"
22 : : #include "edns_python.h"
23 : :
24 : : using namespace isc::dns;
25 : : using namespace isc::dns::python;
26 : : using namespace isc::util;
27 : : using namespace isc::util::python;
28 : :
29 : : namespace {
30 : :
31 : : class s_Opcode : public PyObject {
32 : : public:
33 : : s_Opcode() : cppobj(NULL), static_code(false) {}
34 : : const isc::dns::Opcode* cppobj;
35 : : bool static_code;
36 : : };
37 : :
38 : : typedef CPPPyObjectContainer<s_Opcode, Opcode> OpcodeContainer;
39 : :
40 : : int Opcode_init(s_Opcode* const self, PyObject* args);
41 : : void Opcode_destroy(s_Opcode* const self);
42 : :
43 : : PyObject* Opcode_getCode(const s_Opcode* const self);
44 : : PyObject* Opcode_toText(const s_Opcode* const self);
45 : : PyObject* Opcode_str(PyObject* self);
46 : : PyObject* Opcode_QUERY(const s_Opcode* self);
47 : : PyObject* Opcode_IQUERY(const s_Opcode* self);
48 : : PyObject* Opcode_STATUS(const s_Opcode* self);
49 : : PyObject* Opcode_RESERVED3(const s_Opcode* self);
50 : : PyObject* Opcode_NOTIFY(const s_Opcode* self);
51 : : PyObject* Opcode_UPDATE(const s_Opcode* self);
52 : : PyObject* Opcode_RESERVED6(const s_Opcode* self);
53 : : PyObject* Opcode_RESERVED7(const s_Opcode* self);
54 : : PyObject* Opcode_RESERVED8(const s_Opcode* self);
55 : : PyObject* Opcode_RESERVED9(const s_Opcode* self);
56 : : PyObject* Opcode_RESERVED10(const s_Opcode* self);
57 : : PyObject* Opcode_RESERVED11(const s_Opcode* self);
58 : : PyObject* Opcode_RESERVED12(const s_Opcode* self);
59 : : PyObject* Opcode_RESERVED13(const s_Opcode* self);
60 : : PyObject* Opcode_RESERVED14(const s_Opcode* self);
61 : : PyObject* Opcode_RESERVED15(const s_Opcode* self);
62 : : PyObject* Opcode_richcmp(const s_Opcode* const self,
63 : : const s_Opcode* const other, int op);
64 : :
65 : : PyMethodDef Opcode_methods[] = {
66 : : { "get_code", reinterpret_cast<PyCFunction>(Opcode_getCode), METH_NOARGS,
67 : : "Returns the code value" },
68 : : { "to_text", reinterpret_cast<PyCFunction>(Opcode_toText), METH_NOARGS,
69 : : "Returns the text representation" },
70 : : { "QUERY", reinterpret_cast<PyCFunction>(Opcode_QUERY),
71 : : METH_NOARGS | METH_STATIC, "Creates a QUERY Opcode" },
72 : : { "IQUERY", reinterpret_cast<PyCFunction>(Opcode_IQUERY),
73 : : METH_NOARGS | METH_STATIC, "Creates a IQUERY Opcode" },
74 : : { "STATUS", reinterpret_cast<PyCFunction>(Opcode_STATUS),
75 : : METH_NOARGS | METH_STATIC, "Creates a STATUS Opcode" },
76 : : { "RESERVED3", reinterpret_cast<PyCFunction>(Opcode_RESERVED3),
77 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED3 Opcode" },
78 : : { "NOTIFY", reinterpret_cast<PyCFunction>(Opcode_NOTIFY),
79 : : METH_NOARGS | METH_STATIC, "Creates a NOTIFY Opcode" },
80 : : { "UPDATE", reinterpret_cast<PyCFunction>(Opcode_UPDATE),
81 : : METH_NOARGS | METH_STATIC, "Creates a UPDATE Opcode" },
82 : : { "RESERVED6", reinterpret_cast<PyCFunction>(Opcode_RESERVED6),
83 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED6 Opcode" },
84 : : { "RESERVED7", reinterpret_cast<PyCFunction>(Opcode_RESERVED7),
85 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED7 Opcode" },
86 : : { "RESERVED8", reinterpret_cast<PyCFunction>(Opcode_RESERVED8),
87 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED8 Opcode" },
88 : : { "RESERVED9", reinterpret_cast<PyCFunction>(Opcode_RESERVED9),
89 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED9 Opcode" },
90 : : { "RESERVED10", reinterpret_cast<PyCFunction>(Opcode_RESERVED10),
91 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED10 Opcode" },
92 : : { "RESERVED11", reinterpret_cast<PyCFunction>(Opcode_RESERVED11),
93 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED11 Opcode" },
94 : : { "RESERVED12", reinterpret_cast<PyCFunction>(Opcode_RESERVED12),
95 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED12 Opcode" },
96 : : { "RESERVED13", reinterpret_cast<PyCFunction>(Opcode_RESERVED13),
97 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED13 Opcode" },
98 : : { "RESERVED14", reinterpret_cast<PyCFunction>(Opcode_RESERVED14),
99 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED14 Opcode" },
100 : : { "RESERVED15", reinterpret_cast<PyCFunction>(Opcode_RESERVED15),
101 : : METH_NOARGS | METH_STATIC, "Creates a RESERVED15 Opcode" },
102 : : { NULL, NULL, 0, NULL }
103 : : };
104 : :
105 : :
106 : : int
107 : 7 : Opcode_init(s_Opcode* const self, PyObject* args) {
108 : 7 : uint8_t code = 0;
109 [ + + ]: 7 : if (PyArg_ParseTuple(args, "b", &code)) {
110 : : try {
111 [ + - ][ + + ]: 6 : self->cppobj = new Opcode(code);
112 : 5 : self->static_code = false;
113 : 2 : } catch (const isc::OutOfRange& ex) {
114 [ - + ]: 1 : PyErr_SetString(PyExc_OverflowError, ex.what());
115 : : return (-1);
116 [ + - ]: 1 : } catch (...) {
117 [ # # ]: 0 : PyErr_SetString(po_IscException, "Unexpected exception");
118 : : return (-1);
119 : : }
120 : 5 : return (0);
121 : : }
122 : :
123 : 1 : PyErr_Clear();
124 : 1 : PyErr_SetString(PyExc_TypeError, "Invalid arguments to Opcode constructor");
125 : :
126 : 7 : return (-1);
127 : : }
128 : :
129 : : void
130 : 484 : Opcode_destroy(s_Opcode* const self) {
131 : : // Depending on whether we created the rcode or are referring
132 : : // to a global static one, we do or do not delete self->cppobj here
133 [ + + ]: 484 : if (!self->static_code) {
134 : 13 : delete self->cppobj;
135 : : }
136 : 484 : self->cppobj = NULL;
137 : 484 : Py_TYPE(self)->tp_free(self);
138 : 484 : }
139 : :
140 : : PyObject*
141 : 26 : Opcode_getCode(const s_Opcode* const self) {
142 : 26 : return (Py_BuildValue("I", self->cppobj->getCode()));
143 : : }
144 : :
145 : : PyObject*
146 : 18 : Opcode_toText(const s_Opcode* const self) {
147 [ + - ]: 18 : return (Py_BuildValue("s", self->cppobj->toText().c_str()));
148 : : }
149 : :
150 : : PyObject*
151 : 1 : Opcode_str(PyObject* self) {
152 : : // Simply call the to_text method we already defined
153 : : return (PyObject_CallMethod(self,
154 : : const_cast<char*>("to_text"),
155 : 1 : const_cast<char*>("")));
156 : : }
157 : :
158 : : PyObject*
159 : 356 : Opcode_createStatic(const Opcode& opcode) {
160 : 356 : s_Opcode* ret = PyObject_New(s_Opcode, &opcode_type);
161 [ + - ]: 356 : if (ret != NULL) {
162 : 356 : ret->cppobj = &opcode;
163 : 356 : ret->static_code = true;
164 : : }
165 : 356 : return (ret);
166 : : }
167 : :
168 : : PyObject*
169 : 312 : Opcode_QUERY(const s_Opcode*) {
170 : 312 : return (Opcode_createStatic(Opcode::QUERY()));
171 : : }
172 : :
173 : : PyObject*
174 : 4 : Opcode_IQUERY(const s_Opcode*) {
175 : 4 : return (Opcode_createStatic(Opcode::IQUERY()));
176 : : }
177 : :
178 : : PyObject*
179 : 2 : Opcode_STATUS(const s_Opcode*) {
180 : 2 : return (Opcode_createStatic(Opcode::STATUS()));
181 : : }
182 : :
183 : : PyObject*
184 : 2 : Opcode_RESERVED3(const s_Opcode*) {
185 : 2 : return (Opcode_createStatic(Opcode::RESERVED3()));
186 : : }
187 : :
188 : : PyObject*
189 : 12 : Opcode_NOTIFY(const s_Opcode*) {
190 : 12 : return (Opcode_createStatic(Opcode::NOTIFY()));
191 : : }
192 : :
193 : : PyObject*
194 : 3 : Opcode_UPDATE(const s_Opcode*) {
195 : 3 : return (Opcode_createStatic(Opcode::UPDATE()));
196 : : }
197 : :
198 : : PyObject*
199 : 2 : Opcode_RESERVED6(const s_Opcode*) {
200 : 2 : return (Opcode_createStatic(Opcode::RESERVED6()));
201 : : }
202 : :
203 : : PyObject*
204 : 2 : Opcode_RESERVED7(const s_Opcode*) {
205 : 2 : return (Opcode_createStatic(Opcode::RESERVED7()));
206 : : }
207 : :
208 : : PyObject*
209 : 2 : Opcode_RESERVED8(const s_Opcode*) {
210 : 2 : return (Opcode_createStatic(Opcode::RESERVED8()));
211 : : }
212 : :
213 : : PyObject*
214 : 2 : Opcode_RESERVED9(const s_Opcode*) {
215 : 2 : return (Opcode_createStatic(Opcode::RESERVED9()));
216 : : }
217 : :
218 : : PyObject*
219 : 2 : Opcode_RESERVED10(const s_Opcode*) {
220 : 2 : return (Opcode_createStatic(Opcode::RESERVED10()));
221 : : }
222 : :
223 : : PyObject*
224 : 2 : Opcode_RESERVED11(const s_Opcode*) {
225 : 2 : return (Opcode_createStatic(Opcode::RESERVED11()));
226 : : }
227 : :
228 : : PyObject*
229 : 2 : Opcode_RESERVED12(const s_Opcode*) {
230 : 2 : return (Opcode_createStatic(Opcode::RESERVED12()));
231 : : }
232 : :
233 : : PyObject*
234 : 2 : Opcode_RESERVED13(const s_Opcode*) {
235 : 2 : return (Opcode_createStatic(Opcode::RESERVED13()));
236 : : }
237 : :
238 : : PyObject*
239 : 2 : Opcode_RESERVED14(const s_Opcode*) {
240 : 2 : return (Opcode_createStatic(Opcode::RESERVED14()));
241 : : }
242 : :
243 : : PyObject*
244 : 3 : Opcode_RESERVED15(const s_Opcode*) {
245 : 3 : return (Opcode_createStatic(Opcode::RESERVED15()));
246 : : }
247 : :
248 : : PyObject*
249 : 17 : Opcode_richcmp(const s_Opcode* const self, const s_Opcode* const other,
250 : : const int op)
251 : : {
252 : 17 : bool c = false;
253 : :
254 : : // Check for null and if the types match. If different type,
255 : : // simply return False
256 [ + - ][ + + ]: 17 : if (!other || (self->ob_type != other->ob_type)) {
257 : 1 : Py_RETURN_FALSE;
258 : : }
259 : :
260 : : // Only equals and not equals here, unorderable type
261 [ + + + + : 16 : switch (op) {
+ + - ]
262 : : case Py_LT:
263 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
264 : 1 : return (NULL);
265 : : case Py_LE:
266 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
267 : 1 : return (NULL);
268 : : case Py_EQ:
269 : 16 : c = (*self->cppobj == *other->cppobj);
270 : 8 : break;
271 : : case Py_NE:
272 : 8 : c = (*self->cppobj != *other->cppobj);
273 : 4 : break;
274 : : case Py_GT:
275 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
276 : 1 : return (NULL);
277 : : case Py_GE:
278 : 1 : PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
279 : 1 : return (NULL);
280 : : }
281 [ + + ]: 12 : if (c)
282 : 9 : Py_RETURN_TRUE;
283 : : else
284 : 17 : Py_RETURN_FALSE;
285 : : }
286 : :
287 : : } // end of unnamed namespace
288 : :
289 : : namespace isc {
290 : : namespace dns {
291 : : namespace python {
292 : :
293 : : PyTypeObject opcode_type = {
294 : : PyVarObject_HEAD_INIT(NULL, 0)
295 : : "pydnspp.Opcode",
296 : : sizeof(s_Opcode), // tp_basicsize
297 : : 0, // tp_itemsize
298 : : (destructor)Opcode_destroy, // tp_dealloc
299 : : NULL, // tp_print
300 : : NULL, // tp_getattr
301 : : NULL, // tp_setattr
302 : : NULL, // tp_reserved
303 : : NULL, // tp_repr
304 : : NULL, // tp_as_number
305 : : NULL, // tp_as_sequence
306 : : NULL, // tp_as_mapping
307 : : NULL, // tp_hash
308 : : NULL, // tp_call
309 : : Opcode_str, // tp_str
310 : : NULL, // tp_getattro
311 : : NULL, // tp_setattro
312 : : NULL, // tp_as_buffer
313 : : Py_TPFLAGS_DEFAULT, // tp_flags
314 : : "The Opcode class objects represent standard OPCODEs "
315 : : "of the header section of DNS messages.",
316 : : NULL, // tp_traverse
317 : : NULL, // tp_clear
318 : : (richcmpfunc)Opcode_richcmp, // tp_richcompare
319 : : 0, // tp_weaklistoffset
320 : : NULL, // tp_iter
321 : : NULL, // tp_iternext
322 : : Opcode_methods, // tp_methods
323 : : NULL, // tp_members
324 : : NULL, // tp_getset
325 : : NULL, // tp_base
326 : : NULL, // tp_dict
327 : : NULL, // tp_descr_get
328 : : NULL, // tp_descr_set
329 : : 0, // tp_dictoffset
330 : : (initproc)Opcode_init, // tp_init
331 : : NULL, // tp_alloc
332 : : PyType_GenericNew, // tp_new
333 : : NULL, // tp_free
334 : : NULL, // tp_is_gc
335 : : NULL, // tp_bases
336 : : NULL, // tp_mro
337 : : NULL, // tp_cache
338 : : NULL, // tp_subclasses
339 : : NULL, // tp_weaklist
340 : : NULL, // tp_del
341 : : 0 // tp_version_tag
342 : : };
343 : :
344 : : PyObject*
345 : 121 : createOpcodeObject(const Opcode& source) {
346 : 121 : OpcodeContainer container(PyObject_New(s_Opcode, &opcode_type));
347 [ + - ][ + - ]: 121 : container.set(new Opcode(source));
348 : 121 : return (container.release());
349 : : }
350 : :
351 : : bool
352 : 0 : PyOpcode_Check(PyObject* obj) {
353 [ # # ]: 0 : if (obj == NULL) {
354 [ # # ][ # # ]: 0 : isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
355 : : }
356 [ # # ][ # # ]: 0 : return (PyObject_TypeCheck(obj, &opcode_type));
357 : : }
358 : :
359 : : const Opcode&
360 : 421 : PyOpcode_ToOpcode(const PyObject* opcode_obj) {
361 [ - + ]: 421 : if (opcode_obj == NULL) {
362 [ # # ][ # # ]: 0 : isc_throw(PyCPPWrapperException,
363 : : "obj argument NULL in Opcode PyObject conversion");
364 : : }
365 : 421 : const s_Opcode* opcode = static_cast<const s_Opcode*>(opcode_obj);
366 : 421 : return (*opcode->cppobj);
367 : : }
368 : :
369 : : } // end python namespace
370 : : } // end dns namespace
371 : 0 : } // end isc namespace
|