diff options
Diffstat (limited to 'src/namestore/plugin_rest_namestore.c')
-rw-r--r-- | src/namestore/plugin_rest_namestore.c | 214 |
1 files changed, 161 insertions, 53 deletions
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index d93b2e185..7a5a70fca 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c | |||
@@ -35,11 +35,16 @@ | |||
35 | #include <jansson.h> | 35 | #include <jansson.h> |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * Namestore Namespace | 38 | * Namestore namespace |
39 | */ | 39 | */ |
40 | #define GNUNET_REST_API_NS_NAMESTORE "/namestore" | 40 | #define GNUNET_REST_API_NS_NAMESTORE "/namestore" |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * Namestore import API namespace | ||
44 | */ | ||
45 | #define GNUNET_REST_API_NS_NAMESTORE_IMPORT "/namestore/import" | ||
46 | |||
47 | /** | ||
43 | * Error message Unknown Error | 48 | * Error message Unknown Error |
44 | */ | 49 | */ |
45 | #define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error" | 50 | #define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error" |
@@ -196,11 +201,31 @@ struct RequestHandle | |||
196 | unsigned int rd_count; | 201 | unsigned int rd_count; |
197 | 202 | ||
198 | /** | 203 | /** |
204 | * RecordInfo array | ||
205 | */ | ||
206 | struct GNUNET_NAMESTORE_RecordInfo *ri; | ||
207 | |||
208 | /** | ||
209 | * Size of record info | ||
210 | */ | ||
211 | unsigned int rd_set_count; | ||
212 | |||
213 | /** | ||
214 | * Position of record info | ||
215 | */ | ||
216 | unsigned int rd_set_pos; | ||
217 | |||
218 | /** | ||
199 | * NAMESTORE Operation | 219 | * NAMESTORE Operation |
200 | */ | 220 | */ |
201 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | 221 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; |
202 | 222 | ||
203 | /** | 223 | /** |
224 | * For bulk import, we need a dedicated Namestore handle | ||
225 | */ | ||
226 | struct GNUNET_NAMESTORE_Handle *nc; | ||
227 | |||
228 | /** | ||
204 | * Response object | 229 | * Response object |
205 | */ | 230 | */ |
206 | json_t *resp_object; | 231 | json_t *resp_object; |
@@ -314,7 +339,8 @@ cleanup_handle (void *cls) | |||
314 | GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); | 339 | GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); |
315 | if (NULL != handle->ns_qe) | 340 | if (NULL != handle->ns_qe) |
316 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | 341 | GNUNET_NAMESTORE_cancel (handle->ns_qe); |
317 | 342 | if (NULL != handle->nc) | |
343 | GNUNET_NAMESTORE_disconnect (handle->nc); | ||
318 | if (NULL != handle->resp_object) | 344 | if (NULL != handle->resp_object) |
319 | { | 345 | { |
320 | json_decref (handle->resp_object); | 346 | json_decref (handle->resp_object); |
@@ -721,20 +747,16 @@ ns_lookup_cb (void *cls, | |||
721 | } | 747 | } |
722 | } | 748 | } |
723 | 749 | ||
724 | /** | 750 | |
725 | * Import callback | ||
726 | * | ||
727 | * @param cls the `struct RequestHandle` | ||
728 | * @param success the success indicating integer, GNUNET_OK on success | ||
729 | * @param emsg the error message (can be NULL) | ||
730 | */ | ||
731 | static void | 751 | static void |
732 | import_finished_cb (void *cls, int32_t success, const char *emsg) | 752 | bulk_tx_commit_cb (void *cls, int32_t success, const char *emsg) |
733 | { | 753 | { |
734 | struct RequestHandle *handle = cls; | 754 | struct RequestHandle *handle = cls; |
735 | struct MHD_Response *resp; | 755 | struct MHD_Response *resp; |
736 | 756 | ||
737 | handle->ns_qe = NULL; | 757 | handle->ns_qe = NULL; |
758 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
759 | "Commit finished, %d\n", success); | ||
738 | if (GNUNET_YES != success) | 760 | if (GNUNET_YES != success) |
739 | { | 761 | { |
740 | if (NULL != emsg) | 762 | if (NULL != emsg) |
@@ -743,7 +765,7 @@ import_finished_cb (void *cls, int32_t success, const char *emsg) | |||
743 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 765 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
744 | return; | 766 | return; |
745 | } | 767 | } |
746 | handle->emsg = GNUNET_strdup ("Error importing records"); | 768 | handle->emsg = GNUNET_strdup ("Error importing records on commit"); |
747 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 769 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
748 | return; | 770 | return; |
749 | } | 771 | } |
@@ -754,45 +776,69 @@ import_finished_cb (void *cls, int32_t success, const char *emsg) | |||
754 | 776 | ||
755 | 777 | ||
756 | /** | 778 | /** |
757 | * Handle namestore POST import | 779 | * Import callback |
758 | * | 780 | * |
759 | * @param con_handle the connection handle | 781 | * @param cls the `struct RequestHandle` |
760 | * @param url the url | 782 | * @param success the success indicating integer, GNUNET_OK on success |
761 | * @param cls the RequestHandle | 783 | * @param emsg the error message (can be NULL) |
762 | */ | 784 | */ |
763 | void | 785 | static void |
764 | namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | 786 | import_next_cb (void *cls, int32_t success, const char *emsg) |
765 | const char *url, | ||
766 | void *cls) | ||
767 | { | 787 | { |
768 | struct RequestHandle *handle = cls; | 788 | struct RequestHandle *handle = cls; |
769 | struct EgoEntry *ego_entry; | ||
770 | char *egoname; | ||
771 | json_t *data_js; | ||
772 | json_error_t err; | ||
773 | 789 | ||
774 | char term_data[handle->rest_handle->data_size + 1]; | 790 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
775 | // set zone to name if given | 791 | "Import finished, %d\n", success); |
776 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | 792 | handle->ns_qe = NULL; |
793 | if (GNUNET_YES != success) | ||
777 | { | 794 | { |
778 | handle->response_code = MHD_HTTP_NOT_FOUND; | 795 | if (NULL != emsg) |
779 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | 796 | { |
797 | handle->emsg = GNUNET_strdup (emsg); | ||
798 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
799 | return; | ||
800 | } | ||
801 | handle->emsg = GNUNET_strdup ("Error importing records"); | ||
780 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 802 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
781 | return; | 803 | return; |
782 | } | 804 | } |
783 | ego_entry = NULL; | 805 | unsigned int remaining = handle->rd_set_count - handle->rd_set_pos; |
784 | 806 | if (0 == remaining) | |
785 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
786 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
787 | |||
788 | if (NULL == ego_entry) | ||
789 | { | 807 | { |
790 | handle->response_code = MHD_HTTP_NOT_FOUND; | 808 | handle->ns_qe = GNUNET_NAMESTORE_transaction_commit (handle->nc, |
791 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | 809 | &bulk_tx_commit_cb, |
810 | handle); | ||
811 | return; | ||
812 | } | ||
813 | unsigned int sent_rds = 0; | ||
814 | // Find the smallest set of records we can send with our message size | ||
815 | // restriction of 16 bit | ||
816 | handle->ns_qe = GNUNET_NAMESTORE_records_store2 (handle->nc, | ||
817 | handle->zone_pkey, | ||
818 | remaining, | ||
819 | &handle->ri[handle-> | ||
820 | rd_set_pos], | ||
821 | &sent_rds, | ||
822 | &import_next_cb, | ||
823 | handle); | ||
824 | if ((NULL == handle->ns_qe) && (0 == sent_rds)) | ||
825 | { | ||
826 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
792 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 827 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
793 | return; | 828 | return; |
794 | } | 829 | } |
830 | handle->rd_set_pos += sent_rds; | ||
831 | } | ||
832 | |||
833 | static void | ||
834 | bulk_tx_start (void *cls, int32_t success, const char *emsg) | ||
835 | { | ||
836 | struct RequestHandle *handle = cls; | ||
837 | json_t *data_js; | ||
838 | json_error_t err; | ||
795 | 839 | ||
840 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
841 | "Transaction started...\n"); | ||
796 | if (0 >= handle->rest_handle->data_size) | 842 | if (0 >= handle->rest_handle->data_size) |
797 | { | 843 | { |
798 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 844 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
@@ -800,6 +846,7 @@ namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | |||
800 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 846 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
801 | return; | 847 | return; |
802 | } | 848 | } |
849 | char term_data[handle->rest_handle->data_size + 1]; | ||
803 | term_data[handle->rest_handle->data_size] = '\0'; | 850 | term_data[handle->rest_handle->data_size] = '\0'; |
804 | GNUNET_memcpy (term_data, | 851 | GNUNET_memcpy (term_data, |
805 | handle->rest_handle->data, | 852 | handle->rest_handle->data, |
@@ -818,11 +865,11 @@ namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | |||
818 | json_decref (data_js); | 865 | json_decref (data_js); |
819 | return; | 866 | return; |
820 | } | 867 | } |
821 | size_t rd_set_count = json_array_size (data_js); | 868 | handle->rd_set_count = json_array_size (data_js); |
822 | struct GNUNET_NAMESTORE_RecordInfo ri[rd_set_count]; | 869 | handle->ri = GNUNET_malloc (handle->rd_set_count |
870 | * sizeof (struct GNUNET_NAMESTORE_RecordInfo)); | ||
823 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 871 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
824 | "Got record set of size %d\n", rd_set_count); | 872 | "Got record set of size %d\n", handle->rd_set_count); |
825 | const struct GNUNET_GNSRECORD_Data *a_rd[rd_set_count]; | ||
826 | char *albl; | 873 | char *albl; |
827 | size_t index; | 874 | size_t index; |
828 | json_t *value; | 875 | json_t *value; |
@@ -830,7 +877,8 @@ namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | |||
830 | { | 877 | { |
831 | struct GNUNET_GNSRECORD_Data *rd; | 878 | struct GNUNET_GNSRECORD_Data *rd; |
832 | struct GNUNET_JSON_Specification gnsspec[] = | 879 | struct GNUNET_JSON_Specification gnsspec[] = |
833 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&rd, &ri[index].a_rd_count, | 880 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&rd, |
881 | &handle->ri[index].a_rd_count, | ||
834 | &albl), | 882 | &albl), |
835 | GNUNET_JSON_spec_end () }; | 883 | GNUNET_JSON_spec_end () }; |
836 | if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL)) | 884 | if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL)) |
@@ -840,27 +888,86 @@ namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | |||
840 | json_decref (data_js); | 888 | json_decref (data_js); |
841 | return; | 889 | return; |
842 | } | 890 | } |
843 | ri[index].a_rd = rd; | 891 | handle->ri[index].a_rd = rd; |
844 | ri[index].a_label = albl; | 892 | handle->ri[index].a_label = albl; |
845 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 893 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
846 | "Parsed record set for name %s\n", ri[index].a_label); | 894 | "Parsed record set for name %s\n", |
895 | handle->ri[index].a_label); | ||
847 | } | 896 | } |
848 | } | 897 | } |
849 | //json_decref (data_js); | 898 | // json_decref (data_js); |
850 | 899 | ||
851 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | 900 | unsigned int sent_rds = 0; |
852 | handle->ns_qe = GNUNET_NAMESTORE_records_store2 (ns_handle, | 901 | // Find the smallest set of records we can send with our message size |
902 | // restriction of 16 bit | ||
903 | handle->ns_qe = GNUNET_NAMESTORE_records_store2 (handle->nc, | ||
853 | handle->zone_pkey, | 904 | handle->zone_pkey, |
854 | rd_set_count, | 905 | handle->rd_set_count, |
855 | ri, | 906 | handle->ri, |
856 | &import_finished_cb, | 907 | &sent_rds, |
908 | &import_next_cb, | ||
857 | handle); | 909 | handle); |
858 | if (NULL == handle->ns_qe) | 910 | if ((NULL == handle->ns_qe) && (0 == sent_rds)) |
859 | { | 911 | { |
860 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | 912 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); |
861 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 913 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
862 | return; | 914 | return; |
863 | } | 915 | } |
916 | handle->rd_set_pos += sent_rds; | ||
917 | } | ||
918 | |||
919 | |||
920 | /** | ||
921 | * Handle namestore POST import | ||
922 | * | ||
923 | * @param con_handle the connection handle | ||
924 | * @param url the url | ||
925 | * @param cls the RequestHandle | ||
926 | */ | ||
927 | void | ||
928 | namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | ||
929 | const char *url, | ||
930 | void *cls) | ||
931 | { | ||
932 | struct RequestHandle *handle = cls; | ||
933 | struct EgoEntry *ego_entry; | ||
934 | char *egoname; | ||
935 | |||
936 | // set zone to name if given | ||
937 | if (strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1 >= strlen ( | ||
938 | handle->url)) | ||
939 | { | ||
940 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
941 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
942 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
943 | return; | ||
944 | } | ||
945 | ego_entry = NULL; | ||
946 | |||
947 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1]; | ||
948 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
949 | |||
950 | if (NULL == ego_entry) | ||
951 | { | ||
952 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
953 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
954 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
955 | return; | ||
956 | } | ||
957 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
958 | |||
959 | // We need a per-client connection for a transactional bulk import | ||
960 | handle->nc = GNUNET_NAMESTORE_connect (cfg); | ||
961 | if (NULL == handle->nc) | ||
962 | { | ||
963 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
964 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DATA); | ||
965 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
966 | return; | ||
967 | } | ||
968 | handle->ns_qe = GNUNET_NAMESTORE_transaction_begin (handle->nc, | ||
969 | &bulk_tx_start, | ||
970 | handle); | ||
864 | } | 971 | } |
865 | 972 | ||
866 | /** | 973 | /** |
@@ -1183,8 +1290,9 @@ rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | |||
1183 | struct GNUNET_REST_RequestHandlerError err; | 1290 | struct GNUNET_REST_RequestHandlerError err; |
1184 | static const struct GNUNET_REST_RequestHandler handlers[] = | 1291 | static const struct GNUNET_REST_RequestHandler handlers[] = |
1185 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get }, | 1292 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get }, |
1186 | //{ MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add }, | 1293 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE_IMPORT, |
1187 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_import }, | 1294 | &namestore_import }, |
1295 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add }, | ||
1188 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update }, | 1296 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update }, |
1189 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, | 1297 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, |
1190 | &namestore_delete }, | 1298 | &namestore_delete }, |