messagerenderer_python.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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 <util/buffer.h>
  16. #include <dns/messagerenderer.h>
  17. #include "pydnspp_common.h"
  18. #include "messagerenderer_python.h"
  19. using namespace isc::dns;
  20. using namespace isc::dns::python;
  21. using namespace isc::util;
  22. // MessageRenderer
  23. s_MessageRenderer::s_MessageRenderer() : outputbuffer(NULL),
  24. messagerenderer(NULL)
  25. {
  26. }
  27. namespace {
  28. int MessageRenderer_init(s_MessageRenderer* self);
  29. void MessageRenderer_destroy(s_MessageRenderer* self);
  30. PyObject* MessageRenderer_getData(s_MessageRenderer* self);
  31. PyObject* MessageRenderer_getLength(s_MessageRenderer* self);
  32. PyObject* MessageRenderer_isTruncated(s_MessageRenderer* self);
  33. PyObject* MessageRenderer_getLengthLimit(s_MessageRenderer* self);
  34. PyObject* MessageRenderer_getCompressMode(s_MessageRenderer* self);
  35. PyObject* MessageRenderer_setTruncated(s_MessageRenderer* self);
  36. PyObject* MessageRenderer_setLengthLimit(s_MessageRenderer* self, PyObject* args);
  37. PyObject* MessageRenderer_setCompressMode(s_MessageRenderer* self, PyObject* args);
  38. PyObject* MessageRenderer_clear(s_MessageRenderer* self);
  39. PyMethodDef MessageRenderer_methods[] = {
  40. { "get_data", reinterpret_cast<PyCFunction>(MessageRenderer_getData), METH_NOARGS,
  41. "Returns the data as a bytes() object" },
  42. { "get_length", reinterpret_cast<PyCFunction>(MessageRenderer_getLength), METH_NOARGS,
  43. "Returns the length of the data" },
  44. { "is_truncated", reinterpret_cast<PyCFunction>(MessageRenderer_isTruncated), METH_NOARGS,
  45. "Returns True if the data is truncated" },
  46. { "get_length_limit", reinterpret_cast<PyCFunction>(MessageRenderer_getLengthLimit), METH_NOARGS,
  47. "Returns the length limit of the data" },
  48. { "get_compress_mode", reinterpret_cast<PyCFunction>(MessageRenderer_getCompressMode), METH_NOARGS,
  49. "Returns the current compression mode" },
  50. { "set_truncated", reinterpret_cast<PyCFunction>(MessageRenderer_setTruncated), METH_NOARGS,
  51. "Sets truncated to true" },
  52. { "set_length_limit", reinterpret_cast<PyCFunction>(MessageRenderer_setLengthLimit), METH_VARARGS,
  53. "Sets the length limit of the data to the given number" },
  54. { "set_compress_mode", reinterpret_cast<PyCFunction>(MessageRenderer_setCompressMode), METH_VARARGS,
  55. "Sets the compression mode of the MessageRenderer" },
  56. { "clear", reinterpret_cast<PyCFunction>(MessageRenderer_clear),
  57. METH_NOARGS,
  58. "Clear the internal buffer and other internal resources." },
  59. { NULL, NULL, 0, NULL }
  60. };
  61. int
  62. MessageRenderer_init(s_MessageRenderer* self) {
  63. self->outputbuffer = new OutputBuffer(4096);
  64. self->messagerenderer = new MessageRenderer(*self->outputbuffer);
  65. return (0);
  66. }
  67. void
  68. MessageRenderer_destroy(s_MessageRenderer* self) {
  69. delete self->messagerenderer;
  70. delete self->outputbuffer;
  71. self->messagerenderer = NULL;
  72. self->outputbuffer = NULL;
  73. Py_TYPE(self)->tp_free(self);
  74. }
  75. PyObject*
  76. MessageRenderer_getData(s_MessageRenderer* self) {
  77. return (Py_BuildValue("y#",
  78. self->messagerenderer->getData(),
  79. self->messagerenderer->getLength()));
  80. }
  81. PyObject*
  82. MessageRenderer_getLength(s_MessageRenderer* self) {
  83. return (Py_BuildValue("I", self->messagerenderer->getLength()));
  84. }
  85. PyObject*
  86. MessageRenderer_isTruncated(s_MessageRenderer* self) {
  87. if (self->messagerenderer->isTruncated()) {
  88. Py_RETURN_TRUE;
  89. } else {
  90. Py_RETURN_FALSE;
  91. }
  92. }
  93. PyObject*
  94. MessageRenderer_getLengthLimit(s_MessageRenderer* self) {
  95. return (Py_BuildValue("I", self->messagerenderer->getLengthLimit()));
  96. }
  97. PyObject*
  98. MessageRenderer_getCompressMode(s_MessageRenderer* self) {
  99. return (Py_BuildValue("I", self->messagerenderer->getCompressMode()));
  100. }
  101. PyObject*
  102. MessageRenderer_setTruncated(s_MessageRenderer* self) {
  103. self->messagerenderer->setTruncated();
  104. Py_RETURN_NONE;
  105. }
  106. PyObject*
  107. MessageRenderer_setLengthLimit(s_MessageRenderer* self,
  108. PyObject* args)
  109. {
  110. long lengthlimit;
  111. if (!PyArg_ParseTuple(args, "l", &lengthlimit)) {
  112. PyErr_Clear();
  113. PyErr_SetString(PyExc_TypeError,
  114. "No valid type in set_length_limit argument");
  115. return (NULL);
  116. }
  117. if (lengthlimit < 0) {
  118. PyErr_SetString(PyExc_ValueError,
  119. "MessageRenderer length limit out of range");
  120. return (NULL);
  121. }
  122. self->messagerenderer->setLengthLimit(lengthlimit);
  123. Py_RETURN_NONE;
  124. }
  125. PyObject*
  126. MessageRenderer_setCompressMode(s_MessageRenderer* self,
  127. PyObject* args)
  128. {
  129. int mode;
  130. if (!PyArg_ParseTuple(args, "i", &mode)) {
  131. return (NULL);
  132. }
  133. if (mode == MessageRenderer::CASE_INSENSITIVE) {
  134. self->messagerenderer->setCompressMode(MessageRenderer::CASE_INSENSITIVE);
  135. // If we return NULL it is seen as an error, so use this for
  136. // None returns, it also applies to CASE_SENSITIVE.
  137. Py_RETURN_NONE;
  138. } else if (mode == MessageRenderer::CASE_SENSITIVE) {
  139. self->messagerenderer->setCompressMode(MessageRenderer::CASE_SENSITIVE);
  140. Py_RETURN_NONE;
  141. } else {
  142. PyErr_SetString(PyExc_TypeError,
  143. "MessageRenderer compress mode must be MessageRenderer.CASE_INSENSITIVE"
  144. "or MessageRenderer.CASE_SENSITIVE");
  145. return (NULL);
  146. }
  147. }
  148. PyObject*
  149. MessageRenderer_clear(s_MessageRenderer* self) {
  150. self->messagerenderer->clear();
  151. Py_RETURN_NONE;
  152. }
  153. } // end of unnamed namespace
  154. // end of MessageRenderer
  155. namespace isc {
  156. namespace dns {
  157. namespace python {
  158. PyTypeObject messagerenderer_type = {
  159. PyVarObject_HEAD_INIT(NULL, 0)
  160. "pydnspp.MessageRenderer",
  161. sizeof(s_MessageRenderer), // tp_basicsize
  162. 0, // tp_itemsize
  163. (destructor)MessageRenderer_destroy,// tp_dealloc
  164. NULL, // tp_print
  165. NULL, // tp_getattr
  166. NULL, // tp_setattr
  167. NULL, // tp_reserved
  168. NULL, // tp_repr
  169. NULL, // tp_as_number
  170. NULL, // tp_as_sequence
  171. NULL, // tp_as_mapping
  172. NULL, // tp_hash
  173. NULL, // tp_call
  174. NULL, // tp_str
  175. NULL, // tp_getattro
  176. NULL, // tp_setattro
  177. NULL, // tp_as_buffer
  178. Py_TPFLAGS_DEFAULT, // tp_flags
  179. "The MessageRenderer class encapsulates implementation details "
  180. "of rendering a DNS message into a buffer in wire format. "
  181. "In effect, it's simply responsible for name compression at least in the "
  182. "current implementation. A MessageRenderer class object manages the "
  183. "positions of names rendered in a buffer and uses that information to render "
  184. "subsequent names with compression.",
  185. NULL, // tp_traverse
  186. NULL, // tp_clear
  187. NULL, // tp_richcompare
  188. 0, // tp_weaklistoffset
  189. NULL, // tp_iter
  190. NULL, // tp_iternext
  191. MessageRenderer_methods, // tp_methods
  192. NULL, // tp_members
  193. NULL, // tp_getset
  194. NULL, // tp_base
  195. NULL, // tp_dict
  196. NULL, // tp_descr_get
  197. NULL, // tp_descr_set
  198. 0, // tp_dictoffset
  199. (initproc)MessageRenderer_init, // tp_init
  200. NULL, // tp_alloc
  201. PyType_GenericNew, // tp_new
  202. NULL, // tp_free
  203. NULL, // tp_is_gc
  204. NULL, // tp_bases
  205. NULL, // tp_mro
  206. NULL, // tp_cache
  207. NULL, // tp_subclasses
  208. NULL, // tp_weaklist
  209. NULL, // tp_del
  210. 0 // tp_version_tag
  211. };
  212. // Module Initialization, all statics are initialized here
  213. bool
  214. initModulePart_MessageRenderer(PyObject* mod) {
  215. // Add the exceptions to the module
  216. // Add the enums to the module
  217. // Add the constants to the module
  218. // Add the classes to the module
  219. // We initialize the static description object with PyType_Ready(),
  220. // then add it to the module
  221. // NameComparisonResult
  222. if (PyType_Ready(&messagerenderer_type) < 0) {
  223. return (false);
  224. }
  225. Py_INCREF(&messagerenderer_type);
  226. // Class variables
  227. // These are added to the tp_dict of the type object
  228. addClassVariable(messagerenderer_type, "CASE_INSENSITIVE",
  229. Py_BuildValue("I", MessageRenderer::CASE_INSENSITIVE));
  230. addClassVariable(messagerenderer_type, "CASE_SENSITIVE",
  231. Py_BuildValue("I", MessageRenderer::CASE_SENSITIVE));
  232. PyModule_AddObject(mod, "MessageRenderer",
  233. reinterpret_cast<PyObject*>(&messagerenderer_type));
  234. return (true);
  235. }
  236. } // namespace python
  237. } // namespace dns
  238. } // namespace isc