Skip to content

Commit 2d70acd

Browse files
committed
Added result object
1 parent 8f8e977 commit 2d70acd

File tree

5 files changed

+264
-6
lines changed

5 files changed

+264
-6
lines changed

getdns.c

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,67 @@
4949

5050
PyObject *getdns_error;
5151

52+
PyMemberDef Result_members[] = {
53+
{ "just_address_answers", T_OBJECT_EX, offsetof(getdns_ResultObject, just_address_answers),
54+
0, "Only the query answers" },
55+
{ "replies_tree", T_OBJECT_EX, offsetof(getdns_ResultObject, replies_tree),
56+
0, "The replies tree dictionary" },
57+
{ "replies_full", T_OBJECT_EX, offsetof(getdns_ResultObject, replies_full),
58+
0, "The entire replies structure returned by getdns" },
59+
{ "status", T_OBJECT_EX, offsetof(getdns_ResultObject, status), 0, "Response status" },
60+
{ "answer_type", T_OBJECT_EX, offsetof(getdns_ResultObject, answer_type), 0, "Answer type" },
61+
{ "canonical_name", T_OBJECT_EX, offsetof(getdns_ResultObject, canonical_name), 0,
62+
"Canonical name" },
63+
{ NULL },
64+
};
65+
66+
static PyMethodDef Result_methods[] = {
67+
{ NULL },
68+
};
69+
70+
71+
PyTypeObject getdns_ResultType = {
72+
PyObject_HEAD_INIT(NULL)
73+
0, /*ob_size*/
74+
"getdns.Result", /*tp_name*/
75+
sizeof(getdns_ResultObject), /*tp_basicsize*/
76+
0, /*tp_itemsize*/
77+
(destructor)result_dealloc, /*tp_dealloc*/
78+
0, /*tp_print*/
79+
0, /*tp_getattr*/
80+
0, /*tp_setattr*/
81+
0, /*tp_compare*/
82+
0, /*tp_repr*/
83+
0, /*tp_as_number*/
84+
0, /*tp_as_sequence*/
85+
0, /*tp_as_mapping*/
86+
0, /*tp_hash */
87+
0, /*tp_call*/
88+
0, /*tp_str*/
89+
0, /*tp_getattro*/
90+
0, /*tp_setattro*/
91+
0, /*tp_as_buffer*/
92+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
93+
"Result objects", /* tp_doc */
94+
0, /* tp_traverse */
95+
0, /* tp_clear */
96+
0, /* tp_richcompare */
97+
0, /* tp_weaklistoffset */
98+
0, /* tp_iter */
99+
0, /* tp_iternext */
100+
Result_methods, /* tp_methods */
101+
Result_members, /* tp_members */
102+
0, /* tp_getset */
103+
0, /* tp_base */
104+
0, /* tp_dict */
105+
0, /* tp_descr_get */
106+
0, /* tp_descr_set */
107+
0, /* tp_dictoffset */
108+
(initproc)result_init, /* tp_init */
109+
0, /* tp_alloc */
110+
PyType_GenericNew, /* tp_new */
111+
};
112+
52113

53114
PyMethodDef Context_methods[] = {
54115
{ "get_api_information", (PyCFunction)context_get_api_information,
@@ -143,6 +204,12 @@ PyTypeObject getdns_ContextType = {
143204
(initproc)context_init, /* tp_init */
144205
};
145206

207+
#if 0
208+
PyMethodDef Result_methods[] = {
209+
{ NULL },
210+
};
211+
#endif
212+
146213
pthread_t runner_thread;
147214

148215

@@ -219,6 +286,9 @@ dispatch_query(PyObject *context_capsule,
219286
struct getdns_dict *resp = 0;
220287
getdns_return_t ret;
221288
char *query_name;
289+
PyObject *result_capsule;
290+
PyObject *args;
291+
PyObject *reslt;
222292

223293
context = PyCapsule_GetPointer(context_capsule, "context");
224294
if (extensions_obj) {
@@ -227,7 +297,7 @@ dispatch_query(PyObject *context_capsule,
227297
return NULL;
228298
}
229299
}
230-
query_name = (char *)name;
300+
query_name = (char *)name;
231301

232302
if (callback) {
233303
struct event_base *gen_event_base;
@@ -287,7 +357,7 @@ dispatch_query(PyObject *context_capsule,
287357
UNUSED_PARAM(dispatch_ret);
288358

289359
event_base_free(gen_event_base);
290-
return Py_None;
360+
Py_RETURN_NONE;
291361
}
292362
if ((request_type == GETDNS_RRTYPE_A) || (request_type == GETDNS_RRTYPE_AAAA)) {
293363
if ((ret = getdns_address_sync(context, query_name, extensions_dict, &resp)) != GETDNS_RETURN_GOOD) {
@@ -320,7 +390,14 @@ dispatch_query(PyObject *context_capsule,
320390
return NULL;
321391
}
322392
}
393+
result_capsule = PyCapsule_New(resp, "result", 0);
394+
args = Py_BuildValue("(O)", result_capsule);
395+
reslt = PyObject_CallObject((PyObject *)&getdns_ResultType, args);
396+
return reslt;
397+
#if 0
398+
return py_result(result_capsule);
323399
return getFullResponse(resp);
400+
#endif
324401
}
325402

326403

@@ -391,7 +468,7 @@ do_query(PyObject *context_capsule,
391468
pthread_create(&runner_thread, NULL, (void *)marshall_query, (void *)async_blob);
392469
pthread_detach(runner_thread);
393470
Py_END_ALLOW_THREADS;
394-
return Py_None;
471+
Py_RETURN_NONE;
395472
}
396473
}
397474

@@ -413,12 +490,17 @@ initgetdns(void)
413490

414491
Py_Initialize();
415492
PyEval_InitThreads();
416-
if ((g = Py_InitModule("getdns", getdns_methods)) == NULL)
493+
if ((g = Py_InitModule3("getdns", getdns_methods, GETDNS_DOCSTRING)) == NULL)
417494
return;
418495
getdns_error = PyErr_NewException("getdns.error", NULL, NULL);
419496
Py_INCREF(getdns_error);
420497
PyModule_AddObject(g, "error", getdns_error);
421498
getdns_ContextType.tp_new = PyType_GenericNew;
499+
getdns_ResultType.tp_new = PyType_GenericNew;
500+
if (PyType_Ready(&getdns_ResultType) < 0)
501+
return;
502+
Py_INCREF(&getdns_ResultType);
503+
PyModule_AddObject(g, "Result", (PyObject *)&getdns_ResultType);
422504
if (PyType_Ready(&getdns_ContextType) < 0)
423505
return;
424506
Py_INCREF(&getdns_ContextType);

pygetdns.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#define PYGETDNS_H
3434

3535
#define PYGETDNS_VERSION "0.2.1"
36+
#define GETDNS_DOCSTRING "getdns bindings for Python (see http://www.getdnsapi.net)"
3637

3738
#define GETDNS_STR_IPV4 "IPv4"
3839
#define GETDNS_STR_IPV6 "IPv6"
@@ -61,6 +62,17 @@ typedef struct pygetdns_async_args_blob {
6162
} pygetdns_async_args_blob;
6263

6364

65+
typedef struct {
66+
PyObject_HEAD
67+
PyObject *just_address_answers;
68+
PyObject *answer_type;
69+
PyObject *status;
70+
PyObject *replies_tree;
71+
PyObject *canonical_name;
72+
PyObject *replies_full;
73+
} getdns_ResultObject;
74+
75+
6476
typedef struct {
6577
PyObject_HEAD
6678
PyObject *py_context; /* Python capsule containing getdns_context */
@@ -85,6 +97,17 @@ typedef struct {
8597
} getdns_ContextObject;
8698

8799

100+
extern PyTypeObject getdns_ResultType;
101+
void result_dealloc(getdns_ResultObject *self);
102+
extern PyObject *result_getattro(PyObject *self, PyObject *nameobj);
103+
PyObject *py_result(PyObject *result_capsule);
104+
105+
int get_status(struct getdns_dict *result_dict);
106+
int get_answer_type(struct getdns_dict *result_dict);
107+
char *get_canonical_name(struct getdns_dict *result_dict);
108+
PyObject *get_just_address_answers(struct getdns_dict *result_dict);
109+
PyObject *get_replies_tree(struct getdns_dict *result_dict);
110+
88111
int context_init(getdns_ContextObject *self, PyObject *args, PyObject *keywds);
89112
PyObject *context_getattro(PyObject *self, PyObject *nameobj);
90113
int context_setattro(PyObject *self, PyObject *attrname, PyObject *value);
@@ -111,6 +134,12 @@ PyObject *context_address(getdns_ContextObject *self, PyObject *args, PyObject *
111134
PyObject *context_hostname(getdns_ContextObject *self, PyObject *args, PyObject *keywds);
112135
PyObject *context_service(getdns_ContextObject *self, PyObject *args, PyObject *keywds);
113136

137+
void context_dealloc(getdns_ContextObject *self);
138+
139+
int result_init(getdns_ResultObject *self, PyObject *args, PyObject *keywds);
140+
PyObject *result_getattro(PyObject *self, PyObject *nameobj);
141+
int result_setattro(PyObject *self, PyObject *attrname, PyObject *value);
142+
114143
PyObject *do_query(PyObject *context_capsule, void *name, uint16_t request_type,
115144
PyDictObject *extensions_obj, void *userarg, getdns_transaction_t tid, char *callback);
116145
PyObject *pythonify_address_list(getdns_list *list);
@@ -126,7 +155,6 @@ PyObject *context_fd(PyObject *self, PyObject *args, PyObject *keywds);
126155
PyObject *context_get_num_pending_requests(PyObject *self, PyObject *args, PyObject *keywds);
127156
PyObject *context_process_async(PyObject *self, PyObject *args, PyObject *keywds);
128157
getdns_dict *getdnsify_addressdict(PyObject *pydict);
129-
void context_dealloc(getdns_ContextObject *self);
130158
void *marshall_query(void *blob);
131159
PyObject *dispatch_query(PyObject *context_capsule, void *name, uint16_t request_type,
132160
PyDictObject *extensions_obj, void *userarg, getdns_transaction_t tid, char *callback);

pygetdns_util.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,70 @@
3939
#include <ldns/ldns.h>
4040
#include "pygetdns.h"
4141

42+
43+
44+
int
45+
get_status(struct getdns_dict *result_dict)
46+
{
47+
uint32_t status;
48+
getdns_return_t ret;
49+
50+
if ((ret = getdns_dict_get_int(result_dict, "status", &status)) != GETDNS_RETURN_GOOD)
51+
return 0;
52+
return (int)status;
53+
}
54+
55+
56+
int
57+
get_answer_type(struct getdns_dict *result_dict)
58+
{
59+
uint32_t answer_type;
60+
getdns_return_t ret;
61+
62+
if ((ret = getdns_dict_get_int(result_dict, "answer_type", &answer_type)) != GETDNS_RETURN_GOOD)
63+
return 0;
64+
return (int)answer_type;
65+
}
66+
67+
68+
char *
69+
get_canonical_name(struct getdns_dict *result_dict)
70+
{
71+
getdns_bindata *canonical_name;
72+
getdns_return_t ret;
73+
74+
if ((ret = getdns_dict_get_bindata(result_dict, "canonical_name", &canonical_name)) != GETDNS_RETURN_GOOD)
75+
return 0;
76+
return (char *)canonical_name->data;
77+
}
78+
79+
80+
PyObject *
81+
get_just_address_answers(struct getdns_dict *result_dict)
82+
{
83+
struct getdns_list *just_address_answers;
84+
getdns_return_t ret;
85+
86+
if ((ret = getdns_dict_get_list(result_dict, "just_address_answers", &just_address_answers)) !=
87+
GETDNS_RETURN_GOOD)
88+
return NULL;
89+
return pythonify_address_list(just_address_answers);
90+
}
91+
92+
93+
PyObject *
94+
get_replies_tree(struct getdns_dict *result_dict)
95+
{
96+
struct getdns_list *replies_tree;
97+
getdns_return_t ret;
98+
99+
if ((ret = getdns_dict_get_list(result_dict, "replies_tree", &replies_tree)) !=
100+
GETDNS_RETURN_GOOD)
101+
return NULL;
102+
return glist_to_plist(replies_tree);
103+
}
104+
105+
42106
struct getdns_dict *
43107
extensions_to_getdnsdict(PyDictObject *pydict)
44108
{

result.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#include <Python.h>
2+
#include <structmember.h>
3+
#include <arpa/inet.h>
4+
#include <stdio.h>
5+
#include <string.h>
6+
#include <getdns/getdns.h>
7+
#include <getdns/getdns_ext_libevent.h>
8+
#include <event2/event.h>
9+
#include <pthread.h>
10+
#include "pygetdns.h"
11+
12+
13+
int
14+
result_init(getdns_ResultObject *self, PyObject *args, PyObject *keywds)
15+
{
16+
PyObject *result_capsule;
17+
struct getdns_dict *result_dict;
18+
int status;
19+
int answer_type;
20+
char *canonical_name;
21+
22+
if (!PyArg_ParseTuple(args, "|O", &result_capsule)) {
23+
PyErr_SetString(PyExc_AttributeError, GETDNS_RETURN_INVALID_PARAMETER_TEXT);
24+
Py_DECREF(self);
25+
return -1;
26+
}
27+
if ((result_dict = PyCapsule_GetPointer(result_capsule, "result")) == NULL) {
28+
PyErr_SetString(PyExc_AttributeError, "Unable to initialize result object");
29+
Py_DECREF(self);
30+
return -1;
31+
}
32+
if ((self->replies_full = getFullResponse(result_dict)) == NULL) {
33+
Py_DECREF(self);
34+
return -1;
35+
}
36+
if ((self->replies_tree = get_replies_tree(result_dict)) == NULL) {
37+
Py_DECREF(self);
38+
return -1;
39+
}
40+
if ((status = get_status(result_dict)) == 0) {
41+
Py_DECREF(self);
42+
return -1;
43+
}
44+
self->status = PyInt_FromLong((long)status);
45+
if ((answer_type = get_answer_type(result_dict)) == 0) {
46+
Py_DECREF(self);
47+
return -1;
48+
}
49+
self->answer_type = PyInt_FromLong((long)answer_type);
50+
if ((canonical_name = get_canonical_name(result_dict)) == 0) {
51+
Py_DECREF(self);
52+
return -1;
53+
}
54+
self->canonical_name = PyString_FromString(canonical_name);
55+
if ((self->just_address_answers = get_just_address_answers(result_dict)) == NULL) {
56+
Py_DECREF(self);
57+
return -1;
58+
}
59+
60+
return 0;
61+
}
62+
63+
64+
void
65+
result_dealloc(getdns_ResultObject *self)
66+
{
67+
Py_XDECREF(self->just_address_answers);
68+
Py_XDECREF(self->answer_type);
69+
Py_XDECREF(self->status);
70+
Py_XDECREF(self->replies_tree);
71+
Py_XDECREF(self->replies_full);
72+
Py_XDECREF(self->canonical_name);
73+
self->ob_type->tp_free((PyObject *)self);
74+
}
75+
76+
77+
PyObject *
78+
result_getattro(PyObject *self, PyObject *nameobj)
79+
{
80+
Py_RETURN_NONE;
81+
}
82+
83+

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
include_dirs = [ '/usr/local/include', ],
4343
libraries = [ 'ldns', 'getdns', 'getdns_ext_event' ],
4444
library_dirs = [ '/usr/local/lib' ],
45-
sources = [ 'getdns.c', 'pygetdns_util.c', 'context.c' ],
45+
sources = [ 'getdns.c', 'pygetdns_util.c', 'context.c',
46+
'result.c' ],
4647
runtime_library_dirs = [ '/usr/local/lib' ]
4748
)
4849

0 commit comments

Comments
 (0)