diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-01 23:39:24 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-01 23:39:24 +0000 |
commit | 402a25de1ef93133c9879706071081405ade61f6 (patch) | |
tree | 96763797649dd4bff0b7f8b2010a0589f8179dcb /src/dns/dns_api.c | |
parent | 3e73780b201b600dd8dd8725f5a628d62d9c4f51 (diff) | |
download | gnunet-402a25de1ef93133c9879706071081405ade61f6.tar.gz gnunet-402a25de1ef93133c9879706071081405ade61f6.zip |
first quick hack to extract an initial DNS service API
Diffstat (limited to 'src/dns/dns_api.c')
-rw-r--r-- | src/dns/dns_api.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/src/dns/dns_api.c b/src/dns/dns_api.c new file mode 100644 index 000000000..90b4a8f42 --- /dev/null +++ b/src/dns/dns_api.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file vpn/gnunet-daemon-vpn-dns.c | ||
23 | * @brief | ||
24 | * @author Philipp Toelke | ||
25 | */ | ||
26 | #include <platform.h> | ||
27 | #include <gnunet_common.h> | ||
28 | #include <gnunet_client_lib.h> | ||
29 | #include <gnunet_os_lib.h> | ||
30 | #include <gnunet_mesh_service.h> | ||
31 | #include <gnunet_protocols.h> | ||
32 | #include <gnunet_server_lib.h> | ||
33 | #include <gnunet_container_lib.h> | ||
34 | #include <block_dns.h> | ||
35 | |||
36 | #include "gnunet_dns_service.h" | ||
37 | |||
38 | |||
39 | struct GNUNET_DNS_Handle | ||
40 | { | ||
41 | struct query_packet_list *head; | ||
42 | struct query_packet_list *tail; | ||
43 | struct GNUNET_CLIENT_Connection *dns_connection; | ||
44 | unsigned char restart_hijack; | ||
45 | |||
46 | struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle; | ||
47 | |||
48 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
49 | |||
50 | GNUNET_SCHEDULER_Task process_answer_cb; | ||
51 | |||
52 | void *process_answer_cb_cls; | ||
53 | }; | ||
54 | |||
55 | |||
56 | /** | ||
57 | * Callback called by notify_transmit_ready; sends dns-queries or rehijack-messages | ||
58 | * to the service-dns | ||
59 | * {{{ | ||
60 | */ | ||
61 | size_t | ||
62 | send_query (void *cls GNUNET_UNUSED, size_t size, void *buf) | ||
63 | { | ||
64 | struct GNUNET_DNS_Handle *h = cls; | ||
65 | |||
66 | size_t len; | ||
67 | |||
68 | h->dns_transmit_handle = NULL; | ||
69 | |||
70 | /* | ||
71 | * Send the rehijack-message | ||
72 | */ | ||
73 | if (h->restart_hijack == 1) | ||
74 | { | ||
75 | h->restart_hijack = 0; | ||
76 | /* | ||
77 | * The message is just a header | ||
78 | */ | ||
79 | GNUNET_assert (sizeof (struct GNUNET_MessageHeader) <= size); | ||
80 | struct GNUNET_MessageHeader *hdr = buf; | ||
81 | |||
82 | len = sizeof (struct GNUNET_MessageHeader); | ||
83 | hdr->size = htons (len); | ||
84 | hdr->type = htons (GNUNET_MESSAGE_TYPE_REHIJACK); | ||
85 | } | ||
86 | else if (h->head != NULL) | ||
87 | { | ||
88 | struct query_packet_list *query = h->head; | ||
89 | |||
90 | len = ntohs (query->pkt.hdr.size); | ||
91 | |||
92 | GNUNET_assert (len <= size); | ||
93 | |||
94 | memcpy (buf, &query->pkt.hdr, len); | ||
95 | |||
96 | GNUNET_CONTAINER_DLL_remove (h->head, h->tail, query); | ||
97 | |||
98 | GNUNET_free (query); | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | GNUNET_break (0); | ||
103 | len = 0; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * Check whether more data is to be sent | ||
108 | */ | ||
109 | if (h->head != NULL) | ||
110 | { | ||
111 | h->dns_transmit_handle = | ||
112 | GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, | ||
113 | ntohs (h->head->pkt.hdr.size), | ||
114 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
115 | GNUNET_YES, &send_query, h); | ||
116 | } | ||
117 | else if (h->restart_hijack == 1) | ||
118 | { | ||
119 | h->dns_transmit_handle = | ||
120 | GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, | ||
121 | sizeof (struct | ||
122 | GNUNET_MessageHeader), | ||
123 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
124 | GNUNET_YES, &send_query, h); | ||
125 | } | ||
126 | |||
127 | return len; | ||
128 | } | ||
129 | |||
130 | /* }}} */ | ||
131 | |||
132 | |||
133 | |||
134 | /** | ||
135 | * This receives packets from the service-dns and schedules process_answer to | ||
136 | * handle it | ||
137 | */ | ||
138 | static void | ||
139 | dns_answer_handler (void *cls, | ||
140 | const struct GNUNET_MessageHeader *msg) | ||
141 | { | ||
142 | struct GNUNET_DNS_Handle *h = cls; | ||
143 | |||
144 | /* the service disconnected, reconnect after short wait */ | ||
145 | if (msg == NULL) | ||
146 | { | ||
147 | if (h->dns_transmit_handle != NULL) | ||
148 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->dns_transmit_handle); | ||
149 | h->dns_transmit_handle = NULL; | ||
150 | GNUNET_CLIENT_disconnect (h->dns_connection, GNUNET_NO); | ||
151 | h->dns_connection = NULL; | ||
152 | #if 0 | ||
153 | h->conn_task = | ||
154 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
155 | &connect_to_service_dns, h); | ||
156 | #endif | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | /* the service did something strange, reconnect immediately */ | ||
161 | if (msg->type != htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS)) | ||
162 | { | ||
163 | GNUNET_break (0); | ||
164 | GNUNET_CLIENT_disconnect (h->dns_connection, GNUNET_NO); | ||
165 | h->dns_connection = NULL; | ||
166 | #if 0 | ||
167 | conn_task = GNUNET_SCHEDULER_add_now (&connect_to_service_dns, NULL); | ||
168 | #endif | ||
169 | return; | ||
170 | } | ||
171 | void *pkt = GNUNET_malloc (ntohs (msg->size)); | ||
172 | |||
173 | memcpy (pkt, msg, ntohs (msg->size)); | ||
174 | |||
175 | GNUNET_SCHEDULER_add_now (h->process_answer_cb, pkt); | ||
176 | GNUNET_CLIENT_receive (h->dns_connection, &dns_answer_handler, h, | ||
177 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
178 | } | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Connect to the service-dns | ||
183 | */ | ||
184 | struct GNUNET_DNS_Handle * | ||
185 | GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
186 | GNUNET_SCHEDULER_Task cb, | ||
187 | void *cb_cls) | ||
188 | { | ||
189 | struct GNUNET_DNS_Handle *h; | ||
190 | |||
191 | h = GNUNET_malloc (sizeof (struct GNUNET_DNS_Handle)); | ||
192 | h->cfg = cfg; | ||
193 | h->process_answer_cb = cb; | ||
194 | h->process_answer_cb_cls = cb_cls; | ||
195 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to service-dns\n"); | ||
196 | h->dns_connection = GNUNET_CLIENT_connect ("dns", h->cfg); | ||
197 | /* This would most likely be a misconfiguration */ | ||
198 | GNUNET_assert (NULL != h->dns_connection); | ||
199 | GNUNET_CLIENT_receive (h->dns_connection, | ||
200 | &dns_answer_handler, NULL, | ||
201 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
202 | /* If a packet is already in the list, schedule to send it */ | ||
203 | if (h->dns_transmit_handle == NULL && h->head != NULL) | ||
204 | h->dns_transmit_handle = | ||
205 | GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, | ||
206 | ntohs (h->head->pkt.hdr.size), | ||
207 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
208 | GNUNET_YES, &send_query, h); | ||
209 | else if (h->dns_transmit_handle == NULL && h->restart_hijack == 1) | ||
210 | { | ||
211 | h->dns_transmit_handle = | ||
212 | GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, | ||
213 | sizeof (struct | ||
214 | GNUNET_MessageHeader), | ||
215 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
216 | GNUNET_YES, &send_query, NULL); | ||
217 | } | ||
218 | return h; | ||
219 | } | ||
220 | |||
221 | |||
222 | void | ||
223 | GNUNET_DNS_restart_hijack (struct GNUNET_DNS_Handle *h) | ||
224 | { | ||
225 | h->restart_hijack = 1; | ||
226 | if (NULL != h->dns_connection && h->dns_transmit_handle == NULL) | ||
227 | h->dns_transmit_handle = | ||
228 | GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, | ||
229 | sizeof (struct | ||
230 | GNUNET_MessageHeader), | ||
231 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
232 | GNUNET_YES, &send_query, h); | ||
233 | } | ||
234 | |||
235 | |||
236 | /** | ||
237 | * FIXME: we should not expost our internal structures like this. | ||
238 | * Just a quick initial hack. | ||
239 | */ | ||
240 | void | ||
241 | GNUNET_DNS_queue_request (struct GNUNET_DNS_Handle *h, | ||
242 | struct query_packet_list *q) | ||
243 | { | ||
244 | GNUNET_CONTAINER_DLL_insert_tail (h->head, h->tail, q); | ||
245 | if (h->dns_connection != NULL && h->dns_transmit_handle == NULL) | ||
246 | h->dns_transmit_handle = | ||
247 | GNUNET_CLIENT_notify_transmit_ready (h->dns_connection, ntohs(q->pkt.hdr.size), | ||
248 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
249 | GNUNET_YES, &send_query, | ||
250 | h); | ||
251 | } | ||
252 | |||
253 | |||
254 | void | ||
255 | GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *h) | ||
256 | { | ||
257 | if (h->dns_connection != NULL) | ||
258 | { | ||
259 | GNUNET_CLIENT_disconnect (h->dns_connection, GNUNET_NO); | ||
260 | h->dns_connection = NULL; | ||
261 | } | ||
262 | GNUNET_free (h); | ||
263 | } | ||