aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api_address_lookup.c
blob: 1c0cf734055515481dada589083bf85229e3233f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "platform.h"
#include "gnunet_client_lib.h"
#include "gnunet_arm_service.h"
#include "gnunet_hello_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_server_lib.h"
#include "gnunet_time_lib.h"
#include "gnunet_transport_service.h"
#include "transport.h"

// FIXME: document
struct AddressLookUpCB {
	GNUNET_TRANSPORT_AddressLookUpCallback cb;
	void *cls;
	struct GNUNET_TIME_Absolute timeout;
	struct GNUNET_CLIENT_Connection *client;
};


// FIXME: document
static void
address_response_processor(void *cls, const struct
                           GNUNET_MessageHeader * msg)
{
	struct AddressLookUpCB *alucb = cls;
	const char *address;
	uint16_t size;

	if (msg == NULL)
	{
		/* timeout */
		alucb->cb (alucb->cls, NULL);
		GNUNET_CLIENT_disconnect (alucb->client);
		GNUNET_free (alucb);
		return;
	}
	size = ntohs(msg->size);
	if (size == sizeof(struct GNUNET_MessageHeader))
	{
		/* last reply */
		address = NULL;
	}
	else
	{
		address = (const char*) &msg[1];
		if (address[size - sizeof(struct GNUNET_MessageHeader) - 1] != '\0')
		{
			/* invalid reply */
			GNUNET_break_op (0);
			alucb->cb (alucb->cls, NULL);
			GNUNET_CLIENT_disconnect (alucb->client);
			GNUNET_free (alucb);
			return;
		}
		else
		{
			/* expect more replies */
			GNUNET_CLIENT_receive (alucb->client, &address_response_processor, alucb,
								   GNUNET_TIME_absolute_get_remaining (alucb->timeout));
		}
	}
	alucb->cb (alucb->cls, address);
	if (address == NULL)
	{
		/* done! */
		GNUNET_CLIENT_disconnect (alucb->client);
		GNUNET_free (alucb);
	}
}

void
GNUNET_TRANSPORT_address_lookup (struct GNUNET_SCHEDULER_Handle *sched,
		                         const struct GNUNET_CONFIGURATION_Handle *cfg,
                                 const char * address,
                                 size_t addressLen,
                                 const char * nameTrans,
		                         struct GNUNET_TIME_Relative timeout,
		                         GNUNET_TRANSPORT_AddressLookUpCallback aluc,
		                         void *aluc_cls)
{
	size_t len = sizeof (struct AddressLookupMessage) + addressLen + strlen (nameTrans) + 1;
	struct AddressLookupMessage *msg;
	struct GNUNET_TIME_Absolute abs_timeout;
	struct AddressLookUpCB *aluCB;
	struct GNUNET_CLIENT_Connection *client;

	if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
	{
		GNUNET_break (0);
		aluc (aluc_cls, NULL);
		return;
	}
	client = GNUNET_CLIENT_connect (sched, "transport", cfg);
	if (client == NULL)
	{
		aluc (aluc_cls, NULL);
		return;
	}
	abs_timeout = GNUNET_TIME_relative_to_absolute(timeout);
	msg = GNUNET_malloc (len);
	msg->header->size = htons (len);
	msg->header->type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP);
	msg->timeout = GNUNET_TIME_absolute_hton(abs_timeout);
	msg->addrlen = htonl (addressLen);
	char *addrbuf = (char*) &msg[1];
	memcpy (addrbuf, address, addressLen);
	char *tbuf = &addrbuf[addressLen];
	memcpy (tbuf, nameTrans, strlen(nameTrans) + 1);
	aluCB = GNUNET_malloc (sizeof (struct AddressLookUpCB));
	aluCB->cb = aluc;
	aluCB->cb_cls = aluc_cls;
	aluCB->timeout = abs_timeout;
	aluCB->client = client;
	GNUNET_CLIENT_transmit_and_get_response(client, msg->header, timeout, GNUNET_YES, &address_response_processor, aluCB);
    GNUNET_free(msg);
}