aboutsummaryrefslogtreecommitdiff
path: root/src/set
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-11-27 11:35:42 +0000
committerChristian Grothoff <christian@grothoff.org>2014-11-27 11:35:42 +0000
commit2b0e3f9ba871095d003fc078eee75b5eda6fc8b8 (patch)
treeb37e6f7d930ca23b0743bda4a76f82aa7c794e13 /src/set
parent393b5b11525badff59ff6df0572c5cdf42c1587c (diff)
downloadgnunet-2b0e3f9ba871095d003fc078eee75b5eda6fc8b8.tar.gz
gnunet-2b0e3f9ba871095d003fc078eee75b5eda6fc8b8.zip
again, do not pass salt around, code cleanup, etc.
Diffstat (limited to 'src/set')
-rw-r--r--src/set/gnunet-service-set.c342
-rw-r--r--src/set/gnunet-service-set_union.c10
-rw-r--r--src/set/set.h65
-rw-r--r--src/set/set_api.c14
4 files changed, 259 insertions, 172 deletions
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
index 0fc2e4d6a..c3c0d34f6 100644
--- a/src/set/gnunet-service-set.c
+++ b/src/set/gnunet-service-set.c
@@ -26,6 +26,11 @@
26#include "gnunet-service-set.h" 26#include "gnunet-service-set.h"
27#include "set_protocol.h" 27#include "set_protocol.h"
28 28
29/**
30 * How long do we hold on to an incoming channel if there is
31 * no local listener before giving up?
32 */
33#define INCOMING_CHANNEL_TIMEOUT GNUNET_TIME_UNIT_MINUTES
29 34
30/** 35/**
31 * A listener is inhabited by a client, and waits for evaluation 36 * A listener is inhabited by a client, and waits for evaluation
@@ -195,7 +200,7 @@ listener_destroy (struct Listener *listener)
195 200
196 listener->client = NULL; 201 listener->client = NULL;
197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
198 "disconnecting listener client\n"); 203 "Disconnecting listener client\n");
199 GNUNET_SERVER_client_disconnect (client); 204 GNUNET_SERVER_client_disconnect (client);
200 return; 205 return;
201 } 206 }
@@ -475,6 +480,11 @@ incoming_destroy (struct Operation *incoming)
475 } 480 }
476 /* make sure that the tunnel end handler will not destroy us again */ 481 /* make sure that the tunnel end handler will not destroy us again */
477 incoming->vt = NULL; 482 incoming->vt = NULL;
483 if (NULL != incoming->spec)
484 {
485 GNUNET_free (incoming->spec);
486 incoming->spec = NULL;
487 }
478 if (NULL != incoming->mq) 488 if (NULL != incoming->mq)
479 { 489 {
480 GNUNET_MQ_destroy (incoming->mq); 490 GNUNET_MQ_destroy (incoming->mq);
@@ -548,7 +558,11 @@ incoming_suggest (struct Operation *incoming,
548 558
549 559
550/** 560/**
551 * Handle a request for a set operation from another peer. 561 * Handle a request for a set operation from another peer. Checks if we
562 * have a listener waiting for such a request (and in that case initiates
563 * asking the listener about accepting the connection). If no listener
564 * is waiting, we queue the operation request in hope that a listener
565 * shows up soon (before timeout).
552 * 566 *
553 * This msg is expected as the first and only msg handled through the 567 * This msg is expected as the first and only msg handled through the
554 * non-operation bound virtual table, acceptance of this operation replaces 568 * non-operation bound virtual table, acceptance of this operation replaces
@@ -581,11 +595,16 @@ handle_incoming_msg (struct Operation *op,
581 GNUNET_break_op (0); 595 GNUNET_break_op (0);
582 return GNUNET_SYSERR; 596 return GNUNET_SYSERR;
583 } 597 }
584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
585 "Got op request\n");
586 spec = GNUNET_new (struct OperationSpecification); 598 spec = GNUNET_new (struct OperationSpecification);
587 spec->context_msg = GNUNET_MQ_extract_nested_mh (msg); 599 spec->context_msg = GNUNET_MQ_extract_nested_mh (msg);
588 // for simplicity we just backup the context msg instead of rebuilding it later on 600 /* for simplicity we just backup the context msg instead of rebuilding it later on */
601 if ( (NULL != spec->context_msg) &&
602 (ntohs (spec->context_msg->size) > GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE) )
603 {
604 GNUNET_break_op (0);
605 GNUNET_free (spec);
606 return GNUNET_SYSERR;
607 }
589 if (NULL != spec->context_msg) 608 if (NULL != spec->context_msg)
590 spec->context_msg = GNUNET_copy_message (spec->context_msg); 609 spec->context_msg = GNUNET_copy_message (spec->context_msg);
591 spec->operation = ntohl (msg->operation); 610 spec->operation = ntohl (msg->operation);
@@ -594,28 +613,23 @@ handle_incoming_msg (struct Operation *op,
594 UINT32_MAX); 613 UINT32_MAX);
595 spec->peer = op->peer; 614 spec->peer = op->peer;
596 spec->remote_element_count = ntohl (msg->element_count); 615 spec->remote_element_count = ntohl (msg->element_count);
597
598 op->spec = spec; 616 op->spec = spec;
599 617
600 if ( (NULL != spec->context_msg) &&
601 (ntohs (spec->context_msg->size) > GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE) )
602 {
603 GNUNET_break_op (0);
604 return GNUNET_SYSERR;
605 }
606
607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
608 "received P2P operation request (op %u, app %s)\n",
609 ntohl (msg->operation),
610 GNUNET_h2s (&msg->app_id));
611 listener = listener_get_by_target (ntohl (msg->operation), 618 listener = listener_get_by_target (ntohl (msg->operation),
612 &msg->app_id); 619 &msg->app_id);
613 if (NULL == listener) 620 if (NULL == listener)
614 { 621 {
622 GNUNET_break (GNUNET_SCHEDULER_NO_TASK != op->timeout_task);
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "no listener matches incoming request, waiting with timeout\n"); 624 "No matching listener for incoming request (op %u, app %s), waiting with timeout\n",
625 ntohl (msg->operation),
626 GNUNET_h2s (&msg->app_id));
617 return GNUNET_OK; 627 return GNUNET_OK;
618 } 628 }
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630 "Received P2P operation request (op %u, app %s) for active listener\n",
631 ntohl (msg->operation),
632 GNUNET_h2s (&msg->app_id));
619 incoming_suggest (op, listener); 633 incoming_suggest (op, listener);
620 return GNUNET_OK; 634 return GNUNET_OK;
621} 635}
@@ -627,6 +641,11 @@ handle_incoming_msg (struct Operation *op,
627 * are no more elements in the set. The caller must ensure that the set's iterator is 641 * are no more elements in the set. The caller must ensure that the set's iterator is
628 * valid. 642 * valid.
629 * 643 *
644 * The client will acknowledge each received element with a
645 * #GNUNET_MESSAGE_TYPE_SET_ITER_ACK message. Our
646 * #handle_client_iter_ack() will then trigger the next transmission.
647 * Note that the #GNUNET_MESSAGE_TYPE_SET_ITER_DONE is not acknowledged.
648 *
630 * @param set set that should send its next element to its client 649 * @param set set that should send its next element to its client
631 */ 650 */
632static void 651static void
@@ -635,6 +654,7 @@ send_client_element (struct Set *set)
635 int ret; 654 int ret;
636 struct ElementEntry *ee; 655 struct ElementEntry *ee;
637 struct GNUNET_MQ_Envelope *ev; 656 struct GNUNET_MQ_Envelope *ev;
657 struct GNUNET_SET_IterResponseMessage *msg;
638 658
639 GNUNET_assert (NULL != set->iter); 659 GNUNET_assert (NULL != set->iter);
640 ret = GNUNET_CONTAINER_multihashmap_iterator_next (set->iter, 660 ret = GNUNET_CONTAINER_multihashmap_iterator_next (set->iter,
@@ -648,13 +668,13 @@ send_client_element (struct Set *set)
648 } 668 }
649 else 669 else
650 { 670 {
651 struct GNUNET_SET_IterResponseMessage *msg;
652
653 GNUNET_assert (NULL != ee); 671 GNUNET_assert (NULL != ee);
654 ev = GNUNET_MQ_msg_extra (msg, 672 ev = GNUNET_MQ_msg_extra (msg,
655 ee->element.size, 673 ee->element.size,
656 GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT); 674 GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT);
657 memcpy (&msg[1], ee->element.data, ee->element.size); 675 memcpy (&msg[1],
676 ee->element.data,
677 ee->element.size);
658 msg->element_type = ee->element.element_type; 678 msg->element_type = ee->element.element_type;
659 } 679 }
660 GNUNET_MQ_send (set->client_mq, ev); 680 GNUNET_MQ_send (set->client_mq, ev);
@@ -663,6 +683,9 @@ send_client_element (struct Set *set)
663 683
664/** 684/**
665 * Called when a client wants to iterate the elements of a set. 685 * Called when a client wants to iterate the elements of a set.
686 * Checks if we have a set associated with the client and if we
687 * can right now start an iteration. If all checks out, starts
688 * sending the elements of the set to the client.
666 * 689 *
667 * @param cls unused 690 * @param cls unused
668 * @param client client that sent the message 691 * @param client client that sent the message
@@ -675,33 +698,35 @@ handle_client_iterate (void *cls,
675{ 698{
676 struct Set *set; 699 struct Set *set;
677 700
678 // iterate over a non existing set
679 set = set_get (client); 701 set = set_get (client);
680 if (NULL == set) 702 if (NULL == set)
681 { 703 {
704 /* attempt to iterate over a non existing set */
682 GNUNET_break (0); 705 GNUNET_break (0);
683 GNUNET_SERVER_client_disconnect (client); 706 GNUNET_SERVER_client_disconnect (client);
684 return; 707 return;
685 } 708 }
686
687 // only one concurrent iterate-action per set
688 if (NULL != set->iter) 709 if (NULL != set->iter)
689 { 710 {
711 /* Only one concurrent iterate-action allowed per set */
690 GNUNET_break (0); 712 GNUNET_break (0);
691 GNUNET_SERVER_client_disconnect (client); 713 GNUNET_SERVER_client_disconnect (client);
692 return; 714 return;
693 } 715 }
694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
695 "iterating union set with %u elements\n", 717 "Iterating union set with %u elements\n",
696 GNUNET_CONTAINER_multihashmap_size (set->elements)); 718 GNUNET_CONTAINER_multihashmap_size (set->elements));
697 GNUNET_SERVER_receive_done (client, GNUNET_OK); 719 GNUNET_SERVER_receive_done (client,
720 GNUNET_OK);
698 set->iter = GNUNET_CONTAINER_multihashmap_iterator_create (set->elements); 721 set->iter = GNUNET_CONTAINER_multihashmap_iterator_create (set->elements);
699 send_client_element (set); 722 send_client_element (set);
700} 723}
701 724
702 725
703/** 726/**
704 * Called when a client wants to create a new set. 727 * Called when a client wants to create a new set. This is typically
728 * the first request from a client, and includes the type of set
729 * operation to be performed.
705 * 730 *
706 * @param cls unused 731 * @param cls unused
707 * @param client client that sent the message 732 * @param client client that sent the message
@@ -717,19 +742,16 @@ handle_client_create_set (void *cls,
717 742
718 msg = (const struct GNUNET_SET_CreateMessage *) m; 743 msg = (const struct GNUNET_SET_CreateMessage *) m;
719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
720 "client created new set (operation %u)\n", 745 "Client created new set (operation %u)\n",
721 ntohs (msg->operation)); 746 ntohs (msg->operation));
722
723 // max. one set per client!
724 if (NULL != set_get (client)) 747 if (NULL != set_get (client))
725 { 748 {
749 /* There can only be one set per client */
726 GNUNET_break (0); 750 GNUNET_break (0);
727 GNUNET_SERVER_client_disconnect (client); 751 GNUNET_SERVER_client_disconnect (client);
728 return; 752 return;
729 } 753 }
730
731 set = GNUNET_new (struct Set); 754 set = GNUNET_new (struct Set);
732
733 switch (ntohl (msg->operation)) 755 switch (ntohl (msg->operation))
734 { 756 {
735 case GNUNET_SET_OPERATION_INTERSECTION: 757 case GNUNET_SET_OPERATION_INTERSECTION:
@@ -744,13 +766,15 @@ handle_client_create_set (void *cls,
744 GNUNET_SERVER_client_disconnect (client); 766 GNUNET_SERVER_client_disconnect (client);
745 return; 767 return;
746 } 768 }
747
748 set->state = set->vt->create (); 769 set->state = set->vt->create ();
749 set->elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); 770 set->elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
750 set->client = client; 771 set->client = client;
751 set->client_mq = GNUNET_MQ_queue_for_server_client (client); 772 set->client_mq = GNUNET_MQ_queue_for_server_client (client);
752 GNUNET_CONTAINER_DLL_insert (sets_head, sets_tail, set); 773 GNUNET_CONTAINER_DLL_insert (sets_head,
753 GNUNET_SERVER_receive_done (client, GNUNET_OK); 774 sets_tail,
775 set);
776 GNUNET_SERVER_receive_done (client,
777 GNUNET_OK);
754} 778}
755 779
756 780
@@ -771,14 +795,13 @@ handle_client_listen (void *cls,
771 struct Operation *op; 795 struct Operation *op;
772 796
773 msg = (const struct GNUNET_SET_ListenMessage *) m; 797 msg = (const struct GNUNET_SET_ListenMessage *) m;
774 /* max. one per client! */
775 if (NULL != listener_get (client)) 798 if (NULL != listener_get (client))
776 { 799 {
800 /* max. one active listener per client! */
777 GNUNET_break (0); 801 GNUNET_break (0);
778 GNUNET_SERVER_client_disconnect (client); 802 GNUNET_SERVER_client_disconnect (client);
779 return; 803 return;
780 } 804 }
781
782 listener = GNUNET_new (struct Listener); 805 listener = GNUNET_new (struct Listener);
783 listener->client = client; 806 listener->client = client;
784 listener->client_mq = GNUNET_MQ_queue_for_server_client (client); 807 listener->client_mq = GNUNET_MQ_queue_for_server_client (client);
@@ -788,38 +811,27 @@ handle_client_listen (void *cls,
788 listeners_tail, 811 listeners_tail,
789 listener); 812 listener);
790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
791 "new listener created (op %u, app %s)\n", 814 "New listener created (op %u, app %s)\n",
792 listener->operation, 815 listener->operation,
793 GNUNET_h2s (&listener->app_id)); 816 GNUNET_h2s (&listener->app_id));
794 817
795 /* check for incoming requests the listener is interested in */ 818 /* check for existing incoming requests the listener might be interested in */
796 for (op = incoming_head; NULL != op; op = op->next) 819 for (op = incoming_head; NULL != op; op = op->next)
797 { 820 {
798 if (NULL == op->spec) 821 if (NULL == op->spec)
799 { 822 continue; /* no details available yet */
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
801 "request has no spec yet\n");
802 continue;
803 }
804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
805 "considering (op: %u, app: %s, suggest: %u)\n",
806 op->spec->operation,
807 GNUNET_h2s (&op->spec->app_id),
808 op->suggest_id);
809
810 /* don't consider the incoming request if it has been already suggested to a listener */
811 if (0 != op->suggest_id) 823 if (0 != op->suggest_id)
812 continue; 824 continue; /* this one has been already suggested to a listener */
813 if (listener->operation != op->spec->operation) 825 if (listener->operation != op->spec->operation)
814 continue; 826 continue; /* incompatible operation */
815 if (0 != GNUNET_CRYPTO_hash_cmp (&listener->app_id, &op->spec->app_id)) 827 if (0 != GNUNET_CRYPTO_hash_cmp (&listener->app_id,
816 continue; 828 &op->spec->app_id))
829 continue; /* incompatible appliation */
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
818 "request suggested\n"); 831 "Found matching existing request\n");
819 incoming_suggest (op, listener); 832 incoming_suggest (op,
833 listener);
820 } 834 }
821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
822 "considered all incoming requests\n");
823 GNUNET_SERVER_receive_done (client, GNUNET_OK); 835 GNUNET_SERVER_receive_done (client, GNUNET_OK);
824} 836}
825 837
@@ -841,102 +853,143 @@ handle_client_reject (void *cls,
841 const struct GNUNET_SET_RejectMessage *msg; 853 const struct GNUNET_SET_RejectMessage *msg;
842 854
843 msg = (const struct GNUNET_SET_RejectMessage *) m; 855 msg = (const struct GNUNET_SET_RejectMessage *) m;
844 GNUNET_break (0 == ntohl (msg->request_id));
845
846 // no matching incoming operation for this reject
847 incoming = get_incoming (ntohl (msg->accept_reject_id)); 856 incoming = get_incoming (ntohl (msg->accept_reject_id));
848 if (NULL == incoming) 857 if (NULL == incoming)
849 { 858 {
850 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 859 /* no matching incoming operation for this reject */
860 GNUNET_break (0);
861 GNUNET_SERVER_receive_done (client,
862 GNUNET_SYSERR);
851 return; 863 return;
852 } 864 }
853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 865 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
854 "peer request rejected by client\n"); 866 "Peer request (op %u, app %s) rejected by client\n",
855 867 incoming->spec->operation,
868 GNUNET_h2s (&incoming->spec->app_id));
856 GNUNET_CADET_channel_destroy (incoming->channel); 869 GNUNET_CADET_channel_destroy (incoming->channel);
857 //channel destruction handler called immediately upon destruction 870 GNUNET_SERVER_receive_done (client,
858 GNUNET_SERVER_receive_done (client, GNUNET_OK); 871 GNUNET_OK);
859} 872}
860 873
861 874
862/** 875/**
863 * Called when a client wants to add/remove an element to/from a 876 * Called when a client wants to add an element to a set it inhabits.
864 * set it inhabits.
865 * 877 *
866 * @param cls unused 878 * @param cls unused
867 * @param client client that sent the message 879 * @param client client that sent the message
868 * @param m message sent by the client 880 * @param m message sent by the client
869 */ 881 */
870static void 882static void
871handle_client_add_remove (void *cls, 883handle_client_add (void *cls,
872 struct GNUNET_SERVER_Client *client, 884 struct GNUNET_SERVER_Client *client,
873 const struct GNUNET_MessageHeader *m) 885 const struct GNUNET_MessageHeader *m)
874{ 886{
875 struct Set *set; 887 struct Set *set;
876 const struct GNUNET_SET_ElementMessage *msg; 888 const struct GNUNET_SET_ElementMessage *msg;
877 struct GNUNET_SET_Element el; 889 struct GNUNET_SET_Element el;
878 struct ElementEntry *ee; 890 struct ElementEntry *ee;
891 struct ElementEntry *ee_dup;
879 892
880 // client without a set requested an operation
881 set = set_get (client); 893 set = set_get (client);
882 if (NULL == set) 894 if (NULL == set)
883 { 895 {
896 /* client without a set requested an operation */
884 GNUNET_break (0); 897 GNUNET_break (0);
885 GNUNET_SERVER_client_disconnect (client); 898 GNUNET_SERVER_client_disconnect (client);
886 return; 899 return;
887 } 900 }
888 GNUNET_SERVER_receive_done (client, GNUNET_OK); 901 GNUNET_SERVER_receive_done (client,
902 GNUNET_OK);
889 msg = (const struct GNUNET_SET_ElementMessage *) m; 903 msg = (const struct GNUNET_SET_ElementMessage *) m;
890 el.size = ntohs (m->size) - sizeof *msg; 904 el.size = ntohs (m->size) - sizeof *msg;
891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 905 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
892 "client ins/rem element of size %u\n", el.size); 906 "Client inserts element of size %u\n",
907 el.size);
893 el.data = &msg[1]; 908 el.data = &msg[1];
894 if (GNUNET_MESSAGE_TYPE_SET_REMOVE == ntohs (m->type)) 909 ee = GNUNET_malloc (el.size + sizeof *ee);
910 ee->element.size = el.size;
911 memcpy (&ee[1],
912 el.data,
913 el.size);
914 ee->element.data = &ee[1];
915 ee->generation_added = set->current_generation;
916 ee->remote = GNUNET_NO;
917 GNUNET_CRYPTO_hash (ee->element.data,
918 el.size,
919 &ee->element_hash);
920 ee_dup = GNUNET_CONTAINER_multihashmap_get (set->elements,
921 &ee->element_hash);
922 if (NULL != ee_dup)
895 { 923 {
896 struct GNUNET_HashCode hash; 924 /* same element inserted twice */
925 GNUNET_break (0);
926 GNUNET_free (ee);
927 return;
928 }
929 GNUNET_break (GNUNET_YES ==
930 GNUNET_CONTAINER_multihashmap_put (set->elements,
931 &ee->element_hash,
932 ee,
933 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
934 set->vt->add (set->state, ee);
935}
897 936
898 GNUNET_CRYPTO_hash (el.data, el.size, &hash); 937
899 ee = GNUNET_CONTAINER_multihashmap_get (set->elements, &hash); 938/**
900 if (NULL == ee) 939 * Called when a client wants to remove an element from a set it
901 { 940 * inhabits.
902 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 941 *
903 "client tried to remove non-existing element\n"); 942 * @param cls unused
904 return; 943 * @param client client that sent the message
905 } 944 * @param m message sent by the client
906 if (GNUNET_YES == ee->removed) 945 */
907 { 946static void
908 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 947handle_client_remove (void *cls,
909 "client tried to remove element twice\n"); 948 struct GNUNET_SERVER_Client *client,
910 return; 949 const struct GNUNET_MessageHeader *m)
911 } 950{
912 ee->removed = GNUNET_YES; 951 struct Set *set;
913 ee->generation_removed = set->current_generation; 952 const struct GNUNET_SET_ElementMessage *msg;
914 set->vt->remove (set->state, ee); 953 struct GNUNET_SET_Element el;
954 struct ElementEntry *ee;
955 struct GNUNET_HashCode hash;
956
957 set = set_get (client);
958 if (NULL == set)
959 {
960 /* client without a set requested an operation */
961 GNUNET_break (0);
962 GNUNET_SERVER_client_disconnect (client);
963 return;
915 } 964 }
916 else 965 GNUNET_SERVER_receive_done (client,
966 GNUNET_OK);
967 msg = (const struct GNUNET_SET_ElementMessage *) m;
968 el.size = ntohs (m->size) - sizeof *msg;
969 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970 "Client removes element of size %u\n",
971 el.size);
972 el.data = &msg[1];
973 GNUNET_CRYPTO_hash (el.data,
974 el.size,
975 &hash);
976 ee = GNUNET_CONTAINER_multihashmap_get (set->elements,
977 &hash);
978 if (NULL == ee)
917 { 979 {
918 struct ElementEntry *ee_dup; 980 /* Client tried to remove non-existing element */
919 981 GNUNET_break (0);
920 ee = GNUNET_malloc (el.size + sizeof *ee); 982 return;
921 ee->element.size = el.size;
922 memcpy (&ee[1], el.data, el.size);
923 ee->element.data = &ee[1];
924 ee->generation_added = set->current_generation;
925 ee->remote = GNUNET_NO;
926 GNUNET_CRYPTO_hash (ee->element.data, el.size, &ee->element_hash);
927 ee_dup = GNUNET_CONTAINER_multihashmap_get (set->elements,
928 &ee->element_hash);
929 if (NULL != ee_dup)
930 {
931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
932 "element inserted twice, ignoring\n");
933 GNUNET_free (ee);
934 return;
935 }
936 GNUNET_CONTAINER_multihashmap_put (set->elements, &ee->element_hash, ee,
937 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
938 set->vt->add (set->state, ee);
939 } 983 }
984 if (GNUNET_YES == ee->removed)
985 {
986 /* Client tried to remove element twice */
987 GNUNET_break (0);
988 return;
989 }
990 ee->removed = GNUNET_YES;
991 ee->generation_removed = set->current_generation;
992 set->vt->remove (set->state, ee);
940} 993}
941 994
942 995
@@ -956,6 +1009,7 @@ handle_client_evaluate (void *cls,
956 const struct GNUNET_SET_EvaluateMessage *msg; 1009 const struct GNUNET_SET_EvaluateMessage *msg;
957 struct OperationSpecification *spec; 1010 struct OperationSpecification *spec;
958 struct Operation *op; 1011 struct Operation *op;
1012 const struct GNUNET_MessageHeader *context;
959 1013
960 set = set_get (client); 1014 set = set_get (client);
961 if (NULL == set) 1015 if (NULL == set)
@@ -969,36 +1023,44 @@ handle_client_evaluate (void *cls,
969 spec = GNUNET_new (struct OperationSpecification); 1023 spec = GNUNET_new (struct OperationSpecification);
970 spec->operation = set->operation; 1024 spec->operation = set->operation;
971 spec->app_id = msg->app_id; 1025 spec->app_id = msg->app_id;
972 spec->salt = ntohl (msg->salt); 1026 spec->salt = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1027 UINT32_MAX);
973 spec->peer = msg->target_peer; 1028 spec->peer = msg->target_peer;
974 spec->set = set; 1029 spec->set = set;
975 spec->result_mode = ntohs (msg->result_mode); 1030 spec->result_mode = ntohs (msg->result_mode);
976 spec->client_request_id = ntohl (msg->request_id); 1031 spec->client_request_id = ntohl (msg->request_id);
977 spec->context_msg = GNUNET_MQ_extract_nested_mh (msg); 1032 context = GNUNET_MQ_extract_nested_mh (msg);
978 1033 /* The evaluate message MAY contain a nested message to be passed to
979 // for simplicity we just backup the context msg instead of rebuilding it later on 1034 the listner for additional authentication or application-specific
980 if (NULL != spec->context_msg) 1035 context. We make a copy of this nested/context msg as we need
981 spec->context_msg = GNUNET_copy_message (spec->context_msg); 1036 to transmit it later. */
1037 if (NULL != context)
1038 spec->context_msg = GNUNET_copy_message (context);
982 1039
983 op = GNUNET_new (struct Operation); 1040 op = GNUNET_new (struct Operation);
984 op->spec = spec; 1041 op->spec = spec;
985 op->generation_created = set->current_generation++; 1042 op->generation_created = set->current_generation++;
986 op->vt = set->vt; 1043 op->vt = set->vt;
987 GNUNET_CONTAINER_DLL_insert (set->ops_head, set->ops_tail, op); 1044 GNUNET_CONTAINER_DLL_insert (set->ops_head,
988 1045 set->ops_tail,
989 op->channel = GNUNET_CADET_channel_create (cadet, op, &msg->target_peer, 1046 op);
990 GNUNET_APPLICATION_TYPE_SET,
991 GNUNET_CADET_OPTION_RELIABLE);
992 1047
1048 op->channel = GNUNET_CADET_channel_create (cadet,
1049 op,
1050 &msg->target_peer,
1051 GNUNET_APPLICATION_TYPE_SET,
1052 GNUNET_CADET_OPTION_RELIABLE);
993 op->mq = GNUNET_CADET_mq_create (op->channel); 1053 op->mq = GNUNET_CADET_mq_create (op->channel);
994
995 set->vt->evaluate (op); 1054 set->vt->evaluate (op);
996 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1055 GNUNET_SERVER_receive_done (client,
1056 GNUNET_OK);
997} 1057}
998 1058
999 1059
1000/** 1060/**
1001 * Handle an ack from a client, and send the next element. 1061 * Handle an ack from a client, and send the next element. Note
1062 * that we only expect acks for set elements, not after the
1063 * #GNUNET_MESSAGE_TYPE_SET_ITER_DONE message.
1002 * 1064 *
1003 * @param cls unused 1065 * @param cls unused
1004 * @param client the client 1066 * @param client the client
@@ -1011,24 +1073,24 @@ handle_client_iter_ack (void *cls,
1011{ 1073{
1012 struct Set *set; 1074 struct Set *set;
1013 1075
1014 // client without a set requested an operation
1015 set = set_get (client); 1076 set = set_get (client);
1016 if (NULL == set) 1077 if (NULL == set)
1017 { 1078 {
1079 /* client without a set acknowledged receiving a value */
1018 GNUNET_break (0); 1080 GNUNET_break (0);
1019 GNUNET_SERVER_client_disconnect (client); 1081 GNUNET_SERVER_client_disconnect (client);
1020 return; 1082 return;
1021 } 1083 }
1022
1023 // client sent an ack, but we were not expecting one
1024 if (NULL == set->iter) 1084 if (NULL == set->iter)
1025 { 1085 {
1086 /* client sent an ack, but we were not expecting one (as
1087 set iteration has finished) */
1026 GNUNET_break (0); 1088 GNUNET_break (0);
1027 GNUNET_SERVER_client_disconnect (client); 1089 GNUNET_SERVER_client_disconnect (client);
1028 return; 1090 return;
1029 } 1091 }
1030 1092 GNUNET_SERVER_receive_done (client,
1031 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1093 GNUNET_OK);
1032 send_client_element (set); 1094 send_client_element (set);
1033} 1095}
1034 1096
@@ -1283,15 +1345,15 @@ channel_new_cb (void *cls,
1283 return NULL; 1345 return NULL;
1284 } 1346 }
1285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1286 "new incoming channel\n"); 1348 "New incoming channel\n");
1287 incoming = GNUNET_new (struct Operation); 1349 incoming = GNUNET_new (struct Operation);
1288 incoming->is_incoming = GNUNET_YES; 1350 incoming->is_incoming = GNUNET_YES;
1289 incoming->peer = *initiator; 1351 incoming->peer = *initiator;
1290 incoming->channel = channel; 1352 incoming->channel = channel;
1291 incoming->mq = GNUNET_CADET_mq_create (incoming->channel); 1353 incoming->mq = GNUNET_CADET_mq_create (incoming->channel);
1292 incoming->vt = &incoming_vt; 1354 incoming->vt = &incoming_vt;
1293 incoming->timeout_task = 1355 incoming->timeout_task
1294 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, 1356 = GNUNET_SCHEDULER_add_delayed (INCOMING_CHANNEL_TIMEOUT,
1295 &incoming_timeout_cb, 1357 &incoming_timeout_cb,
1296 incoming); 1358 incoming);
1297 GNUNET_CONTAINER_DLL_insert_tail (incoming_head, 1359 GNUNET_CONTAINER_DLL_insert_tail (incoming_head,
@@ -1405,7 +1467,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1405 {handle_client_accept, NULL, GNUNET_MESSAGE_TYPE_SET_ACCEPT, 1467 {handle_client_accept, NULL, GNUNET_MESSAGE_TYPE_SET_ACCEPT,
1406 sizeof (struct GNUNET_SET_AcceptMessage)}, 1468 sizeof (struct GNUNET_SET_AcceptMessage)},
1407 {handle_client_iter_ack, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_ACK, 0}, 1469 {handle_client_iter_ack, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_ACK, 0},
1408 {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_ADD, 0}, 1470 {handle_client_add, NULL, GNUNET_MESSAGE_TYPE_SET_ADD, 0},
1409 {handle_client_create_set, NULL, GNUNET_MESSAGE_TYPE_SET_CREATE, 1471 {handle_client_create_set, NULL, GNUNET_MESSAGE_TYPE_SET_CREATE,
1410 sizeof (struct GNUNET_SET_CreateMessage)}, 1472 sizeof (struct GNUNET_SET_CreateMessage)},
1411 {handle_client_iterate, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST, 1473 {handle_client_iterate, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST,
@@ -1415,7 +1477,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1415 sizeof (struct GNUNET_SET_ListenMessage)}, 1477 sizeof (struct GNUNET_SET_ListenMessage)},
1416 {handle_client_reject, NULL, GNUNET_MESSAGE_TYPE_SET_REJECT, 1478 {handle_client_reject, NULL, GNUNET_MESSAGE_TYPE_SET_REJECT,
1417 sizeof (struct GNUNET_SET_RejectMessage)}, 1479 sizeof (struct GNUNET_SET_RejectMessage)},
1418 {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_REMOVE, 0}, 1480 {handle_client_remove, NULL, GNUNET_MESSAGE_TYPE_SET_REMOVE, 0},
1419 {handle_client_cancel, NULL, GNUNET_MESSAGE_TYPE_SET_CANCEL, 1481 {handle_client_cancel, NULL, GNUNET_MESSAGE_TYPE_SET_CANCEL,
1420 sizeof (struct GNUNET_SET_CancelMessage)}, 1482 sizeof (struct GNUNET_SET_CancelMessage)},
1421 {NULL, NULL, 0, 0} 1483 {NULL, NULL, 0, 0}
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c
index c00728015..88b8856b0 100644
--- a/src/set/gnunet-service-set_union.c
+++ b/src/set/gnunet-service-set_union.c
@@ -355,7 +355,8 @@ send_operation_request (struct Operation *op)
355 struct GNUNET_MQ_Envelope *ev; 355 struct GNUNET_MQ_Envelope *ev;
356 struct OperationRequestMessage *msg; 356 struct OperationRequestMessage *msg;
357 357
358 ev = GNUNET_MQ_msg_nested_mh (msg, GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST, 358 ev = GNUNET_MQ_msg_nested_mh (msg,
359 GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST,
359 op->spec->context_msg); 360 op->spec->context_msg);
360 361
361 if (NULL == ev) 362 if (NULL == ev)
@@ -371,10 +372,11 @@ send_operation_request (struct Operation *op)
371 GNUNET_MQ_send (op->mq, ev); 372 GNUNET_MQ_send (op->mq, ev);
372 373
373 if (NULL != op->spec->context_msg) 374 if (NULL != op->spec->context_msg)
374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent op request with context message\n"); 375 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
376 "sent op request with context message\n");
375 else 377 else
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent op request without context message\n"); 378 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
377 379 "sent op request without context message\n");
378 if (NULL != op->spec->context_msg) 380 if (NULL != op->spec->context_msg)
379 { 381 {
380 GNUNET_free (op->spec->context_msg); 382 GNUNET_free (op->spec->context_msg);
diff --git a/src/set/set.h b/src/set/set.h
index be3a7a0c6..f3aedff4f 100644
--- a/src/set/set.h
+++ b/src/set/set.h
@@ -37,6 +37,11 @@
37 37
38GNUNET_NETWORK_STRUCT_BEGIN 38GNUNET_NETWORK_STRUCT_BEGIN
39 39
40/**
41 * Message sent by the client to the service to ask starting
42 * a new set to perform operations with. Includes the desired
43 * set operation type.
44 */
40struct GNUNET_SET_CreateMessage 45struct GNUNET_SET_CreateMessage
41{ 46{
42 /** 47 /**
@@ -51,6 +56,11 @@ struct GNUNET_SET_CreateMessage
51}; 56};
52 57
53 58
59/**
60 * Message sent by the client to the service to start listening for
61 * incoming requests to perform a certain type of set operation for a
62 * certain type of application.
63 */
54struct GNUNET_SET_ListenMessage 64struct GNUNET_SET_ListenMessage
55{ 65{
56 /** 66 /**
@@ -71,6 +81,10 @@ struct GNUNET_SET_ListenMessage
71}; 81};
72 82
73 83
84/**
85 * Message sent by a listening client to the service to accept
86 * performing the operation with the other peer.
87 */
74struct GNUNET_SET_AcceptMessage 88struct GNUNET_SET_AcceptMessage
75{ 89{
76 /** 90 /**
@@ -79,13 +93,12 @@ struct GNUNET_SET_AcceptMessage
79 struct GNUNET_MessageHeader header; 93 struct GNUNET_MessageHeader header;
80 94
81 /** 95 /**
82 * ID of the incoming request we want to accept / reject. 96 * ID of the incoming request we want to accept.
83 */ 97 */
84 uint32_t accept_reject_id GNUNET_PACKED; 98 uint32_t accept_reject_id GNUNET_PACKED;
85 99
86 /** 100 /**
87 * Request ID to identify responses, 101 * Request ID to identify responses.
88 * must be 0 if we don't accept the request.
89 */ 102 */
90 uint32_t request_id GNUNET_PACKED; 103 uint32_t request_id GNUNET_PACKED;
91 104
@@ -97,6 +110,10 @@ struct GNUNET_SET_AcceptMessage
97}; 110};
98 111
99 112
113/**
114 * Message sent by a listening client to the service to reject
115 * performing the operation with the other peer.
116 */
100struct GNUNET_SET_RejectMessage 117struct GNUNET_SET_RejectMessage
101{ 118{
102 /** 119 /**
@@ -105,16 +122,10 @@ struct GNUNET_SET_RejectMessage
105 struct GNUNET_MessageHeader header; 122 struct GNUNET_MessageHeader header;
106 123
107 /** 124 /**
108 * ID of the incoming request we want to accept / reject. 125 * ID of the incoming request we want to reject.
109 */ 126 */
110 uint32_t accept_reject_id GNUNET_PACKED; 127 uint32_t accept_reject_id GNUNET_PACKED;
111 128
112 /**
113 * Request ID to identify responses,
114 * must be 0 if we don't accept the request.
115 */
116 uint32_t request_id GNUNET_PACKED;
117
118}; 129};
119 130
120 131
@@ -143,6 +154,11 @@ struct GNUNET_SET_RequestMessage
143}; 154};
144 155
145 156
157/**
158 * Message sent by client to service to initiate a set operation as a
159 * client (not as listener). A set (which determines the operation
160 * type) must already exist in association with this client.
161 */
146struct GNUNET_SET_EvaluateMessage 162struct GNUNET_SET_EvaluateMessage
147{ 163{
148 /** 164 /**
@@ -151,9 +167,10 @@ struct GNUNET_SET_EvaluateMessage
151 struct GNUNET_MessageHeader header; 167 struct GNUNET_MessageHeader header;
152 168
153 /** 169 /**
154 * id of our evaluate, chosen by the client 170 * How should results be sent to us?
171 * See `enum GNUNET_SET_ResultMode`.
155 */ 172 */
156 uint32_t request_id GNUNET_PACKED; 173 uint32_t result_mode GNUNET_PACKED;
157 174
158 /** 175 /**
159 * Peer to evaluate the operation with 176 * Peer to evaluate the operation with
@@ -166,17 +183,13 @@ struct GNUNET_SET_EvaluateMessage
166 struct GNUNET_HashCode app_id; 183 struct GNUNET_HashCode app_id;
167 184
168 /** 185 /**
169 * Salt to use for the operation. 186 * Id of our set to evaluate, chosen implicitly by the client when it
170 */ 187 * calls #GNUNE_SET_commit().
171 uint32_t salt GNUNET_PACKED;
172
173 /**
174 * How should results be sent to us?
175 * See `enum GNUNET_SET_ResultMode`.
176 */ 188 */
177 uint32_t result_mode GNUNET_PACKED; 189 uint32_t request_id GNUNET_PACKED;
178 190
179 /* rest: inner message */ 191 /* rest: context message, that is, application-specific
192 message to convince listener to pick up */
180}; 193};
181 194
182 195
@@ -207,6 +220,10 @@ struct GNUNET_SET_ResultMessage
207}; 220};
208 221
209 222
223/**
224 * Message sent by client to the service to add or remove
225 * an element to/from the set.
226 */
210struct GNUNET_SET_ElementMessage 227struct GNUNET_SET_ElementMessage
211{ 228{
212 /** 229 /**
@@ -215,8 +232,14 @@ struct GNUNET_SET_ElementMessage
215 */ 232 */
216 struct GNUNET_MessageHeader header; 233 struct GNUNET_MessageHeader header;
217 234
235 /**
236 * Type of the element to add or remove.
237 */
218 uint16_t element_type GNUNET_PACKED; 238 uint16_t element_type GNUNET_PACKED;
219 239
240 /**
241 * For alignment, always zero.
242 */
220 uint16_t reserved GNUNET_PACKED; 243 uint16_t reserved GNUNET_PACKED;
221 244
222 /* rest: the actual element */ 245 /* rest: the actual element */
diff --git a/src/set/set_api.c b/src/set/set_api.c
index 1ef0cc50c..ff0c959e4 100644
--- a/src/set/set_api.c
+++ b/src/set/set_api.c
@@ -325,14 +325,14 @@ handle_request (void *cls,
325 const struct GNUNET_SET_RequestMessage *msg = (const struct GNUNET_SET_RequestMessage *) mh; 325 const struct GNUNET_SET_RequestMessage *msg = (const struct GNUNET_SET_RequestMessage *) mh;
326 struct GNUNET_SET_ListenHandle *lh = cls; 326 struct GNUNET_SET_ListenHandle *lh = cls;
327 struct GNUNET_SET_Request *req; 327 struct GNUNET_SET_Request *req;
328 struct GNUNET_MessageHeader *context_msg; 328 const struct GNUNET_MessageHeader *context_msg;
329 329
330 LOG (GNUNET_ERROR_TYPE_DEBUG, 330 LOG (GNUNET_ERROR_TYPE_DEBUG,
331 "processing operation request\n"); 331 "processing operation request\n");
332 req = GNUNET_new (struct GNUNET_SET_Request); 332 req = GNUNET_new (struct GNUNET_SET_Request);
333 req->accept_id = ntohl (msg->accept_id); 333 req->accept_id = ntohl (msg->accept_id);
334 context_msg = GNUNET_MQ_extract_nested_mh (msg); 334 context_msg = GNUNET_MQ_extract_nested_mh (msg);
335 /* calling GNUNET_SET_accept in the listen cb will set req->accepted */ 335 /* calling #GNUNET_SET_accept() in the listen cb will set req->accepted */
336 lh->listen_cb (lh->listen_cls, &msg->peer_id, context_msg, req); 336 lh->listen_cb (lh->listen_cls, &msg->peer_id, context_msg, req);
337 337
338 /* we got another request => reset the backoff */ 338 /* we got another request => reset the backoff */
@@ -345,8 +345,6 @@ handle_request (void *cls,
345 345
346 mqm = GNUNET_MQ_msg (rmsg, 346 mqm = GNUNET_MQ_msg (rmsg,
347 GNUNET_MESSAGE_TYPE_SET_REJECT); 347 GNUNET_MESSAGE_TYPE_SET_REJECT);
348 /* no request id, as we refused */
349 rmsg->request_id = htonl (0);
350 rmsg->accept_reject_id = msg->accept_id; 348 rmsg->accept_reject_id = msg->accept_id;
351 GNUNET_MQ_send (lh->mq, mqm); 349 GNUNET_MQ_send (lh->mq, mqm);
352 LOG (GNUNET_ERROR_TYPE_DEBUG, 350 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -363,7 +361,8 @@ handle_request (void *cls,
363 361
364 362
365static void 363static void
366handle_client_listener_error (void *cls, enum GNUNET_MQ_Error error) 364handle_client_listener_error (void *cls,
365 enum GNUNET_MQ_Error error)
367{ 366{
368 struct GNUNET_SET_ListenHandle *lh = cls; 367 struct GNUNET_SET_ListenHandle *lh = cls;
369 368
@@ -639,7 +638,6 @@ GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
639 oh = GNUNET_new (struct GNUNET_SET_OperationHandle); 638 oh = GNUNET_new (struct GNUNET_SET_OperationHandle);
640 oh->result_cb = result_cb; 639 oh->result_cb = result_cb;
641 oh->result_cls = result_cls; 640 oh->result_cls = result_cls;
642
643 mqm = GNUNET_MQ_msg_nested_mh (msg, 641 mqm = GNUNET_MQ_msg_nested_mh (msg,
644 GNUNET_MESSAGE_TYPE_SET_EVALUATE, 642 GNUNET_MESSAGE_TYPE_SET_EVALUATE,
645 context_msg); 643 context_msg);
@@ -825,7 +823,9 @@ GNUNET_SET_commit (struct GNUNET_SET_OperationHandle *oh,
825 return GNUNET_SYSERR; 823 return GNUNET_SYSERR;
826 GNUNET_assert (NULL != oh->conclude_mqm); 824 GNUNET_assert (NULL != oh->conclude_mqm);
827 oh->set = set; 825 oh->set = set;
828 GNUNET_CONTAINER_DLL_insert (set->ops_head, set->ops_tail, oh); 826 GNUNET_CONTAINER_DLL_insert (set->ops_head,
827 set->ops_tail,
828 oh);
829 oh->request_id = GNUNET_MQ_assoc_add (set->mq, oh); 829 oh->request_id = GNUNET_MQ_assoc_add (set->mq, oh);
830 *oh->request_id_addr = htonl (oh->request_id); 830 *oh->request_id_addr = htonl (oh->request_id);
831 GNUNET_MQ_send (set->mq, oh->conclude_mqm); 831 GNUNET_MQ_send (set->mq, oh->conclude_mqm);