GNUnet  0.10.x
dns_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2012, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include "gnunet_dns_service.h"
28 #include "dns.h"
29 
30 
39 
43  uint64_t request_id;
44 
48  uint32_t generation;
49 };
50 
51 
60 
65 
70 
74  void *rh_cls;
75 
80 
84  uint32_t generation;
85 
89  enum GNUNET_DNS_Flags flags;
90 
95  unsigned int pending_requests;
96 };
97 
98 
105 static void
106 reconnect(void *cls);
107 
108 
114 static void
116 {
117  if (NULL != dh->mq)
118  {
119  GNUNET_MQ_destroy(dh->mq);
120  dh->mq = NULL;
121  }
122  dh->reconnect_task =
124  &reconnect,
125  dh);
126 }
127 
128 
137 static void
139  enum GNUNET_MQ_Error error)
140 {
141  struct GNUNET_DNS_Handle *dh = cls;
142 
143  force_reconnect(dh);
144 }
145 
146 
147 
155 static int
156 check_request(void *cls,
157  const struct GNUNET_DNS_Request *req)
158 {
159  if (0 != ntohl(req->reserved))
160  {
161  GNUNET_break(0);
162  return GNUNET_SYSERR;
163  }
164  return GNUNET_OK;
165 }
166 
167 
175 static void
176 handle_request(void *cls,
177  const struct GNUNET_DNS_Request *req)
178 {
179  struct GNUNET_DNS_Handle *dh = cls;
180  size_t payload_length = ntohs(req->header.size) - sizeof(*req);
181  struct GNUNET_DNS_RequestHandle *rh;
182 
184  rh->dh = dh;
185  rh->request_id = req->request_id;
186  rh->generation = dh->generation;
187  dh->pending_requests++;
188  dh->rh(dh->rh_cls,
189  rh,
190  payload_length,
191  (const char*)&req[1]);
192 }
193 
194 
200 static void
201 reconnect(void *cls)
202 {
203  struct GNUNET_DNS_Handle *dh = cls;
204  struct GNUNET_MQ_MessageHandler handlers[] = {
207  struct GNUNET_DNS_Request,
208  dh),
210  };
211  struct GNUNET_MQ_Envelope *env;
212  struct GNUNET_DNS_Register *msg;
213 
214  dh->reconnect_task = NULL;
215  dh->mq = GNUNET_CLIENT_connect(dh->cfg,
216  "dns",
217  handlers,
219  dh);
220  if (NULL == dh->mq)
221  return;
222  dh->generation++;
223  env = GNUNET_MQ_msg(msg,
225  msg->flags = htonl(dh->flags);
226  GNUNET_MQ_send(dh->mq,
227  env);
228 }
229 
230 
241 void
243 {
244  struct GNUNET_MQ_Envelope *env;
245  struct GNUNET_DNS_Response *resp;
246 
247  GNUNET_assert(0 < rh->dh->pending_requests--);
248  if (rh->generation != rh->dh->generation)
249  {
250  GNUNET_free(rh);
251  return;
252  }
253  env = GNUNET_MQ_msg(resp,
255  resp->drop_flag = htonl(1);
256  resp->request_id = rh->request_id;
257  GNUNET_MQ_send(rh->dh->mq,
258  env);
259  GNUNET_free(rh);
260 }
261 
262 
269 void
271 {
272  struct GNUNET_MQ_Envelope *env;
273  struct GNUNET_DNS_Response *resp;
274 
275  GNUNET_assert(0 < rh->dh->pending_requests--);
276  if (rh->generation != rh->dh->generation)
277  {
278  GNUNET_free(rh);
279  return;
280  }
281  env = GNUNET_MQ_msg(resp,
283  resp->request_id = rh->request_id;
284  resp->drop_flag = htonl(0);
285  GNUNET_MQ_send(rh->dh->mq,
286  env);
287  GNUNET_free(rh);
288 }
289 
290 
300 void
302  uint16_t reply_length,
303  const char *reply)
304 {
305  struct GNUNET_MQ_Envelope *env;
306  struct GNUNET_DNS_Response *resp;
307 
308  GNUNET_assert(0 < rh->dh->pending_requests--);
309  if (rh->generation != rh->dh->generation)
310  {
311  GNUNET_free(rh);
312  return;
313  }
314  if (reply_length + sizeof(struct GNUNET_DNS_Response)
316  {
317  GNUNET_break(0);
318  GNUNET_free(rh);
319  return;
320  }
321  env = GNUNET_MQ_msg_extra(resp,
322  reply_length,
324  resp->drop_flag = htonl(2);
325  resp->request_id = rh->request_id;
326  GNUNET_memcpy(&resp[1],
327  reply,
328  reply_length);
329  GNUNET_MQ_send(rh->dh->mq,
330  env);
331  GNUNET_free(rh);
332 }
333 
334 
344 struct GNUNET_DNS_Handle *
346  enum GNUNET_DNS_Flags flags,
348  void *rh_cls)
349 {
350  struct GNUNET_DNS_Handle *dh;
351 
352  dh = GNUNET_new(struct GNUNET_DNS_Handle);
353  dh->cfg = cfg;
354  dh->flags = flags;
355  dh->rh = rh;
356  dh->rh_cls = rh_cls;
358  return dh;
359 }
360 
361 
367 void
369 {
370  if (NULL != dh->mq)
371  {
372  GNUNET_MQ_destroy(dh->mq);
373  dh->mq = NULL;
374  }
375  if (NULL != dh->reconnect_task)
376  {
378  dh->reconnect_task = NULL;
379  }
380  /* make sure client has no pending requests left over! */
381  GNUNET_break(0 == dh->pending_requests);
382  GNUNET_free(dh);
383 }
384 
385 /* end of dns_api.c */
uint32_t flags
NBO encoding of enum GNUNET_DNS_Flags for the client.
Definition: dns.h:44
static void reconnect(void *cls)
Reconnect to the DNS service.
Definition: dns_api.c:201
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
void * rh_cls
Closure for rh.
Definition: dns_api.c:74
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:900
enum GNUNET_DNS_Flags flags
Flags for events we care about.
Definition: dns_api.c:89
GNUNET_MQ_Error
Error codes for the queue.
uint32_t generation
Re-connect counter, to make sure we did not reconnect in the meantime.
Definition: dns_api.c:48
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
uint32_t generation
Re-connect counter, to make sure we did not reconnect in the meantime.
Definition: dns_api.c:84
struct GNUNET_MQ_Handle * mq
Connection to DNS service, or NULL.
Definition: dns_api.c:59
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_DNS_Handle * dh
Handle to DNS API.
Definition: dns_api.c:38
static void force_reconnect(struct GNUNET_DNS_Handle *dh)
Drop the existing connection and reconnect to the DNS service.
Definition: dns_api.c:115
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
Message from client to DNS service: here is my reply.
Definition: dns.h:74
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_SCHEDULER_Task * reconnect_task
Task to reconnect to the service.
Definition: dns_api.c:79
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST.
Definition: dns.h:55
static void handle_request(void *cls, const struct GNUNET_DNS_Request *req)
This receives packets from the DNS service and calls the application to handle it.
Definition: dns_api.c:176
static int check_request(void *cls, const struct GNUNET_DNS_Request *req)
This receives packets from the DNS service and calls the application to check that the request is wel...
Definition: dns_api.c:156
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
void GNUNET_DNS_disconnect(struct GNUNET_DNS_Handle *dh)
Disconnect from the DNS service.
Definition: dns_api.c:368
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT
Initial message from client to DNS service for registration.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
Message from client to DNS service to register itself.
Definition: dns.h:35
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
unsigned int pending_requests
Number of GNUNET_DNS_RequestHandles we have outstanding.
Definition: dns_api.c:95
uint64_t request_id
Unique request ID.
Definition: dns.h:65
Message handler for a specific message type.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
DNS handle.
Definition: dns_api.c:55
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
uint64_t request_id
Stored in network byte order (as for us, it is just a random number).
Definition: dns_api.c:43
uint64_t request_id
Unique request ID.
Definition: dns.h:88
uint32_t reserved
Always zero.
Definition: dns.h:60
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
void(* GNUNET_DNS_RequestHandler)(void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request)
Signature of a function that is called whenever the DNS service encounters a DNS request and needs to...
struct GNUNET_DNS_Handle * GNUNET_DNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_DNS_Flags flags, GNUNET_DNS_RequestHandler rh, void *rh_cls)
Connect to the service-dns.
Definition: dns_api.c:345
Handle to a message queue.
Definition: mq.c:84
GNUNET_DNS_RequestHandler rh
Function to call to get replies.
Definition: dns_api.c:69
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
Definition: dns_api.c:64
void GNUNET_DNS_request_answer(struct GNUNET_DNS_RequestHandle *rh, uint16_t reply_length, const char *reply)
If a GNUNET_DNS_RequestHandler calls this function, the request is supposed to be answered with the d...
Definition: dns_api.c:301
Handle to identify an individual DNS request.
Definition: dns_api.c:34
configuration data
Definition: configuration.c:83
void GNUNET_DNS_request_forward(struct GNUNET_DNS_RequestHandle *rh)
If a GNUNET_DNS_RequestHandler calls this function, the request is given to other clients or the glob...
Definition: dns_api.c:242
Message from DNS service to client: please handle a request.
Definition: dns.h:51
Entry in list of pending tasks.
Definition: scheduler.c:131
void GNUNET_DNS_request_drop(struct GNUNET_DNS_RequestHandle *rh)
If a GNUNET_DNS_RequestHandler calls this function, the request is to be dropped and no response shou...
Definition: dns_api.c:270
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:821
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:351
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: dns_api.c:138
GNUNET_DNS_Flags
Flags that specify when to call the client&#39;s handler.
uint32_t drop_flag
Zero to drop, 1 for no change (no payload), 2 for update (message has payload).
Definition: dns.h:83
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
IPC messages between DNS API and DNS service.
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956