GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle
*th);
+void GNUNET_MESH_tunnel_set_head(struct GNUNET_MESH_Tunnel* tunnel, void* head);
+void GNUNET_MESH_tunnel_set_tail(struct GNUNET_MESH_Tunnel* tunnel, void* tail);
+void* GNUNET_MESH_tunnel_get_head(struct GNUNET_MESH_Tunnel* tunnel);
+void* GNUNET_MESH_tunnel_get_tail(struct GNUNET_MESH_Tunnel* tunnel);
+
+void GNUNET_MESH_tunnel_set_data(struct GNUNET_MESH_Tunnel* tunnel, void* data);
+void* GNUNET_MESH_tunnel_get_data(struct GNUNET_MESH_Tunnel* tunnel);
#if 0 /* keep Emacsens' auto-indent happy */
{
/* The context of the receive-function. */
void *ctx;
+
+ /* A list, usable by application-code (for queues) */
+ void* app_head;
+ void* app_tail;
+
+ /* A pointer, usable by application-code */
+ void* app_data;
};
struct tunnel_list_element
*) th);
}
+void
+GNUNET_MESH_tunnel_set_head (struct GNUNET_MESH_Tunnel *tunnel, void *head)
+{
+ tunnel->app_head = head;
+}
+
+void
+GNUNET_MESH_tunnel_set_tail (struct GNUNET_MESH_Tunnel *tunnel, void *tail)
+{
+ tunnel->app_tail = tail;
+}
+
+void *
+GNUNET_MESH_tunnel_get_head (struct GNUNET_MESH_Tunnel *tunnel)
+{
+ return tunnel->app_head;
+}
+
+void *
+GNUNET_MESH_tunnel_get_tail (struct GNUNET_MESH_Tunnel *tunnel)
+{
+ return tunnel->app_head;
+}
+
+void
+GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
+{
+ tunnel->app_data = data;
+}
+
+void *
+GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
+{
+ return tunnel->app_data;
+}
+
+
void build_hello_message(struct GNUNET_MESH_Handle* handle,
const GNUNET_MESH_ApplicationType *stypes)
{
static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
+struct tunnel_notify_queue
+{
+ struct tunnel_notify_queue* next;
+ struct tunnel_notify_queue* prev;
+ void* cls;
+ size_t len;
+};
+
/**
* Function that frees everything from a hashmap
*/
static size_t
send_udp_to_peer_notify_callback (void *cls, size_t size, void *buf)
{
- struct GNUNET_MessageHeader *hdr = cls;
+ struct GNUNET_MESH_Tunnel** tunnel = cls;
+ GNUNET_MESH_tunnel_set_data(*tunnel, NULL);
+ struct GNUNET_MessageHeader *hdr = (struct GNUNET_MessageHeader*)(tunnel + 1);
GNUNET_assert (size >= ntohs (hdr->size));
memcpy (buf, hdr, ntohs (hdr->size));
size = ntohs(hdr->size);
GNUNET_free (cls);
+
+ if (NULL != GNUNET_MESH_tunnel_get_head(*tunnel))
+ {
+ struct tunnel_notify_queue* element = GNUNET_MESH_tunnel_get_head(*tunnel);
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(*tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(*tunnel);
+
+ GNUNET_CONTAINER_DLL_remove(head, tail, element);
+
+ GNUNET_MESH_tunnel_set_head(*tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(*tunnel, tail);
+
+ struct GNUNET_MESH_TransmitHandle* th = GNUNET_MESH_notify_transmit_ready (*tunnel,
+ GNUNET_NO,
+ 42,
+ GNUNET_TIME_relative_divide
+ (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
+ (const struct GNUNET_PeerIdentity *)
+ NULL, element->len,
+ send_udp_to_peer_notify_callback, element->cls);
+ /* save the handle */
+ GNUNET_MESH_tunnel_set_data(*tunnel, th);
+ }
+
return size;
}
len =
sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
ntohs (udp->len);
- msg = GNUNET_malloc (len);
+ struct GNUNET_MESH_Tunnel** ctunnel = GNUNET_malloc (sizeof(struct GNUNET_MESH_TUNNEL*) + len);
+ *ctunnel = tunnel;
+ msg = (struct GNUNET_MessageHeader*)(ctunnel + 1);
msg->size = htons (len);
msg->type = htons (state->type == SERVICE ? GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK : GNUNET_MESSAGE_TYPE_REMOTE_UDP_BACK);
GNUNET_HashCode *desc = (GNUNET_HashCode *) (msg + 1);
void *_udp = desc + 1;
memcpy (_udp, udp, ntohs (udp->len));
- GNUNET_MESH_notify_transmit_ready (tunnel,
- GNUNET_NO,
- 42,
- GNUNET_TIME_relative_divide
- (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
- (const struct GNUNET_PeerIdentity *)
- NULL, len,
- send_udp_to_peer_notify_callback, msg);
+ if (NULL == GNUNET_MESH_tunnel_get_data(tunnel))
+ {
+ /* No notify is pending */
+ struct GNUNET_MESH_TransmitHandle* th = GNUNET_MESH_notify_transmit_ready (tunnel,
+ GNUNET_NO,
+ 42,
+ GNUNET_TIME_relative_divide
+ (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
+ (const struct GNUNET_PeerIdentity *)
+ NULL, len,
+ send_udp_to_peer_notify_callback, ctunnel);
+ /* save the handle */
+ GNUNET_MESH_tunnel_set_data(tunnel, th);
+ }
+ else
+ {
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(tunnel);
+
+ struct tunnel_notify_queue* element = GNUNET_malloc(sizeof(struct tunnel_notify_queue));
+ element->cls = ctunnel;
+ element->len = len;
+
+ GNUNET_CONTAINER_DLL_insert_tail(head, tail, element);
+ GNUNET_MESH_tunnel_set_head(tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(tunnel, tail);
+ }
}
/**
len =
sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + pktlen;
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "len: %d\n", pktlen);
- msg = GNUNET_malloc (len);
+ struct GNUNET_MESH_Tunnel** ctunnel = GNUNET_malloc (sizeof(struct GNUNET_MESH_TUNNEL*) + len);
+ *ctunnel = tunnel;
+ msg = (struct GNUNET_MessageHeader*)(ctunnel + 1);
msg->size = htons (len);
msg->type = htons (state->type == SERVICE ? GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK : GNUNET_MESSAGE_TYPE_REMOTE_TCP_BACK);
GNUNET_HashCode *desc = (GNUNET_HashCode *) (msg + 1);
void *_tcp = desc + 1;
memcpy (_tcp, tcp, pktlen);
- GNUNET_MESH_notify_transmit_ready (tunnel,
+ if (NULL == GNUNET_MESH_tunnel_get_data(tunnel))
+ {
+ /* No notify is pending */
+ struct GNUNET_MESH_TransmitHandle* th = GNUNET_MESH_notify_transmit_ready (tunnel,
GNUNET_NO,
42,
GNUNET_TIME_relative_divide
(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
(const struct GNUNET_PeerIdentity *)NULL,
len, send_udp_to_peer_notify_callback,
- msg);
+ ctunnel);
+ /* save the handle */
+ GNUNET_MESH_tunnel_set_data(tunnel, th);
+ }
+ else
+ {
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(tunnel);
+
+ struct tunnel_notify_queue* element = GNUNET_malloc(sizeof(struct tunnel_notify_queue));
+ element->cls = ctunnel;
+ element->len = len;
+
+ GNUNET_CONTAINER_DLL_insert_tail(head, tail, element);
+ }
}
struct GNUNET_CONTAINER_MultiHashMap* hashmap;
static struct GNUNET_CONTAINER_Heap *heap;
+struct tunnel_notify_queue
+{
+ struct tunnel_notify_queue* next;
+ struct tunnel_notify_queue* prev;
+ size_t len;
+ void* cls;
+};
+
/**
* If there are at least this many address-mappings, old ones will be removed
*/
send_pkt_to_peer_notify_callback (void *cls, size_t size, void *buf)
{
struct GNUNET_MESH_Tunnel **tunnel = cls;
+ GNUNET_MESH_tunnel_set_data(*tunnel, NULL);
struct GNUNET_MessageHeader *hdr =
(struct GNUNET_MessageHeader *) (tunnel + 1);
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "send_pkt_to_peer_notify_callback: buf = %x; size = %u;\n", buf, size);
size = ntohs(hdr->size);
GNUNET_free (cls);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent!\n");
+
+ if (NULL != GNUNET_MESH_tunnel_get_head(*tunnel))
+ {
+ struct tunnel_notify_queue* element = GNUNET_MESH_tunnel_get_head(*tunnel);
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(*tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(*tunnel);
+
+ GNUNET_CONTAINER_DLL_remove(head, tail, element);
+
+ GNUNET_MESH_tunnel_set_head(*tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(*tunnel, tail);
+
+ struct GNUNET_MESH_TransmitHandle* th = GNUNET_MESH_notify_transmit_ready (*tunnel,
+ GNUNET_NO,
+ 42,
+ GNUNET_TIME_relative_divide
+ (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
+ (const struct GNUNET_PeerIdentity *)
+ NULL, element->len,
+ send_pkt_to_peer_notify_callback, element->cls);
+ /* save the handle */
+ GNUNET_MESH_tunnel_set_data(*tunnel, th);
+ }
+
return size;
}
GNUNET_assert(NULL != tunnel);
GNUNET_assert(NULL != *tunnel);
- GNUNET_MESH_notify_transmit_ready (*tunnel,
- GNUNET_NO,
- 42,
- GNUNET_TIME_relative_divide(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
- (const struct GNUNET_PeerIdentity *)NULL,
- ntohs(hdr->size),
- send_pkt_to_peer_notify_callback,
- cls);
+ if (NULL == GNUNET_MESH_tunnel_get_data(*tunnel))
+ {
+ struct GNUNET_MESH_TransmitHandle* th = GNUNET_MESH_notify_transmit_ready (*tunnel,
+ GNUNET_NO,
+ 42,
+ GNUNET_TIME_relative_divide(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
+ (const struct GNUNET_PeerIdentity *)NULL,
+ ntohs(hdr->size),
+ send_pkt_to_peer_notify_callback,
+ cls);
+ GNUNET_MESH_tunnel_set_data(*tunnel, th);
+ }
+ else
+ {
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(*tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(*tunnel);
+ struct tunnel_notify_queue* element = GNUNET_malloc(sizeof *element);
+
+ element->cls = cls;
+ element->len = ntohs(hdr->size);
+
+ GNUNET_CONTAINER_DLL_insert_tail(head, tail, element);
+
+ GNUNET_MESH_tunnel_set_head(*tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(*tunnel, tail);
+ }
}
/**
#include "platform.h"
#include "gnunet_getopt_lib.h"
#include "gnunet_service_lib.h"
+#include <gnunet_constants.h>
#include "gnunet_network_lib.h"
#include "gnunet_os_lib.h"
#include "gnunet-service-dns-p.h"
struct GNUNET_DHT_GetHandle* handle;
};
+struct tunnel_notify_queue
+{
+ struct tunnel_notify_queue* next;
+ struct tunnel_notify_queue* prev;
+ void* cls;
+ size_t len;
+ GNUNET_CONNECTION_TransmitReadyNotify cb;
+};
+
/**
* Hijack all outgoing DNS-Traffic but for traffic leaving "our" port.
*/
GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
struct GNUNET_MessageHeader *hdr = buf;
uint32_t *sz = cls;
- struct dns_pkt *dns = (struct dns_pkt *) (sz + 1);
+ struct GNUNET_MESH_Tunnel **tunnel = (struct GNUNET_MESH_Tunnel**)(sz+1);
+ struct dns_pkt *dns = (struct dns_pkt *) (tunnel + 1);
hdr->type = htons (GNUNET_MESSAGE_TYPE_REMOTE_ANSWER_DNS);
hdr->size = htons (*sz + sizeof (struct GNUNET_MessageHeader));
memcpy (hdr + 1, dns, *sz);
GNUNET_free (cls);
+
+ if (NULL != GNUNET_MESH_tunnel_get_head(*tunnel))
+ {
+ struct tunnel_notify_queue* element = GNUNET_MESH_tunnel_get_head(*tunnel);
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(*tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(*tunnel);
+
+ GNUNET_CONTAINER_DLL_remove(head, tail, element);
+
+ GNUNET_MESH_tunnel_set_head(*tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(*tunnel, tail);
+ struct GNUNET_MESH_TransmitHandle* th = GNUNET_MESH_notify_transmit_ready (*tunnel,
+ GNUNET_NO,
+ 42,
+ GNUNET_TIME_relative_divide
+ (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
+ (const struct GNUNET_PeerIdentity *)
+ NULL, element->len,
+ element->cb, element->cls);
+ /* save the handle */
+ GNUNET_MESH_tunnel_set_data(*tunnel, th);
+ }
return ntohs (hdr->size);
}
mesh_send (void *cls, size_t size, void *buf)
{
struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
+ GNUNET_MESH_tunnel_set_data(cls_->tunnel, NULL);
GNUNET_assert(cls_->hdr.size <= size);
cls_->hdr.size = htons(cls_->hdr.size);
memcpy(buf, &cls_->hdr, size);
+
+ if (NULL != GNUNET_MESH_tunnel_get_head(cls_->tunnel))
+ {
+ struct tunnel_notify_queue* element = GNUNET_MESH_tunnel_get_head(cls_->tunnel);
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(cls_->tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(cls_->tunnel);
+
+ GNUNET_CONTAINER_DLL_remove(head, tail, element);
+
+ GNUNET_MESH_tunnel_set_head(cls_->tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(cls_->tunnel, tail);
+ struct GNUNET_MESH_TransmitHandle* th = GNUNET_MESH_notify_transmit_ready (cls_->tunnel,
+ GNUNET_NO,
+ 42,
+ GNUNET_TIME_relative_divide
+ (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
+ (const struct GNUNET_PeerIdentity *)
+ NULL, element->len,
+ element->cb, element->cls);
+ /* save the handle */
+ GNUNET_MESH_tunnel_set_data(cls_->tunnel, th);
+ }
+
+ GNUNET_free(cls);
return size;
}
-void mesh_connect (void* cls, const struct GNUNET_PeerIdentity* peer, const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused))) {
- if (NULL == peer) return;
- struct tunnel_cls *cls_ = (struct tunnel_cls*)cls;
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected to peer %s, sending query with id %d\n", GNUNET_i2s(peer), ntohs(cls_->dns.s.id));
-
- GNUNET_MESH_notify_transmit_ready(cls_->tunnel,
- GNUNET_YES,
- 42,
- GNUNET_TIME_UNIT_MINUTES,
- NULL,
- cls_->hdr.size,
- mesh_send,
- cls);
+void
+mesh_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_TRANSPORT_ATS_Information *atsi
+ __attribute__ ((unused)))
+{
+ if (NULL == peer)
+ return;
+ struct tunnel_cls *cls_ = (struct tunnel_cls *) cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connected to peer %s, sending query with id %d\n",
+ GNUNET_i2s (peer), ntohs (cls_->dns.s.id));
+
+ if (NULL == GNUNET_MESH_tunnel_get_data (cls_->tunnel))
+ {
+ struct GNUNET_MESH_TransmitHandle *th =
+ GNUNET_MESH_notify_transmit_ready (cls_->tunnel,
+ GNUNET_YES,
+ 42,
+ GNUNET_TIME_UNIT_MINUTES,
+ NULL,
+ cls_->hdr.size,
+ mesh_send,
+ cls);
+
+ GNUNET_MESH_tunnel_set_data (cls_->tunnel, th);
+ }
+ else
+ {
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(cls_->tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(cls_->tunnel);
+
+ struct tunnel_notify_queue* element = GNUNET_malloc(sizeof(struct tunnel_notify_queue));
+ element->cls = cls;
+ element->len = cls_->hdr.size;
+ element->cb = mesh_send;
+
+ GNUNET_CONTAINER_DLL_insert_tail(head, tail, element);
+ GNUNET_MESH_tunnel_set_head(cls_->tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(cls_->tunnel, tail);
+ }
}
* Read a response-packet of the UDP-Socket
*/
static void
-read_response (void *cls __attribute__((unused)), const struct GNUNET_SCHEDULER_TaskContext *tc)
+read_response (void *cls
+ __attribute__ ((unused)),
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct sockaddr_in addr;
socklen_t addrlen = sizeof (addr);
{
if (query_states[dns->s.id].tunnel != NULL)
{
- uint32_t *c = GNUNET_malloc(4 + r);
+ /* This response should go through a tunnel */
+ uint32_t *c = GNUNET_malloc (4 + sizeof(struct GNUNET_MESH_Tunnel*) + r);
*c = r;
- memcpy(c+1, dns, r);
- GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel,
- GNUNET_YES,
- 32,
- GNUNET_TIME_UNIT_MINUTES,
- NULL, r + sizeof(struct GNUNET_MessageHeader), mesh_send_response, c);
+ struct GNUNET_MESH_Tunnel** t = (struct GNUNET_MESH_Tunnel**)(c + 1);
+ *t = query_states[dns->s.id].tunnel;
+ memcpy (t + 1, dns, r);
+ if (NULL ==
+ GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel))
+ {
+ struct GNUNET_MESH_TransmitHandle *th =
+ GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel,
+ GNUNET_YES,
+ 32,
+ GNUNET_TIME_UNIT_MINUTES,
+ NULL,
+ r +
+ sizeof (struct
+ GNUNET_MessageHeader),
+ mesh_send_response, c);
+ GNUNET_MESH_tunnel_set_data (query_states[dns->s.id].tunnel,
+ th);
+ }
+ else
+ {
+ struct tunnel_notify_queue* head = GNUNET_MESH_tunnel_get_head(query_states[dns->s.id].tunnel);
+ struct tunnel_notify_queue* tail = GNUNET_MESH_tunnel_get_tail(query_states[dns->s.id].tunnel);
+
+ struct tunnel_notify_queue* element = GNUNET_malloc(sizeof(struct tunnel_notify_queue));
+ element->cls = c;
+ element->len = r+sizeof(struct GNUNET_MessageHeader);
+ element->cb = mesh_send_response;
+
+ GNUNET_CONTAINER_DLL_insert_tail(head, tail, element);
+ GNUNET_MESH_tunnel_set_head(query_states[dns->s.id].tunnel, head);
+ GNUNET_MESH_tunnel_set_tail(query_states[dns->s.id].tunnel, tail);
+ }
}
else
{
GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer);
- GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].
- client, len,
+ GNUNET_SERVER_notify_transmit_ready (query_states
+ [dns->s.id].client, len,
GNUNET_TIME_UNIT_FOREVER_REL,
&send_answer,
- query_states[dns->s.id].
- client);
+ query_states[dns->s.
+ id].client);
}
}
}