Branch data Line data Source code
1 : : // Copyright (C) 2011 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 <string>
18 : : #include <stdexcept>
19 : :
20 : : #include <util/python/pycppwrapper_util.h>
21 : :
22 : : #include <dns/tsigrecord.h>
23 : :
24 : : #include "pydnspp_common.h"
25 : : #include "pydnspp_towire.h"
26 : : #include "name_python.h"
27 : : #include "tsig_rdata_python.h"
28 : : #include "tsigrecord_python.h"
29 : :
30 : : using namespace std;
31 : : using namespace isc::util::python;
32 : : using namespace isc::dns;
33 : : using namespace isc::dns::python;
34 : :
35 : : // For each class, we need a struct, a helper functions (init, destroy,
36 : : // and static wrappers around the methods we export), a list of methods,
37 : : // and a type description
38 : :
39 : : //
40 : : // TSIGRecord
41 : : //
42 : :
43 : : namespace {
44 : : // The s_* Class simply covers one instantiation of the object
45 : : class s_TSIGRecord : public PyObject {
46 : : public:
47 : : s_TSIGRecord() : cppobj(NULL) {};
48 : : TSIGRecord* cppobj;
49 : : };
50 : :
51 : : // Shortcut type which would be convenient for adding class variables safely.
52 : : typedef CPPPyObjectContainer<s_TSIGRecord, TSIGRecord> TSIGRecordContainer;
53 : :
54 : : //
55 : : // We declare the functions here, the definitions are below
56 : : // the type definition of the object, since both can use the other
57 : : //
58 : :
59 : : // General creation and destruction
60 : : int TSIGRecord_init(s_TSIGRecord* self, PyObject* args);
61 : : void TSIGRecord_destroy(s_TSIGRecord* self);
62 : : PyObject* TSIGRecord_toText(const s_TSIGRecord* const self);
63 : : PyObject* TSIGRecord_str(PyObject* self);
64 : : PyObject* TSIGRecord_toWire(const s_TSIGRecord* self, PyObject* args);
65 : : PyObject* TSIGRecord_getName(const s_TSIGRecord* self);
66 : : PyObject* TSIGRecord_getLength(const s_TSIGRecord* self);
67 : : PyObject* TSIGRecord_getRdata(const s_TSIGRecord* self);
68 : :
69 : : // These are the functions we export
70 : : // For a minimal support, we don't need them.
71 : :
72 : : // This list contains the actual set of functions we have in
73 : : // python. Each entry has
74 : : // 1. Python method name
75 : : // 2. Our static function here
76 : : // 3. Argument type
77 : : // 4. Documentation
78 : : PyMethodDef TSIGRecord_methods[] = {
79 : : { "get_name", reinterpret_cast<PyCFunction>(TSIGRecord_getName),
80 : : METH_NOARGS,
81 : : "Return the owner name of the TSIG RR, which is the TSIG key name" },
82 : : { "get_length", reinterpret_cast<PyCFunction>(TSIGRecord_getLength),
83 : : METH_NOARGS,
84 : : "Return the length of the TSIG record" },
85 : : { "get_rdata", reinterpret_cast<PyCFunction>(TSIGRecord_getRdata),
86 : : METH_NOARGS,
87 : : "Return the RDATA of the TSIG RR" },
88 : : { "to_text", reinterpret_cast<PyCFunction>(TSIGRecord_toText), METH_NOARGS,
89 : : "Returns the text representation" },
90 : : { "to_wire", reinterpret_cast<PyCFunction>(TSIGRecord_toWire),
91 : : METH_VARARGS,
92 : : "Converts the TSIGRecord object to wire format.\n"
93 : : "The argument can be either a MessageRenderer or an object that "
94 : : "implements the sequence interface. If the object is mutable "
95 : : "(for instance a bytearray()), the wire data is added in-place.\n"
96 : : "If it is not (for instance a bytes() object), a new object is "
97 : : "returned" },
98 : : { NULL, NULL, 0, NULL }
99 : : };
100 : :
101 : : int
102 : 36 : TSIGRecord_init(s_TSIGRecord* self, PyObject* args) {
103 : : try {
104 : : const PyObject* py_name;
105 : : const PyObject* py_tsig;
106 [ + - ]: 36 : if (PyArg_ParseTuple(args, "O!O!", &name_type, &py_name,
107 [ + - ]: 36 : &tsig_type, &py_tsig)) {
108 : 36 : self->cppobj = new TSIGRecord(PyName_ToName(py_name),
109 [ + - ][ + - ]: 36 : PyTSIG_ToTSIG(py_tsig));
[ + - ][ + - ]
110 : 36 : return (0);
111 : : }
112 : 0 : } catch (const exception& ex) {
113 : : const string ex_what = "Failed to construct TSIGRecord object: " +
114 [ # # ][ # # ]: 0 : string(ex.what());
115 [ # # ]: 0 : PyErr_SetString(po_IscException, ex_what.c_str());
116 : : return (-1);
117 [ # # ]: 0 : } catch (...) {
118 : : PyErr_SetString(po_IscException,
119 [ # # ]: 0 : "Unexpected exception in constructing TSIGRecord");
120 : : return (-1);
121 : : }
122 : :
123 : : PyErr_SetString(PyExc_TypeError,
124 : 0 : "Invalid arguments to TSIGRecord constructor");
125 : :
126 : 36 : return (-1);
127 : : }
128 : :
129 : : // This is a template of typical code logic of python object destructor.
130 : : // In many cases you can use it without modification, but check that carefully.
131 : : void
132 : 221 : TSIGRecord_destroy(s_TSIGRecord* const self) {
133 [ + - ]: 442 : delete self->cppobj;
134 : 221 : self->cppobj = NULL;
135 : 221 : Py_TYPE(self)->tp_free(self);
136 : 221 : }
137 : :
138 : : // This should be able to be used without modification as long as the
139 : : // underlying C++ class has toText().
140 : : PyObject*
141 : 2 : TSIGRecord_toText(const s_TSIGRecord* const self) {
142 : : try {
143 : : // toText() could throw, so we need to catch any exceptions below.
144 [ + - ][ + - ]: 2 : return (Py_BuildValue("s", self->cppobj->toText().c_str()));
145 : 0 : } catch (const exception& ex) {
146 : : const string ex_what =
147 : : "Failed to convert TSIGRecord object to text: " +
148 [ # # ][ # # ]: 0 : string(ex.what());
149 [ # # ]: 0 : PyErr_SetString(po_IscException, ex_what.c_str());
150 [ # # ]: 0 : } catch (...) {
151 : : PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
152 [ # # ]: 0 : "converting TSIGRecord object to text");
153 : : }
154 : : return (NULL);
155 : : }
156 : :
157 : : PyObject*
158 : 1 : TSIGRecord_str(PyObject* self) {
159 : : // Simply call the to_text method we already defined
160 : : return (PyObject_CallMethod(self, const_cast<char*>("to_text"),
161 : 1 : const_cast<char*>("")));
162 : : }
163 : :
164 : : PyObject*
165 : 19 : TSIGRecord_toWire(const s_TSIGRecord* const self, PyObject* args) {
166 : : typedef ToWireCallInt<const TSIGRecord> ToWireCall;
167 : : PyObject* (*towire_fn)(const s_TSIGRecord* const, PyObject*) =
168 : 19 : toWireWrapper<s_TSIGRecord, TSIGRecord, ToWireCall>;
169 : 19 : return (towire_fn(self, args));
170 : : }
171 : :
172 : : PyObject*
173 : 22 : TSIGRecord_getName(const s_TSIGRecord* const self) {
174 : : try {
175 [ + - ]: 22 : return (createNameObject(self->cppobj->getName()));
176 : 0 : } catch (const exception& ex) {
177 : : const string ex_what =
178 [ # # ][ # # ]: 0 : "Failed to get TSIGRecord name: " + string(ex.what());
179 [ # # ]: 0 : PyErr_SetString(po_IscException, ex_what.c_str());
180 [ # # ]: 0 : } catch (...) {
181 : : PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
182 [ # # ]: 0 : "getting TSIGRecord name");
183 : : }
184 : : return (NULL);
185 : : }
186 : :
187 : : PyObject*
188 : 21 : TSIGRecord_getLength(const s_TSIGRecord* const self) {
189 : 21 : return (Py_BuildValue("H", self->cppobj->getLength()));
190 : : }
191 : :
192 : : PyObject*
193 : 28 : TSIGRecord_getRdata(const s_TSIGRecord* const self) {
194 : : try {
195 [ + - ]: 28 : return (createTSIGObject(self->cppobj->getRdata()));
196 : 0 : } catch (const exception& ex) {
197 : : const string ex_what =
198 [ # # ][ # # ]: 0 : "Failed to get TSIGRecord RDATA: " + string(ex.what());
199 [ # # ]: 0 : PyErr_SetString(po_IscException, ex_what.c_str());
200 [ # # ]: 0 : } catch (...) {
201 : : PyErr_SetString(PyExc_SystemError, "Unexpected failure in "
202 [ # # ]: 0 : "getting TSIGRecord RDATA");
203 : : }
204 : : return (NULL);
205 : : }
206 : :
207 : : } // end of unnamed namespace
208 : :
209 : : namespace isc {
210 : : namespace dns {
211 : : namespace python {
212 : : // This defines the complete type for reflection in python and
213 : : // parsing of PyObject* to s_TSIGRecord
214 : : // Most of the functions are not actually implemented and NULL here.
215 : : PyTypeObject tsigrecord_type = {
216 : : PyVarObject_HEAD_INIT(NULL, 0)
217 : : "pydnspp.TSIGRecord",
218 : : sizeof(s_TSIGRecord), // tp_basicsize
219 : : 0, // tp_itemsize
220 : : reinterpret_cast<destructor>(TSIGRecord_destroy), // tp_dealloc
221 : : NULL, // tp_print
222 : : NULL, // tp_getattr
223 : : NULL, // tp_setattr
224 : : NULL, // tp_reserved
225 : : NULL, // tp_repr
226 : : NULL, // tp_as_number
227 : : NULL, // tp_as_sequence
228 : : NULL, // tp_as_mapping
229 : : NULL, // tp_hash
230 : : NULL, // tp_call
231 : : TSIGRecord_str, // tp_str
232 : : NULL, // tp_getattro
233 : : NULL, // tp_setattro
234 : : NULL, // tp_as_buffer
235 : : Py_TPFLAGS_DEFAULT, // tp_flags
236 : : "The TSIGRecord class objects is...(COMPLETE THIS)",
237 : : NULL, // tp_traverse
238 : : NULL, // tp_clear
239 : : NULL, // tp_richcompare
240 : : 0, // tp_weaklistoffset
241 : : NULL, // tp_iter
242 : : NULL, // tp_iternext
243 : : TSIGRecord_methods, // tp_methods
244 : : NULL, // tp_members
245 : : NULL, // tp_getset
246 : : NULL, // tp_base
247 : : NULL, // tp_dict
248 : : NULL, // tp_descr_get
249 : : NULL, // tp_descr_set
250 : : 0, // tp_dictoffset
251 : : reinterpret_cast<initproc>(TSIGRecord_init), // tp_init
252 : : NULL, // tp_alloc
253 : : PyType_GenericNew, // tp_new
254 : : NULL, // tp_free
255 : : NULL, // tp_is_gc
256 : : NULL, // tp_bases
257 : : NULL, // tp_mro
258 : : NULL, // tp_cache
259 : : NULL, // tp_subclasses
260 : : NULL, // tp_weaklist
261 : : NULL, // tp_del
262 : : 0 // tp_version_tag
263 : : };
264 : :
265 : : PyObject*
266 : 185 : createTSIGRecordObject(const TSIGRecord& source) {
267 : 185 : TSIGRecordContainer container(PyObject_New(s_TSIGRecord, &tsigrecord_type));
268 [ + - ][ + - ]: 370 : container.set(new TSIGRecord(source));
269 : 185 : return (container.release());
270 : : }
271 : :
272 : : bool
273 : 0 : PyTSIGRecord_Check(PyObject* obj) {
274 [ # # ]: 0 : if (obj == NULL) {
275 [ # # ][ # # ]: 0 : isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
276 : : }
277 [ # # ][ # # ]: 0 : return (PyObject_TypeCheck(obj, &tsigrecord_type));
278 : : }
279 : :
280 : : const TSIGRecord&
281 : 51 : PyTSIGRecord_ToTSIGRecord(PyObject* tsigrecord_obj) {
282 [ - + ]: 51 : if (tsigrecord_obj == NULL) {
283 [ # # ][ # # ]: 0 : isc_throw(PyCPPWrapperException,
284 : : "obj argument NULL in TSIGRecord PyObject conversion");
285 : : }
286 : 51 : s_TSIGRecord* tsigrecord = static_cast<s_TSIGRecord*>(tsigrecord_obj);
287 : 51 : return (*tsigrecord->cppobj);
288 : : }
289 : :
290 : :
291 : : } // namespace python
292 : : } // namespace dns
293 : 123 : } // namespace isc
|