opcode_python.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. #include <Python.h>
  15. #include <dns/opcode.h>
  16. #include <util/python/pycppwrapper_util.h>
  17. #include "pydnspp_common.h"
  18. #include "opcode_python.h"
  19. #include "edns_python.h"
  20. using namespace isc::dns;
  21. using namespace isc::dns::python;
  22. using namespace isc::util;
  23. using namespace isc::util::python;
  24. namespace {
  25. class s_Opcode : public PyObject {
  26. public:
  27. s_Opcode() : cppobj(NULL), static_code(false) {}
  28. const isc::dns::Opcode* cppobj;
  29. bool static_code;
  30. };
  31. typedef CPPPyObjectContainer<s_Opcode, Opcode> OpcodeContainer;
  32. int Opcode_init(s_Opcode* const self, PyObject* args);
  33. void Opcode_destroy(s_Opcode* const self);
  34. PyObject* Opcode_getCode(const s_Opcode* const self);
  35. PyObject* Opcode_toText(const s_Opcode* const self);
  36. PyObject* Opcode_str(PyObject* self);
  37. PyMethodDef Opcode_methods[] = {
  38. { "get_code", reinterpret_cast<PyCFunction>(Opcode_getCode), METH_NOARGS,
  39. "Returns the code value" },
  40. { "to_text", reinterpret_cast<PyCFunction>(Opcode_toText), METH_NOARGS,
  41. "Returns the text representation" },
  42. { NULL, NULL, 0, NULL }
  43. };
  44. int
  45. Opcode_init(s_Opcode* const self, PyObject* args) {
  46. uint8_t code = 0;
  47. if (PyArg_ParseTuple(args, "b", &code)) {
  48. try {
  49. self->cppobj = new Opcode(code);
  50. self->static_code = false;
  51. } catch (const isc::OutOfRange& ex) {
  52. PyErr_SetString(PyExc_OverflowError, ex.what());
  53. return (-1);
  54. } catch (...) {
  55. PyErr_SetString(po_IscException, "Unexpected exception");
  56. return (-1);
  57. }
  58. return (0);
  59. }
  60. PyErr_Clear();
  61. PyErr_SetString(PyExc_TypeError, "Invalid arguments to Opcode constructor");
  62. return (-1);
  63. }
  64. void
  65. Opcode_destroy(s_Opcode* const self) {
  66. // Depending on whether we created the rcode or are referring
  67. // to a global static one, we do or do not delete self->cppobj here
  68. if (!self->static_code) {
  69. delete self->cppobj;
  70. }
  71. self->cppobj = NULL;
  72. Py_TYPE(self)->tp_free(self);
  73. }
  74. PyObject*
  75. Opcode_getCode(const s_Opcode* const self) {
  76. return (Py_BuildValue("I", self->cppobj->getCode()));
  77. }
  78. PyObject*
  79. Opcode_toText(const s_Opcode* const self) {
  80. return (Py_BuildValue("s", self->cppobj->toText().c_str()));
  81. }
  82. PyObject*
  83. Opcode_str(PyObject* self) {
  84. // Simply call the to_text method we already defined
  85. return (PyObject_CallMethod(self,
  86. const_cast<char*>("to_text"),
  87. const_cast<char*>("")));
  88. }
  89. PyObject*
  90. Opcode_richcmp(const s_Opcode* const self, const s_Opcode* const other,
  91. const int op)
  92. {
  93. bool c = false;
  94. // Check for null and if the types match. If different type,
  95. // simply return False
  96. if (!other || (self->ob_type != other->ob_type)) {
  97. Py_RETURN_FALSE;
  98. }
  99. // Only equals and not equals here, unorderable type
  100. switch (op) {
  101. case Py_LT:
  102. PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
  103. return (NULL);
  104. case Py_LE:
  105. PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
  106. return (NULL);
  107. case Py_EQ:
  108. c = (*self->cppobj == *other->cppobj);
  109. break;
  110. case Py_NE:
  111. c = (*self->cppobj != *other->cppobj);
  112. break;
  113. case Py_GT:
  114. PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
  115. return (NULL);
  116. case Py_GE:
  117. PyErr_SetString(PyExc_TypeError, "Unorderable type; Opcode");
  118. return (NULL);
  119. }
  120. if (c)
  121. Py_RETURN_TRUE;
  122. else
  123. Py_RETURN_FALSE;
  124. }
  125. } // end of unnamed namespace
  126. namespace isc {
  127. namespace dns {
  128. namespace python {
  129. PyTypeObject opcode_type = {
  130. PyVarObject_HEAD_INIT(NULL, 0)
  131. "pydnspp.Opcode",
  132. sizeof(s_Opcode), // tp_basicsize
  133. 0, // tp_itemsize
  134. (destructor)Opcode_destroy, // tp_dealloc
  135. NULL, // tp_print
  136. NULL, // tp_getattr
  137. NULL, // tp_setattr
  138. NULL, // tp_reserved
  139. NULL, // tp_repr
  140. NULL, // tp_as_number
  141. NULL, // tp_as_sequence
  142. NULL, // tp_as_mapping
  143. NULL, // tp_hash
  144. NULL, // tp_call
  145. Opcode_str, // tp_str
  146. NULL, // tp_getattro
  147. NULL, // tp_setattro
  148. NULL, // tp_as_buffer
  149. Py_TPFLAGS_DEFAULT, // tp_flags
  150. "The Opcode class objects represent standard OPCODEs "
  151. "of the header section of DNS messages.",
  152. NULL, // tp_traverse
  153. NULL, // tp_clear
  154. (richcmpfunc)Opcode_richcmp, // tp_richcompare
  155. 0, // tp_weaklistoffset
  156. NULL, // tp_iter
  157. NULL, // tp_iternext
  158. Opcode_methods, // tp_methods
  159. NULL, // tp_members
  160. NULL, // tp_getset
  161. NULL, // tp_base
  162. NULL, // tp_dict
  163. NULL, // tp_descr_get
  164. NULL, // tp_descr_set
  165. 0, // tp_dictoffset
  166. (initproc)Opcode_init, // tp_init
  167. NULL, // tp_alloc
  168. PyType_GenericNew, // tp_new
  169. NULL, // tp_free
  170. NULL, // tp_is_gc
  171. NULL, // tp_bases
  172. NULL, // tp_mro
  173. NULL, // tp_cache
  174. NULL, // tp_subclasses
  175. NULL, // tp_weaklist
  176. NULL, // tp_del
  177. 0 // tp_version_tag
  178. };
  179. PyObject*
  180. createOpcodeObject(const Opcode& source) {
  181. OpcodeContainer container(PyObject_New(s_Opcode, &opcode_type));
  182. container.set(new Opcode(source));
  183. return (container.release());
  184. }
  185. bool
  186. PyOpcode_Check(PyObject* obj) {
  187. if (obj == NULL) {
  188. isc_throw(PyCPPWrapperException, "obj argument NULL in typecheck");
  189. }
  190. return (PyObject_TypeCheck(obj, &opcode_type));
  191. }
  192. const Opcode&
  193. PyOpcode_ToOpcode(const PyObject* opcode_obj) {
  194. if (opcode_obj == NULL) {
  195. isc_throw(PyCPPWrapperException,
  196. "obj argument NULL in Opcode PyObject conversion");
  197. }
  198. const s_Opcode* opcode = static_cast<const s_Opcode*>(opcode_obj);
  199. return (*opcode->cppobj);
  200. }
  201. } // end python namespace
  202. } // end dns namespace
  203. } // end isc namespace