diff options
Diffstat (limited to 'src/dv/dv_api.c')
-rw-r--r-- | src/dv/dv_api.c | 157 |
1 files changed, 129 insertions, 28 deletions
diff --git a/src/dv/dv_api.c b/src/dv/dv_api.c index a2d9f1762..29b6dcca3 100644 --- a/src/dv/dv_api.c +++ b/src/dv/dv_api.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "gnunet_time_lib.h" | 36 | #include "gnunet_time_lib.h" |
37 | #include "gnunet_dv_service.h" | 37 | #include "gnunet_dv_service.h" |
38 | #include "dv.h" | 38 | #include "dv.h" |
39 | #include "../transport/plugin_transport.h" | ||
39 | 40 | ||
40 | 41 | ||
41 | struct PendingMessages | 42 | struct PendingMessages |
@@ -109,12 +110,21 @@ struct GNUNET_DV_Handle | |||
109 | */ | 110 | */ |
110 | void *receive_cls; | 111 | void *receive_cls; |
111 | 112 | ||
113 | /** | ||
114 | * Current unique ID | ||
115 | */ | ||
116 | uint32_t uid_gen; | ||
117 | |||
118 | /** | ||
119 | * Hashmap containing outstanding send requests awaiting confirmation. | ||
120 | */ | ||
121 | struct GNUNET_CONTAINER_MultiHashMap *send_callbacks; | ||
122 | |||
112 | }; | 123 | }; |
113 | 124 | ||
114 | 125 | ||
115 | struct StartContext | 126 | struct StartContext |
116 | { | 127 | { |
117 | |||
118 | /** | 128 | /** |
119 | * Start message | 129 | * Start message |
120 | */ | 130 | */ |
@@ -126,6 +136,37 @@ struct StartContext | |||
126 | struct GNUNET_DV_Handle *handle; | 136 | struct GNUNET_DV_Handle *handle; |
127 | }; | 137 | }; |
128 | 138 | ||
139 | struct SendCallbackContext | ||
140 | { | ||
141 | /** | ||
142 | * The continuation to call once a message is confirmed sent (or failed) | ||
143 | */ | ||
144 | GNUNET_TRANSPORT_TransmitContinuation cont; | ||
145 | |||
146 | /** | ||
147 | * Closure to call with send continuation. | ||
148 | */ | ||
149 | void *cont_cls; | ||
150 | |||
151 | /** | ||
152 | * Target of the message. | ||
153 | */ | ||
154 | struct GNUNET_PeerIdentity target; | ||
155 | }; | ||
156 | |||
157 | /** | ||
158 | * Convert unique ID to hash code. | ||
159 | * | ||
160 | * @param uid unique ID to convert | ||
161 | * @param hash set to uid (extended with zeros) | ||
162 | */ | ||
163 | static void | ||
164 | hash_from_uid (uint32_t uid, | ||
165 | GNUNET_HashCode *hash) | ||
166 | { | ||
167 | memset (hash, 0, sizeof(GNUNET_HashCode)); | ||
168 | *((uint32_t*)hash) = uid; | ||
169 | } | ||
129 | 170 | ||
130 | /** | 171 | /** |
131 | * Try to (re)connect to the dv service. | 172 | * Try to (re)connect to the dv service. |
@@ -283,58 +324,98 @@ static void add_pending(struct GNUNET_DV_Handle *handle, struct GNUNET_DV_SendMe | |||
283 | process_pending_message(handle); | 324 | process_pending_message(handle); |
284 | } | 325 | } |
285 | 326 | ||
286 | 327 | /** | |
328 | * Handles a message sent from the DV service to us. | ||
329 | * Parse it out and give it to the plugin. | ||
330 | * | ||
331 | * @param cls the handle to the DV API | ||
332 | * @param msg the message that was received | ||
333 | */ | ||
287 | void handle_message_receipt (void *cls, | 334 | void handle_message_receipt (void *cls, |
288 | const struct GNUNET_MessageHeader * msg) | 335 | const struct GNUNET_MessageHeader * msg) |
289 | { | 336 | { |
290 | struct GNUNET_DV_Handle *handle = cls; | 337 | struct GNUNET_DV_Handle *handle = cls; |
291 | struct GNUNET_DV_MessageReceived *received_msg; | 338 | struct GNUNET_DV_MessageReceived *received_msg; |
339 | struct GNUNET_DV_SendResultMessage *send_result_msg; | ||
292 | size_t packed_msg_len; | 340 | size_t packed_msg_len; |
293 | size_t sender_address_len; | 341 | size_t sender_address_len; |
294 | char *sender_address; | 342 | char *sender_address; |
295 | char *packed_msg; | 343 | char *packed_msg; |
296 | char *packed_msg_start; | 344 | char *packed_msg_start; |
345 | GNUNET_HashCode uidhash; | ||
346 | struct SendCallbackContext *send_ctx; | ||
297 | 347 | ||
298 | if (msg == NULL) | 348 | if (msg == NULL) |
299 | { | 349 | { |
300 | return; /* Connection closed? */ | 350 | return; /* Connection closed? */ |
301 | } | 351 | } |
302 | 352 | ||
303 | GNUNET_assert(ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE); | 353 | GNUNET_assert((ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE) || (ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT)); |
304 | 354 | ||
305 | if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived)) | 355 | switch (ntohs(msg->type)) |
306 | return; | 356 | { |
357 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE: | ||
358 | if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived)) | ||
359 | return; | ||
307 | 360 | ||
308 | received_msg = (struct GNUNET_DV_MessageReceived *)msg; | 361 | received_msg = (struct GNUNET_DV_MessageReceived *)msg; |
309 | packed_msg_len = ntohl(received_msg->msg_len); | 362 | packed_msg_len = ntohl(received_msg->msg_len); |
310 | sender_address_len = ntohl(received_msg->sender_address_len); | 363 | sender_address_len = ntohl(received_msg->sender_address_len); |
311 | 364 | ||
312 | GNUNET_assert(ntohs(msg->size) == (sizeof(struct GNUNET_DV_MessageReceived) + packed_msg_len + sender_address_len)); | 365 | GNUNET_assert(ntohs(msg->size) == (sizeof(struct GNUNET_DV_MessageReceived) + packed_msg_len + sender_address_len)); |
313 | #if DEBUG_DV | 366 | #if DEBUG_DV |
314 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "dv api receives message, size checks out!\n"); | 367 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "dv api receives message, size checks out!\n"); |
315 | #endif | 368 | #endif |
316 | sender_address = GNUNET_malloc(sender_address_len); | 369 | sender_address = GNUNET_malloc(sender_address_len); |
317 | memcpy(sender_address, &received_msg[1], sender_address_len); | 370 | memcpy(sender_address, &received_msg[1], sender_address_len); |
318 | packed_msg_start = (char *)&received_msg[1]; | 371 | packed_msg_start = (char *)&received_msg[1]; |
319 | packed_msg = GNUNET_malloc(packed_msg_len); | 372 | packed_msg = GNUNET_malloc(packed_msg_len); |
320 | memcpy(packed_msg, &packed_msg_start[sender_address_len], packed_msg_len); | 373 | memcpy(packed_msg, &packed_msg_start[sender_address_len], packed_msg_len); |
321 | 374 | ||
322 | #if DEBUG_DV | 375 | #if DEBUG_DV |
323 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: packed message type: %d or %d\n", ntohs(((struct GNUNET_MessageHeader *)packed_msg)->type), ((struct GNUNET_MessageHeader *)packed_msg)->type); | 376 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: packed message type: %d or %d\n", ntohs(((struct GNUNET_MessageHeader *)packed_msg)->type), ((struct GNUNET_MessageHeader *)packed_msg)->type); |
324 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: message sender reported as %s\n", GNUNET_i2s(&received_msg->sender)); | 377 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: message sender reported as %s\n", GNUNET_i2s(&received_msg->sender)); |
325 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: distance is %u\n", ntohl(received_msg->distance)); | 378 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV_API receive: distance is %u\n", ntohl(received_msg->distance)); |
326 | #endif | 379 | #endif |
327 | 380 | ||
328 | handle->receive_handler(handle->receive_cls, | 381 | handle->receive_handler(handle->receive_cls, |
329 | &received_msg->sender, | 382 | &received_msg->sender, |
330 | packed_msg, | 383 | packed_msg, |
331 | packed_msg_len, | 384 | packed_msg_len, |
332 | ntohl(received_msg->distance), | 385 | ntohl(received_msg->distance), |
333 | sender_address, | 386 | sender_address, |
334 | sender_address_len); | 387 | sender_address_len); |
388 | |||
389 | GNUNET_free(sender_address); | ||
390 | break; | ||
391 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT: | ||
392 | if (ntohs(msg->size) < sizeof(struct GNUNET_DV_SendResultMessage)) | ||
393 | return; | ||
335 | 394 | ||
336 | GNUNET_free(sender_address); | 395 | send_result_msg = (struct GNUNET_DV_SendResultMessage *)msg; |
396 | hash_from_uid(ntohl(send_result_msg->uid), &uidhash); | ||
397 | send_ctx = GNUNET_CONTAINER_multihashmap_get(handle->send_callbacks, &uidhash); | ||
398 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got uid of %u or %u, hash of %s !!!!\n", ntohl(send_result_msg->uid), send_result_msg->uid, GNUNET_h2s(&uidhash)); | ||
337 | 399 | ||
400 | if ((send_ctx != NULL) && (send_ctx->cont != NULL)) | ||
401 | { | ||
402 | #if DEBUG_DV | ||
403 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "dv api notifies transport of send result (%u)!\n", ntohl(send_result_msg->result)); | ||
404 | #endif | ||
405 | if (ntohl(send_result_msg->result) == 0) | ||
406 | { | ||
407 | send_ctx->cont(send_ctx->cont_cls, &send_ctx->target, GNUNET_OK); | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | send_ctx->cont(send_ctx->cont_cls, &send_ctx->target, GNUNET_SYSERR); | ||
412 | } | ||
413 | } | ||
414 | GNUNET_free_non_null(send_ctx); | ||
415 | break; | ||
416 | default: | ||
417 | break; | ||
418 | } | ||
338 | GNUNET_CLIENT_receive (handle->client, | 419 | GNUNET_CLIENT_receive (handle->client, |
339 | &handle_message_receipt, | 420 | &handle_message_receipt, |
340 | handle, GNUNET_TIME_UNIT_FOREVER_REL); | 421 | handle, GNUNET_TIME_UNIT_FOREVER_REL); |
@@ -361,14 +442,18 @@ int GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle, | |||
361 | unsigned int priority, | 442 | unsigned int priority, |
362 | struct GNUNET_TIME_Relative timeout, | 443 | struct GNUNET_TIME_Relative timeout, |
363 | const void *addr, | 444 | const void *addr, |
364 | size_t addrlen) | 445 | size_t addrlen, |
446 | GNUNET_TRANSPORT_TransmitContinuation | ||
447 | cont, void *cont_cls) | ||
365 | { | 448 | { |
366 | struct GNUNET_DV_SendMessage *msg; | 449 | struct GNUNET_DV_SendMessage *msg; |
450 | struct SendCallbackContext *send_ctx; | ||
367 | char *end_of_message; | 451 | char *end_of_message; |
368 | /* FIXME: Copy message to end of thingy, can't just allocate dummy! */ | 452 | GNUNET_HashCode uidhash; |
369 | #if DEBUG_DV | 453 | #if DEBUG_DV |
370 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV SEND called with message of size %d, address size %d, total size to send is %d\n", msgbuf_size, addrlen, sizeof(struct GNUNET_DV_SendMessage) + msgbuf_size + addrlen); | 454 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV SEND called with message of size %d, address size %d, total size to send is %d\n", msgbuf_size, addrlen, sizeof(struct GNUNET_DV_SendMessage) + msgbuf_size + addrlen); |
371 | #endif | 455 | #endif |
456 | dv_handle->uid_gen++; | ||
372 | msg = GNUNET_malloc(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); | 457 | msg = GNUNET_malloc(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); |
373 | msg->header.size = htons(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); | 458 | msg->header.size = htons(sizeof(struct GNUNET_DV_SendMessage) + addrlen + msgbuf_size); |
374 | msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND); | 459 | msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND); |
@@ -377,12 +462,26 @@ int GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle, | |||
377 | msg->priority = htonl(priority); | 462 | msg->priority = htonl(priority); |
378 | msg->timeout = timeout; | 463 | msg->timeout = timeout; |
379 | msg->addrlen = htonl(addrlen); | 464 | msg->addrlen = htonl(addrlen); |
465 | msg->uid = htonl(dv_handle->uid_gen); | ||
380 | memcpy(&msg[1], addr, addrlen); | 466 | memcpy(&msg[1], addr, addrlen); |
381 | end_of_message = (char *)&msg[1]; | 467 | end_of_message = (char *)&msg[1]; |
382 | end_of_message = &end_of_message[addrlen]; | 468 | end_of_message = &end_of_message[addrlen]; |
383 | memcpy(end_of_message, msgbuf, msgbuf_size); | 469 | memcpy(end_of_message, msgbuf, msgbuf_size); |
384 | add_pending(dv_handle, msg); | 470 | add_pending(dv_handle, msg); |
385 | 471 | ||
472 | send_ctx = GNUNET_malloc(sizeof(struct SendCallbackContext)); | ||
473 | |||
474 | send_ctx->cont = cont; | ||
475 | if (cont == NULL) | ||
476 | fprintf(stderr, "DV_SEND called with null continuation!\n"); | ||
477 | send_ctx->cont_cls = cont_cls; | ||
478 | memcpy(&send_ctx->target, target, sizeof(struct GNUNET_PeerIdentity)); | ||
479 | |||
480 | hash_from_uid(dv_handle->uid_gen, &uidhash); | ||
481 | |||
482 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "set uid of %u or %u, hash of %s !!!!\n", dv_handle->uid_gen, htonl(dv_handle->uid_gen), GNUNET_h2s(&uidhash)); | ||
483 | GNUNET_CONTAINER_multihashmap_put(dv_handle->send_callbacks, &uidhash, send_ctx, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
484 | |||
386 | return GNUNET_OK; | 485 | return GNUNET_OK; |
387 | } | 486 | } |
388 | 487 | ||
@@ -464,6 +563,8 @@ GNUNET_DV_connect (struct GNUNET_SCHEDULER_Handle *sched, | |||
464 | GNUNET_YES, | 563 | GNUNET_YES, |
465 | &transmit_start, start_context); | 564 | &transmit_start, start_context); |
466 | 565 | ||
566 | handle->send_callbacks = GNUNET_CONTAINER_multihashmap_create(100); | ||
567 | |||
467 | GNUNET_CLIENT_receive (handle->client, | 568 | GNUNET_CLIENT_receive (handle->client, |
468 | &handle_message_receipt, | 569 | &handle_message_receipt, |
469 | handle, GNUNET_TIME_UNIT_FOREVER_REL); | 570 | handle, GNUNET_TIME_UNIT_FOREVER_REL); |